From da90237d03f4ace36b5779b414554d564ec355c4 Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Sat, 20 Apr 2019 20:09:59 +0200 Subject: Add error checking to all cc4group_getOnlyEntryData and cc4group_getChildren calls --- src/cc4group.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 152 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/cc4group.c b/src/cc4group.c index b3653b7..40b838c 100644 --- a/src/cc4group.c +++ b/src/cc4group.c @@ -266,7 +266,8 @@ static void deleteChildren(GroupEntryList* const entries) cc4group_applyMemoryManagementEnd(entry->value.memoryManagement, entry->value.data); } - if(entry->value.core.Directory) + // if they are not loaded yet, there is no need to delete them + if(entry->value.core.Directory && entry->value.children != NULL) { deleteChildren(entry->value.children); } @@ -991,16 +992,27 @@ static void cc4group_init(CC4Group* const this) this->error.lastFormattedMessage = NULL; } -static void cc4group_setMakerRecursively(CC4Group* const this, const C4GroupEntryData* groupEntry, const char* const maker) +static bool cc4group_setMakerRecursively(CC4Group* const this, const C4GroupEntryData* groupEntry, const char* const maker) { - ForeachGroupEntry(cc4group_getChildren(this, groupEntry)) + GroupEntryList* children = cc4group_getChildren(this, groupEntry); + if(children == NULL) + { + return false; + } + + ForeachGroupEntry(children) { if(entry->value.core.Directory) { C4GroupHeader_setMaker(entry->value.header, maker); - cc4group_setMakerRecursively(this, &entry->value, maker); + if(!cc4group_setMakerRecursively(this, &entry->value, maker)) + { + return false; + } } } + + return true; } static bool cc4group_setMaker(CC4Group* const this, const char* const maker, const char* const path, bool const recursive) @@ -1018,21 +1030,32 @@ static bool cc4group_setMaker(CC4Group* const this, const char* const maker, con C4GroupHeader_setMaker(entry->header, maker); if(recursive) { - cc4group_setMakerRecursively(this, entry, maker); + return cc4group_setMakerRecursively(this, entry, maker); } return true; } -static void cc4group_setOfficialRecursively(CC4Group* const this, const C4GroupEntryData* groupEntry, bool const official) +static bool cc4group_setOfficialRecursively(CC4Group* const this, const C4GroupEntryData* groupEntry, bool const official) { - ForeachGroupEntry(cc4group_getChildren(this, groupEntry)) + GroupEntryList* children = cc4group_getChildren(this, groupEntry); + if(children == NULL) + { + return false; + } + + ForeachGroupEntry(children) { if(entry->value.core.Directory) { C4GroupHeader_setOfficial(entry->value.header, official); - cc4group_setOfficialRecursively(this, &entry->value, official); + if(!cc4group_setOfficialRecursively(this, &entry->value, official)) + { + return false; + } } } + + return true; } static bool cc4group_setOfficial(CC4Group* const this, bool const official, const char* const path, bool const recursive) @@ -1049,22 +1072,33 @@ static bool cc4group_setOfficial(CC4Group* const this, bool const official, cons C4GroupHeader_setOfficial(entry->header, official); if(recursive) { - cc4group_setOfficialRecursively(this, entry, official); + return cc4group_setOfficialRecursively(this, entry, official); } return true; } -static void cc4group_setCreationRecursively(CC4Group* const this, const C4GroupEntryData* groupEntry, int32_t const creation) +static bool cc4group_setCreationRecursively(CC4Group* const this, const C4GroupEntryData* groupEntry, int32_t const creation) { - ForeachGroupEntry(cc4group_getChildren(this, groupEntry)) + GroupEntryList* children = cc4group_getChildren(this, groupEntry); + if(children == NULL) + { + return false; + } + + ForeachGroupEntry(children) { entry->value.core.Modified = creation; if(entry->value.core.Directory) { C4GroupHeader_setCreation(entry->value.header, creation); - cc4group_setCreationRecursively(this, &entry->value, creation); + if(!cc4group_setCreationRecursively(this, &entry->value, creation)) + { + return false; + } } } + + return true; } static bool cc4group_setCreation(CC4Group* const this, int32_t const creation, const char* const path, bool const recursive) @@ -1085,7 +1119,7 @@ static bool cc4group_setCreation(CC4Group* const this, int32_t const creation, c C4GroupHeader_setCreation(entry->header, creation); if(recursive) { - cc4group_setCreationRecursively(this, entry, creation); + return cc4group_setCreationRecursively(this, entry, creation); } } return true; @@ -1206,7 +1240,12 @@ static bool cc4group_extractEntry(CC4Group* const this, const C4GroupEntryData* SET_ERRNO_ERROR("open: Creating target file"); return false; } - write(file, cc4group_getOnlyEntryData(this, root), root->core.Size); + const uint8_t* data = cc4group_getOnlyEntryData(this, root); + if(data == NULL) + { + return false; + } + write(file, data, root->core.Size); if(close(file) == -1) { @@ -1254,7 +1293,14 @@ static bool cc4group_extractChildren(CC4Group* const this, const C4GroupEntryDat goto ret; } - ForeachGroupEntry(cc4group_getChildren(this, root)) + GroupEntryList* children = cc4group_getChildren(this, root); + if(children == NULL) + { + success = false; + goto ret; + } + + ForeachGroupEntry(children) { if(!cc4group_extractChildren(this, &entry->value, tmpPath)) { @@ -1268,7 +1314,7 @@ static bool cc4group_extractChildren(CC4Group* const this, const C4GroupEntryDat } else { - success = cc4group_extractEntry(this ,root, tmpPath); + success = cc4group_extractEntry(this, root, tmpPath); goto ret; } @@ -1329,8 +1375,16 @@ static const C4GroupEntryData* cc4group_getEntryByPath(CC4Group* const this, con break; } + GroupEntryList* children = cc4group_getChildren(this, currentParent); + if(!children) + { + *error = true; + currentParent = NULL; + goto ret; + } + bool found = false; - ForeachGroupEntry(cc4group_getChildren(this, currentParent)) + ForeachGroupEntry(children) { if(strcmp(entry->value.core.FileName, part) == 0) { @@ -1347,6 +1401,7 @@ static const C4GroupEntryData* cc4group_getEntryByPath(CC4Group* const this, con } } +ret: free(path); return currentParent; @@ -1468,7 +1523,7 @@ static bool cc4group_getEntryData(CC4Group* const this, const char* const entryP *data = cc4group_getOnlyEntryData(this, entry); *size = entry->core.Size; - return true; + return *data != NULL || *size == 0; } static void cc4group_setTmpMemoryStrategy(const CC4Group_TmpMemoryStrategy strategy) @@ -1515,6 +1570,11 @@ static size_t cc4group_calculateEntrySizes(CC4Group* const this, C4GroupEntryDat if(entryData->core.Directory) { GroupEntryList* children = cc4group_getChildren(this, entryData); + if(children == NULL) + { + return 0; + } + size_t sum = sizeof(C4GroupHeader) + GroupEntryListSize(children) * sizeof(C4GroupEntryCore); ForeachGroupEntry(children) { @@ -1533,8 +1593,14 @@ static void cc4group_calculateEntryCRC(CC4Group* const this, C4GroupEntryData* c { if(groupEntry->core.Directory) { + GroupEntryList* children = cc4group_getChildren(this, groupEntry); + if(children == NULL) + { + return; + } + uint32_t crc = 0; - ForeachGroupEntry(cc4group_getChildren(this, groupEntry)) + ForeachGroupEntry(children) { cc4group_calculateEntryCRC(this, &entry->value); crc ^= entry->value.core.CRC; @@ -1544,7 +1610,12 @@ static void cc4group_calculateEntryCRC(CC4Group* const this, C4GroupEntryData* c } else if(groupEntry->core.HasCRC != C4GroupEntryCore_ContentsFileNameCRC) { - uint32_t crc = crc32(0, cc4group_getOnlyEntryData(this, groupEntry), groupEntry->core.Size); + const uint8_t* data = cc4group_getOnlyEntryData(this, groupEntry); + if(data == NULL) + { + return; + } + uint32_t crc = crc32(0, data, groupEntry->core.Size); crc = crc32(crc, (uint8_t*)groupEntry->core.FileName, strlen(groupEntry->core.FileName)); groupEntry->core.HasCRC = C4GroupEntryCore_ContentsFileNameCRC; @@ -1651,8 +1722,20 @@ static bool cc4group_deflateToCallback(WriteCallback* const callback, const void static bool cc4group_writeEntries(CC4Group* const this, C4GroupEntryData* const entryData, WriteCallback* const callback) { - C4GroupHeader header = *(C4GroupHeader*)cc4group_getOnlyEntryData(this, entryData); + const C4GroupHeader* origHeader = (const C4GroupHeader*)cc4group_getOnlyEntryData(this, entryData); + if(origHeader == NULL) + { + return false; + } + + C4GroupHeader header = *origHeader; GroupEntryList* children = cc4group_getChildren(this, entryData); + + if(children == NULL) + { + return false; + } + header.Entries = GroupEntryListSize(children); header.Ver1 = 1; header.Ver2 = 2; @@ -1698,7 +1781,13 @@ static bool cc4group_writeEntries(CC4Group* const this, C4GroupEntryData* const } else if(entry->value.core.Size > 0) { - if(!cc4group_deflateToCallback(callback, cc4group_getOnlyEntryData(this, &entry->value), entry->value.core.Size, Z_NO_FLUSH, Z_OK)) + const uint8_t* data = cc4group_getOnlyEntryData(this, &entry->value); + if(data == NULL) + { + return false; + } + + if(!cc4group_deflateToCallback(callback, data, entry->value.core.Size, Z_NO_FLUSH, Z_OK)) { SET_MESSAGE_ERROR("Failed writing entry data"); return false; @@ -1939,6 +2028,11 @@ static bool cc4group_getEntryInfos(CC4Group* const this, const char* const path, } GroupEntryList* children = cc4group_getChildren(this, node); + if(children == NULL) + { + return false; + } + *size = GroupEntryListSize(children); CC4Group_EntryInfo* myInfos = malloc(*size * sizeof(CC4Group_EntryInfo)); if(myInfos == NULL) @@ -2004,8 +2098,16 @@ static bool cc4group_getParentAndChildEntries(CC4Group* const this, const char* } *parentEntry = parent; + + GroupEntryList* children = cc4group_getChildren(this, parent); + if(children == NULL) + { + free(myPath); + return false; + } + GroupEntryListEntry* child = NULL; - ForeachGroupEntry(cc4group_getChildren(this, parent)) + ForeachGroupEntry(children) { if(strcmp(entry->value.core.FileName, entryName) == 0) { @@ -2046,10 +2148,16 @@ static bool cc4group_deleteEntry(CC4Group* const this, const char* const path, b return false; } - deleteChildren(cc4group_getChildren(this, &deleteEntry->value)); + // if they are not loaded yet, there is no need to delete them + if(deleteEntry->value.children != NULL) + { + deleteChildren(deleteEntry->value.children); + } } GroupEntryList* parentChildren = cc4group_getChildren(this, parent); + assert(parentChildren); // if there was an error, it should have really been catched already in cc4group_getParentAndChildEntries + GroupEntryListRemove(parentChildren, deleteEntry); parent->header->Entries = GroupEntryListSize(parentChildren); @@ -2062,6 +2170,11 @@ static C4GroupEntryData* cc4group_addEntryToDirectory(CC4Group* const this, C4Gr // TODO? Implement engine-optimized order sorting here? GroupEntryList* directoryChildren = cc4group_getChildren(this, directory); + if(directoryChildren == NULL) + { + return NULL; // TODO: error checking in callees of this + } + C4GroupEntryData* newEntry = &GroupEntryListAppend(directoryChildren, *entry)->value; newEntry->parent = directory; directory->header->Entries = GroupEntryListSize(directoryChildren); @@ -2113,7 +2226,13 @@ static bool cc4group_renameEntry(CC4Group* const this, const char* const oldPath } C4GroupEntryCore_setFileName(&entry->value.core, targetName); - cc4group_addEntryToDirectory(this, newParent, &entry->value); + if(cc4group_addEntryToDirectory(this, newParent, &entry->value) == NULL) + { + free(targetPath); + return false; + } + + assert(cc4group_getChildren(this, oldParent)); // again, should have been catched already with cc4group_getParentAndChildEntries GroupEntryListRemove(cc4group_getChildren(this, oldParent), entry); free(targetPath); @@ -2131,7 +2250,7 @@ static C4GroupEntryData* cc4group_createEntry(CC4Group* const this, const char* if(error) { - return false; + return NULL; } char* targetPath = strdup(path); @@ -2294,6 +2413,13 @@ static CC4Group* cc4group_openAsChild(CC4Group* const this, const char* const pa child->root.core.Directory = 1; child->root.core.FileName[0] = '\0'; child->root.children = cc4group_getChildren(this, entry); + + if(child->root.children == NULL) + { + cc4group_delete(child); + return NULL; + } + child->parent = this; ++this->referenceCounter; -- cgit v1.2.3-54-g00ecf