Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion extras/backends/pak/fs_pak.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ static fs_bool32 fs_iterator_item_exists_pak(fs_iterator_pak* pIteratorPak, cons
fs_uint32 i;

for (i = 0; i < pIteratorPak->count; i += 1) {
if (fs_strncmp(pIteratorPak->items[i].name, pName, nameLen) == 0) {
if (strlen(pIteratorPak->items[i].name) == nameLen && fs_strncmp(pIteratorPak->items[i].name, pName, nameLen) == 0) {
return FS_TRUE;
}
}
Expand Down
28 changes: 16 additions & 12 deletions fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2102,18 +2102,22 @@ static fs_opened_archive* fs_find_opened_archive(fs* pFS, const char* pArchivePa
}

FS_ASSERT(pArchivePath != NULL);
FS_ASSERT(archivePathLen > 0);
FS_ASSERT(archivePathLen != 0);

if (archivePathLen == FS_NULL_TERMINATED) {
archivePathLen = strlen(pArchivePath);
}

cursor = 0;
while (cursor < pFS->openedArchivesSize) {
fs_opened_archive* pOpenedArchive = (fs_opened_archive*)FS_OFFSET_PTR(pFS->pOpenedArchives, cursor);

if (fs_strncmp(pOpenedArchive->pPath, pArchivePath, archivePathLen) == 0) {
if (strlen(pOpenedArchive->pPath) == archivePathLen && fs_strncmp(pOpenedArchive->pPath, pArchivePath, archivePathLen) == 0) {
return pOpenedArchive;
}

/* Getting here means this archive is not the one we're looking for. */
cursor += FS_ALIGN(sizeof(fs*) + sizeof(size_t) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
cursor += FS_ALIGN(sizeof(pOpenedArchive->pArchive) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
}

/* If we get here it means we couldn't find the archive by it's name. */
Expand All @@ -2140,7 +2144,7 @@ static fs_opened_archive* fs_find_opened_archive_by_fs(fs* pFS, fs* pArchive)
}

/* Getting here means this archive is not the one we're looking for. */
cursor += FS_ALIGN(sizeof(fs*) + sizeof(size_t) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
cursor += FS_ALIGN(sizeof(pOpenedArchive->pArchive) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
}

/* If we get here it means we couldn't find the archive. */
Expand All @@ -2161,7 +2165,7 @@ static fs_result fs_add_opened_archive(fs* pFS, fs* pArchive, const char* pArchi
archivePathLen = strlen(pArchivePath);
}

openedArchiveSize = FS_ALIGN(sizeof(fs*) + sizeof(size_t) + archivePathLen + 1, FS_SIZEOF_PTR);
openedArchiveSize = FS_ALIGN(sizeof(pOpenedArchive->pArchive) + archivePathLen + 1, FS_SIZEOF_PTR);

if (pFS->openedArchivesSize + openedArchiveSize > pFS->openedArchivesCap) {
size_t newOpenedArchivesCap;
Expand Down Expand Up @@ -2198,7 +2202,7 @@ static fs_result fs_remove_opened_archive(fs* pFS, fs_opened_archive* pOpenedArc
/* This is a simple matter of doing a memmove() to move memory down. pOpenedArchive should be an offset of pFS->pOpenedArchives. */
size_t openedArchiveSize;

openedArchiveSize = FS_ALIGN(sizeof(fs_opened_archive*) + sizeof(size_t) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
openedArchiveSize = FS_ALIGN(sizeof(pOpenedArchive->pArchive) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);

FS_ASSERT(((fs_uintptr)pOpenedArchive + openedArchiveSize) > ((fs_uintptr)pFS->pOpenedArchives));
FS_ASSERT(((fs_uintptr)pOpenedArchive + openedArchiveSize) <= ((fs_uintptr)pFS->pOpenedArchives + pFS->openedArchivesSize));
Expand Down Expand Up @@ -3991,7 +3995,7 @@ static void fs_iterator_internal_resolve_public_members(fs_iterator_internal* pI
pIterator->base.info = pIterator->ppItems[pIterator->itemIndex]->info;
}

static fs_iterator_item* fs_iterator_internal_find(fs_iterator_internal* pIterator, const char* pName)
static fs_iterator_item* fs_iterator_internal_find(fs_iterator_internal* pIterator, const char* pName, size_t nameLen)
{
/*
We cannot use ppItems here because this function will be called before that has been set up. Instead we need
Expand All @@ -4002,7 +4006,7 @@ static fs_iterator_item* fs_iterator_internal_find(fs_iterator_internal* pIterat

for (iItem = 0; iItem < pIterator->itemCount; iItem += 1) {
fs_iterator_item* pItem = (fs_iterator_item*)FS_OFFSET_PTR(pIterator, sizeof(fs_iterator_internal) + cursor);
if (fs_strncmp(fs_iterator_item_name(pItem), pName, pItem->nameLen) == 0) {
if (pItem->nameLen == nameLen && fs_strncmp(fs_iterator_item_name(pItem), pName, pItem->nameLen) == 0) {
return pItem;
}

Expand Down Expand Up @@ -4031,7 +4035,7 @@ static fs_iterator_internal* fs_iterator_internal_append(fs_iterator_internal* p

/* Check if the item already exists. If so, skip it. */
if (pIterator != NULL) {
pNewItem = fs_iterator_internal_find(pIterator, pOther->pName);
pNewItem = fs_iterator_internal_find(pIterator, pOther->pName, pOther->nameLen);
if (pNewItem != NULL) {
return pIterator; /* Already exists. Skip it. */
}
Expand Down Expand Up @@ -4672,7 +4676,7 @@ static void fs_gc_nolock(fs* pFS, int policy, fs* pSpecificArchive)
FS_ASSERT(pOpenedArchive != NULL);

fs_gc_archives(pOpenedArchive->pArchive, policy);
cursor += FS_ALIGN(sizeof(fs*) + sizeof(size_t) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
cursor += FS_ALIGN(sizeof(pOpenedArchive->pArchive) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
}
}
}
Expand All @@ -4696,7 +4700,7 @@ static void fs_gc_nolock(fs* pFS, int policy, fs* pSpecificArchive)
}
}

cursor += FS_ALIGN(sizeof(fs*) + sizeof(size_t) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
cursor += FS_ALIGN(sizeof(pOpenedArchive->pArchive) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
}

/* Determine how many archives to collect. */
Expand Down Expand Up @@ -4728,7 +4732,7 @@ static void fs_gc_nolock(fs* pFS, int policy, fs* pSpecificArchive)
collectionCount -= 1;
/* Note that we're not advancing the cursor here because we just removed this entry. */
} else {
cursor += FS_ALIGN(sizeof(fs*) + sizeof(size_t) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
cursor += FS_ALIGN(sizeof(pOpenedArchive->pArchive) + strlen(pOpenedArchive->pPath) + 1, FS_SIZEOF_PTR);
}
}
}
Expand Down
83 changes: 82 additions & 1 deletion tests/fs_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -2180,6 +2180,85 @@ int fs_test_mounts_iteration(fs_test* pTest)

return FS_SUCCESS;
}

int fs_test_mounts_iteration_prefix_bug(fs_test* pTest)
{
fs_test_state* pTestState = (fs_test_state*)pTest->pUserData;
fs_result result;
fs_iterator* pIterator;
fs_config memConfig;
fs* pMem1;
fs* pMem2;
fs_file* pFile;
int count = 0;
fs_bool32 found1 = FS_FALSE;
fs_bool32 found2 = FS_FALSE;

/* We'll use the memory file system for this to avoid any dependencies on the physical disk. */
memConfig = fs_config_init(FS_MEM, NULL, NULL);

result = fs_init(&memConfig, &pMem1);
if (result != FS_SUCCESS) {
printf("%s: Failed to initialize memory file system 1.\n", pTest->name);
return FS_ERROR;
}

result = fs_init(&memConfig, &pMem2);
if (result != FS_SUCCESS) {
printf("%s: Failed to initialize memory file system 2.\n", pTest->name);
fs_uninit(pMem1);
return FS_ERROR;
}

/* Create test.txt in pMem1 */
fs_mkdir(pMem1, "/data", FS_WRITE | FS_IGNORE_MOUNTS);
result = fs_file_open(pMem1, "/data/test.txt", FS_WRITE | FS_IGNORE_MOUNTS, &pFile);
if (result == FS_SUCCESS) {
fs_file_close(pFile);
}

/* Create test.txt.meta in pMem2 */
fs_mkdir(pMem2, "/data", FS_WRITE | FS_IGNORE_MOUNTS);
result = fs_file_open(pMem2, "/data/test.txt.meta", FS_WRITE | FS_IGNORE_MOUNTS, &pFile);
if (result == FS_SUCCESS) {
fs_file_close(pFile);
}

/*
Mount both to root in pTestState->pFS.
Priority: Most recent has highest priority. We want pMem1 (test.txt) to be checked first.
*/
fs_mount_fs(pTestState->pFS, pMem2, "/prefix_test", 0);
fs_mount_fs(pTestState->pFS, pMem1, "/prefix_test", 0);

/* Iterate /prefix_test/data */
pIterator = fs_first(pTestState->pFS, "/prefix_test/data", FS_READ);
while (pIterator != NULL) {
if (fs_strncmp("test.txt", pIterator->pName, pIterator->nameLen) == 0 && pIterator->nameLen == 8) {
found1 = FS_TRUE;
}
if (fs_strncmp("test.txt.meta", pIterator->pName, pIterator->nameLen) == 0 && pIterator->nameLen == 13) {
found2 = FS_TRUE;
}

count++;
pIterator = fs_next(pIterator);
}

/* Cleanup mounts first. */
fs_unmount_fs(pTestState->pFS, pMem1, FS_READ);
fs_unmount_fs(pTestState->pFS, pMem2, FS_READ);

fs_uninit(pMem1);
fs_uninit(pMem2);

if (!found1 || !found2 || count != 2) {
printf("%s: Prefix bug detected. Expected 2 files (test.txt and test.txt.meta), found %d.\n", pTest->name, count);
return FS_ERROR;
}

return FS_SUCCESS;
}
/* END mounts_iteration */

/* BEG unmount */
Expand Down Expand Up @@ -4249,6 +4328,7 @@ int main(int argc, char** argv)
fs_test test_mounts_rename; /* Tests renaming files with mounts. */
fs_test test_mounts_remove; /* Tests removing files with mounts. */
fs_test test_mounts_iteration; /* Tests iterating directories with mounts. */
fs_test test_mounts_iteration_prefix_bug;
fs_test test_unmount; /* This needs to be the last mount test. */
fs_test test_archives; /* The top-level test for archives. This will set up the `fs` object and the folder and file structure in preparation for subsequent tests. */
fs_test test_archives_opaque; /* Tests that opening files inside an archive in opaque mode fails as expected. */
Expand Down Expand Up @@ -4354,8 +4434,9 @@ int main(int argc, char** argv)
fs_test_init(&test_mounts_read, "Mounts Read", fs_test_mounts_read, &test_mounts_state, &test_mounts);
fs_test_init(&test_mounts_mkdir, "Mounts Make Directory", fs_test_mounts_mkdir, &test_mounts_state, &test_mounts);
fs_test_init(&test_mounts_rename, "Mounts Rename", fs_test_mounts_rename, &test_mounts_state, &test_mounts);
fs_test_init(&test_mounts_remove, "Mounts Remove", fs_test_mounts_remove, &test_mounts_state, &test_mounts);
fs_test_init(&test_mounts_remove, "Mounts Remove", fs_test_mounts_remove, &test_mounts_state, &test_mounts);
fs_test_init(&test_mounts_iteration, "Mounts Iteration", fs_test_mounts_iteration, &test_mounts_state, &test_mounts);
fs_test_init(&test_mounts_iteration_prefix_bug, "Mounts Iteration Prefix Bug", fs_test_mounts_iteration_prefix_bug, &test_mounts_state, &test_mounts);
fs_test_init(&test_unmount, "Unmount", fs_test_unmount, &test_mounts_state, &test_mounts);

/*
Expand Down
Loading