Skip to content

Commit

Permalink
Merge pull request #291 from Gottox/fix/sqsh-config-oob
Browse files Browse the repository at this point in the history
Fix/sqsh config oob
  • Loading branch information
Gottox authored Aug 17, 2024
2 parents cccc583 + face878 commit 5f998a2
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 122 deletions.
3 changes: 2 additions & 1 deletion libsqsh/src/archive/archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ sqsh__archive_init(
memset(&archive->map_manager, 0, sizeof(struct SqshMapManager));

if (config != NULL) {
memcpy(&archive->config, config, sizeof(struct SqshConfig));
memcpy(&archive->config, config,
offsetof(struct SqshConfig, _reserved));
} else {
memset(&archive->config, 0, sizeof(struct SqshConfig));
}
Expand Down
161 changes: 40 additions & 121 deletions test/libsqsh/archive/archive.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,127 +40,46 @@
#include <sqsh_data_private.h>
#include <sqsh_file_private.h>

UTEST(file, load_file) {
int rv;
struct SqshArchive archive = {0};
struct SqshFile file = {0};
uint8_t payload[8192] = {
SQSH_HEADER,
/* inode */
[INODE_TABLE_OFFSET + 15] = METABLOCK_HEADER(0, 128),
0,
0,
0,
INODE_HEADER(2, 0666, 0, 0, 4242, 1),
INODE_BASIC_FILE(1024, 0xFFFFFFFF, 0, 1),
UINT32_BYTES(42),

};
mk_stub(&archive, payload, sizeof(payload));

uint64_t inode_ref = sqsh_address_ref_create(15, 3);
rv = sqsh__file_init(&file, &archive, inode_ref);
ASSERT_EQ(0, rv);

ASSERT_EQ(SQSH_FILE_TYPE_FILE, sqsh_file_type(&file));
ASSERT_EQ(0666, sqsh_file_permission(&file));
ASSERT_EQ((uint32_t)4242, sqsh_file_modified_time(&file));
ASSERT_EQ((uint32_t)1024, sqsh_file_blocks_start(&file));
ASSERT_EQ(false, sqsh_file_has_fragment(&file));

ASSERT_EQ((uint32_t)1, sqsh_file_block_count(&file));
ASSERT_EQ((uint32_t)42, sqsh_file_block_size(&file, 0));

sqsh__file_cleanup(&file);
sqsh__archive_cleanup(&archive);
}

UTEST(file, resolve_file) {
int rv = 0;
struct SqshArchive archive = {0};
uint8_t payload[] = {
/* clang-format off */
SQSH_HEADER,
[1024] = '1', '2', '3', '4', '5', '6', '7', '8',
/* inode */
[INODE_TABLE_OFFSET] = METABLOCK_HEADER(0, 1024),
INODE_HEADER(1, 0, 0, 0, 0, 1),
INODE_BASIC_DIR(0, 1024, 0, 0),
[INODE_TABLE_OFFSET+2+128] =
INODE_HEADER(3, 0, 0, 0, 0, 2),
INODE_BASIC_SYMLINK(3),
't', 'g', 't',
[INODE_TABLE_OFFSET+2+256] =
INODE_HEADER(2, 0, 0, 0, 0, 3),
INODE_BASIC_FILE(1024, 0xFFFFFFFF, 0, 8),
DATA_BLOCK_REF(8, 0),
[DIRECTORY_TABLE_OFFSET] = METABLOCK_HEADER(0, 128),
DIRECTORY_HEADER(2, 0, 0),
DIRECTORY_ENTRY(128, 2, 3, 3),
's', 'r', 'c',
DIRECTORY_ENTRY(256, 3, 2, 3),
't', 'g', 't',
[FRAGMENT_TABLE_OFFSET] = 0,
/* clang-format on */
};
mk_stub(&archive, payload, sizeof(payload));

struct SqshFile *symlink = sqsh_lopen(&archive, "/src", &rv);
ASSERT_EQ(0, rv);
ASSERT_EQ(SQSH_FILE_TYPE_SYMLINK, sqsh_file_type(symlink));

rv = sqsh_file_symlink_resolve(symlink);
ASSERT_EQ(0, rv);
ASSERT_EQ(SQSH_FILE_TYPE_FILE, sqsh_file_type(symlink));
ASSERT_EQ((uint32_t)3, sqsh_file_inode(symlink));

sqsh_close(symlink);

sqsh__archive_cleanup(&archive);
}

UTEST(file, resolve_unkown_dir_inode) {
int rv = 0;
struct SqshArchive archive = {0};
uint8_t payload[] = {
/* clang-format off */
SQSH_HEADER,
[1024] = '1', '2', '3', '4', '5', '6', '7', '8',
/* inode */
[INODE_TABLE_OFFSET] = METABLOCK_HEADER(0, 1024),
INODE_HEADER(1, 0, 0, 0, 0, 1),
INODE_BASIC_DIR(0, 1024, 0, 0),
[INODE_TABLE_OFFSET+2+128] =
INODE_HEADER(3, 0, 0, 0, 0, 2),
INODE_BASIC_SYMLINK(3),
't', 'g', 't',
[INODE_TABLE_OFFSET+2+256] =
INODE_HEADER(2, 0, 0, 0, 0, 3),
INODE_BASIC_FILE(1024, 0xFFFFFFFF, 0, 8),
DATA_BLOCK_REF(8, 0),
[DIRECTORY_TABLE_OFFSET] = METABLOCK_HEADER(0, 128),
DIRECTORY_HEADER(2, 0, 0),
DIRECTORY_ENTRY(128, 2, 3, 3),
's', 'r', 'c',
DIRECTORY_ENTRY(256, 3, 2, 3),
't', 'g', 't',
[FRAGMENT_TABLE_OFFSET] = 0,
/* clang-format on */
};
mk_stub(&archive, payload, sizeof(payload));

struct SqshFile *symlink = sqsh_lopen(&archive, "/src", &rv);
ASSERT_EQ(0, rv);
ASSERT_EQ(SQSH_FILE_TYPE_SYMLINK, sqsh_file_type(symlink));
symlink->dir_inode = 0;
symlink->has_dir_inode = false;

rv = sqsh_file_symlink_resolve(symlink);
ASSERT_EQ(-SQSH_ERROR_INODE_PARENT_UNSET, rv);

sqsh_close(symlink);

sqsh__archive_cleanup(&archive);
// The SqshConfig struct as it was in version 1.0. This is used to perform ABI
// compatibility checks.

struct SqshConfigV1_0 {
uint64_t archive_offset;
uint64_t source_size;
const struct SqshMemoryMapperImpl *source_mapper;
int mapper_block_size;
int mapper_lru_size;
int compression_lru_size;
size_t max_symlink_depth;
char _reserved[128];
};

UTEST(config, config_compat_check_v1_0) {
ASSERT_EQ(
offsetof(struct SqshConfig, archive_offset),
offsetof(struct SqshConfigV1_0, archive_offset));
ASSERT_EQ(
offsetof(struct SqshConfig, source_size),
offsetof(struct SqshConfigV1_0, source_size));
ASSERT_EQ(
offsetof(struct SqshConfig, source_mapper),
offsetof(struct SqshConfigV1_0, source_mapper));
ASSERT_EQ(
offsetof(struct SqshConfig, mapper_block_size),
offsetof(struct SqshConfigV1_0, mapper_block_size));
ASSERT_EQ(
offsetof(struct SqshConfig, mapper_lru_size),
offsetof(struct SqshConfigV1_0, mapper_lru_size));
ASSERT_EQ(
offsetof(struct SqshConfig, compression_lru_size),
offsetof(struct SqshConfigV1_0, compression_lru_size));
ASSERT_EQ(
offsetof(struct SqshConfig, max_symlink_depth),
offsetof(struct SqshConfigV1_0, max_symlink_depth));

ASSERT_LT(
offsetof(struct SqshConfig, _reserved),
sizeof(struct SqshConfigV1_0));
}

UTEST_MAIN()
1 change: 1 addition & 0 deletions test/libsqsh/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_languages('cpp', native: false)
sqsh_test = [
'check_version.c',
'cpp-test.cpp',
'archive/archive.c',
'archive/compression_options.c',
'archive/inode_map.c',
'directory/directory_iterator.c',
Expand Down

0 comments on commit 5f998a2

Please sign in to comment.