fix: skip raw terrain chunk data with 64 bit relative seeks

Each skip computed an absolute offset as a 32 bit tellg plus a size
product in 32 bit math (colorMapSize * colorMapSize * 4 and friends),
which wraps for large values and can seek backwards. The skips are now
relative to the current position with the size promoted to
std::streamoff first. Offsets are unchanged for every real terrain file,
so this only removes the overflow the TODO asked about.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-26 18:49:54 -05:00
parent b5e9d3b94c
commit 746919b3d2

View File

@@ -18,43 +18,43 @@ RawChunk::RawChunk(std::ifstream& stream) {
// We can just skip the rest of the data so we can read the next chunks, we don't need anymore data // We can just skip the rest of the data so we can read the next chunks, we don't need anymore data
// Possible overflow here? TODO make reasonable upper bound or confirm big numbers arent necessary to have // Skips are relative and done in 64 bit math so large sizes can't wrap around and seek backwards.
uint32_t colorMapSize; uint32_t colorMapSize;
BinaryIO::BinaryRead(stream, colorMapSize); BinaryIO::BinaryRead(stream, colorMapSize);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (colorMapSize * colorMapSize * 4)); stream.seekg(static_cast<std::streamoff>(colorMapSize) * colorMapSize * 4, std::ios::cur);
uint32_t lightmapSize; uint32_t lightmapSize;
BinaryIO::BinaryRead(stream, lightmapSize); BinaryIO::BinaryRead(stream, lightmapSize);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (lightmapSize)); stream.seekg(static_cast<std::streamoff>(lightmapSize), std::ios::cur);
uint32_t colorMapSize2; uint32_t colorMapSize2;
BinaryIO::BinaryRead(stream, colorMapSize2); BinaryIO::BinaryRead(stream, colorMapSize2);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (colorMapSize2 * colorMapSize2 * 4)); stream.seekg(static_cast<std::streamoff>(colorMapSize2) * colorMapSize2 * 4, std::ios::cur);
uint8_t unknown; uint8_t unknown;
BinaryIO::BinaryRead(stream, unknown); BinaryIO::BinaryRead(stream, unknown);
uint32_t blendmapSize; uint32_t blendmapSize;
BinaryIO::BinaryRead(stream, blendmapSize); BinaryIO::BinaryRead(stream, blendmapSize);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (blendmapSize)); stream.seekg(static_cast<std::streamoff>(blendmapSize), std::ios::cur);
uint32_t pointSize; uint32_t pointSize;
BinaryIO::BinaryRead(stream, pointSize); BinaryIO::BinaryRead(stream, pointSize);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (pointSize * 9 * 4)); stream.seekg(static_cast<std::streamoff>(pointSize) * 9 * 4, std::ios::cur);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (colorMapSize * colorMapSize)); stream.seekg(static_cast<std::streamoff>(colorMapSize) * colorMapSize, std::ios::cur);
uint32_t endCounter; uint32_t endCounter;
BinaryIO::BinaryRead(stream, endCounter); BinaryIO::BinaryRead(stream, endCounter);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (endCounter * 2)); stream.seekg(static_cast<std::streamoff>(endCounter) * 2, std::ios::cur);
if (endCounter != 0) { if (endCounter != 0) {
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (32)); stream.seekg(32, std::ios::cur);
for (int i = 0; i < 0x10; i++) { for (int i = 0; i < 0x10; i++) {
uint16_t finalCountdown; uint16_t finalCountdown;
BinaryIO::BinaryRead(stream, finalCountdown); BinaryIO::BinaryRead(stream, finalCountdown);
stream.seekg(static_cast<uint32_t>(stream.tellg()) + (finalCountdown * 2)); stream.seekg(static_cast<std::streamoff>(finalCountdown) * 2, std::ios::cur);
} }
} }