Skip to content

Commit

Permalink
Merge pull request #74 from Gottox/fix/open-corrupt-direntry
Browse files Browse the repository at this point in the history
directory_iterator: consistency check on open
  • Loading branch information
Gottox committed Aug 27, 2023
2 parents 9b8ec2c + b6d0ff4 commit a3b5154
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 2 deletions.
39 changes: 37 additions & 2 deletions lib/directory/directory_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ load_metablock(
}

static int
check_consistency(struct SqshDirectoryIterator *iterator) {
check_consistency(const struct SqshDirectoryIterator *iterator) {
const char *name = sqsh_directory_iterator_name(iterator);
const size_t name_len = sqsh_directory_iterator_name_size(iterator);

Expand Down Expand Up @@ -269,13 +269,48 @@ sqsh_directory_iterator_file_type(
return SQSH_FILE_TYPE_UNKNOWN;
}

static int
check_file_consistency(
const struct SqshDirectoryIterator *iterator,
const struct SqshFile *file) {
const uint64_t file_inode = sqsh_file_inode(file);
const uint64_t iter_inode = sqsh_directory_iterator_inode_number(iterator);
if (iter_inode != file_inode) {
return -SQSH_ERROR_CORRUPTED_DIRECTORY_ENTRY;
}

enum SqshFileType file_type = sqsh_file_type(file);
enum SqshFileType iter_type = sqsh_directory_iterator_file_type(iterator);
if (iter_type != file_type) {
return -SQSH_ERROR_CORRUPTED_DIRECTORY_ENTRY;
}
return 0;
}

struct SqshFile *
sqsh_directory_iterator_open_file(
const struct SqshDirectoryIterator *iterator, int *err) {
int rv = 0;
struct SqshFile *file = NULL;
const uint64_t inode_ref = sqsh_directory_iterator_inode_ref(iterator);
struct SqshArchive *archive = iterator->file->archive;

return sqsh_open_by_ref(archive, inode_ref, err);
file = sqsh_open_by_ref(archive, inode_ref, &rv);
if (file == NULL) {
goto out;
}

rv = check_file_consistency(iterator, file);

out:
if (rv < 0) {
sqsh_close(file);
file = NULL;
}
if (err != NULL) {
*err = rv;
}
return file;
}

static int
Expand Down
46 changes: 46 additions & 0 deletions test/directory/directory_iterator.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,55 @@ iter_invalid_file_type(void) {
sqsh__archive_cleanup(&archive);
}

static void
iter_inconsistent_file_type(void) {
int rv;
struct SqshArchive archive = {0};
uint8_t payload[] = {
/* clang-format off */
SQSH_HEADER,
/* 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',
[DIRECTORY_TABLE_OFFSET] = METABLOCK_HEADER(0, 128),
DIRECTORY_HEADER(2, 0, 0),
DIRECTORY_ENTRY(128, 2, 1, 1),
'1',
[FRAGMENT_TABLE_OFFSET] = 0,
/* clang-format on */
};
mk_stub(&archive, payload, sizeof(payload));

struct SqshFile file = {0};
rv = sqsh__file_init(&file, &archive, 0);
assert(rv == 0);

struct SqshDirectoryIterator *iter =
sqsh_directory_iterator_new(&file, &rv);
assert(rv == 0);

bool has_next = sqsh_directory_iterator_next(iter, &rv);
assert(rv == 0);
assert(has_next == true);

struct SqshFile *entry_file = sqsh_directory_iterator_open_file(iter, &rv);
assert(rv == -SQSH_ERROR_CORRUPTED_DIRECTORY_ENTRY);
assert(entry_file == NULL);

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

DECLARE_TESTS
TEST(iter_two_files)
TEST(iter_invalid_file_name_with_slash)
TEST(iter_invalid_file_name_with_0)
TEST(iter_invalid_file_type)
TEST(iter_inconsistent_file_type)
END_TESTS

0 comments on commit a3b5154

Please sign in to comment.