diff --git a/src/Cafe/Filesystem/WUD/wud.cpp b/src/Cafe/Filesystem/WUD/wud.cpp index 07f6b7a3..3e266506 100644 --- a/src/Cafe/Filesystem/WUD/wud.cpp +++ b/src/Cafe/Filesystem/WUD/wud.cpp @@ -43,8 +43,20 @@ wud_t* wud_open(const fs::path& path) wud->offsetSectorArray = (wud->offsetSectorArray + (long long)(wud->sectorSize-1)); wud->offsetSectorArray = wud->offsetSectorArray - (wud->offsetSectorArray%(long long)wud->sectorSize); // read index table - unsigned int indexTableSize = sizeof(unsigned int) * wud->indexTableEntryCount; + uint64 indexTableSize64 = (uint64)sizeof(unsigned int) * (uint64)wud->indexTableEntryCount; + if (indexTableSize64 == 0 || indexTableSize64 > 0x40000000ull || indexTableSize64 > (uint64)inputFileSize) + { + // reject implausible/crafted index table sizes to avoid integer overflow and over-allocation + wud_close(wud); + return nullptr; + } + unsigned int indexTableSize = (unsigned int)indexTableSize64; wud->indexTable = (unsigned int*)malloc(indexTableSize); + if (!wud->indexTable) + { + wud_close(wud); + return nullptr; + } wud->fs->SetPosition(wud->offsetIndexTable); if( wud->fs->readData(wud->indexTable, indexTableSize) != indexTableSize ) { diff --git a/src/Cafe/Filesystem/WUHB/WUHBReader.cpp b/src/Cafe/Filesystem/WUHB/WUHBReader.cpp index e7a4c9be..1ef28011 100644 --- a/src/Cafe/Filesystem/WUHB/WUHBReader.cpp +++ b/src/Cafe/Filesystem/WUHB/WUHBReader.cpp @@ -115,6 +115,8 @@ uint32 WUHBReader::GetHashTableEntryOffset(uint32 hash, bool isFile) const const uint64 hash_table_ofs = (isFile ? m_header.file_hash_table_ofs : m_header.dir_hash_table_ofs); const uint64 hash_table_entry_count = hash_table_size / sizeof(uint32); + if (hash_table_entry_count == 0) + return ROMFS_ENTRY_EMPTY; const uint64 hash_table_entry_offset = hash_table_ofs + (hash % hash_table_entry_count) * sizeof(uint32); m_fileIn->SetPosition(hash_table_entry_offset); @@ -131,10 +133,15 @@ uint32 WUHBReader::GetHashTableEntryOffset(uint32 hash, bool isFile) const template bool WUHBReader::SearchHashList(uint32& entryOffset, const fs::path& targetName) const { - for (;;) + for (uint32 iterations = 0; ; iterations++) { if (entryOffset == ROMFS_ENTRY_EMPTY) return false; + if (iterations >= 0x100000) + { + cemuLog_log(LogType::Force, "WUHB: aborting suspected cyclic hash chain"); + return false; + } auto entry = GetEntry(entryOffset); if (entry.name == targetName) diff --git a/src/Cafe/Filesystem/fscDeviceWuhb.cpp b/src/Cafe/Filesystem/fscDeviceWuhb.cpp index 5e8e6484..35cdc633 100644 --- a/src/Cafe/Filesystem/fscDeviceWuhb.cpp +++ b/src/Cafe/Filesystem/fscDeviceWuhb.cpp @@ -75,7 +75,8 @@ class FSCDeviceWuhbFileCtx : public FSCVirtualFile dirEntry->isDirectory = true; dirEntry->isFile = false; dirEntry->fileSize = 0; - std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH); + std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH - 1); + dirEntry->path[FSC_MAX_DIR_NAME_LENGTH - 1] = '\0'; return true; } } @@ -88,7 +89,8 @@ class FSCDeviceWuhbFileCtx : public FSCVirtualFile dirEntry->isDirectory = false; dirEntry->isFile = true; dirEntry->fileSize = entry.size; - std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH); + std::strncpy(dirEntry->path, entry.name.c_str(), FSC_MAX_DIR_NAME_LENGTH - 1); + dirEntry->path[FSC_MAX_DIR_NAME_LENGTH - 1] = '\0'; return true; } } diff --git a/src/Cafe/IOSU/fsa/iosu_fsa.cpp b/src/Cafe/IOSU/fsa/iosu_fsa.cpp index 1429d083..fee43aa8 100644 --- a/src/Cafe/IOSU/fsa/iosu_fsa.cpp +++ b/src/Cafe/IOSU/fsa/iosu_fsa.cpp @@ -556,7 +556,8 @@ namespace iosu FSCDirEntry fscDirEntry; if (fsc_nextDir(fscFile, &fscDirEntry) == false) return FSA_RESULT::END_OF_DIRECTORY; - strcpy(dirEntryOut->name, fscDirEntry.path); + strncpy(dirEntryOut->name, fscDirEntry.path, sizeof(dirEntryOut->name)); + dirEntryOut->name[sizeof(dirEntryOut->name) - 1] = '\0'; FSFlag statFlag = FSFlag::NONE; dirEntryOut->stat.size = 0; if (fscDirEntry.isDirectory)