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
5 changes: 5 additions & 0 deletions Core/GameEngine/Include/Common/MapReaderWriterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
#define K_LIGHTING_VERSION_3 3 // Added 2 additional global lights for terrain.
#define K_WORLDDICT_VERSION_1 1
#define K_MAPPREVIEW_VERSION_1 1

// TheSuperHackers @bugfix arcticdolphin 12/10/2026 Map size limits.
Comment thread
xezon marked this conversation as resolved.
#define MAX_MAP_DIMENSION 8192 // The shroud texture spans the map and shoreline tiles pack each coordinate into 16 bits
#define MAX_MAP_AREA (4096*4096) // Terrain, pathfinding and partition arrays allocate per cell in a 32 bit process

/** Virtual helper class, so that we can write map data using FILE* or CFile. */
class OutputStream {
public:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ class WorldHeightMap : public RefCountClass,
public: // height map info.
static Int getMinHeightValue() {return K_MIN_HEIGHT;}
static Int getMaxHeightValue() {return K_MAX_HEIGHT;}
static Bool isValidMapSize(Int width, Int height, Int borderSize); ///< Within MAX_MAP_DIMENSION and MAX_MAP_AREA, width and height include the border

UnsignedByte *getDataPtr() {return m_data;}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,24 @@ Bool WorldHeightMap::ParseObjectsDataChunk(DataChunkInput &file, DataChunkInfo *
return (file.parse(userData));
}

Bool WorldHeightMap::isValidMapSize(Int width, Int height, Int borderSize)
{
if (width <= 0 || width > MAX_MAP_DIMENSION)
return false;
if (height <= 0 || height > MAX_MAP_DIMENSION)
return false;
if (width * height > MAX_MAP_AREA)
return false;
if (borderSize < 0 || borderSize > (width - 1) / 2 || borderSize > (height - 1) / 2)
return false;
return true;
}

static Bool isValidHeightDataSize(DataChunkInput &file, Int dataSize, Int width, Int height)
{
return dataSize > 0 && dataSize == width * height && (UnsignedInt)dataSize <= file.getChunkDataSizeLeft();
}

/**
* WorldHeightMap::ParseHeightMapData - read a height map chunk.
* Format is the newer CHUNKY format.
Expand Down Expand Up @@ -857,6 +875,10 @@ Bool WorldHeightMap::ParseHeightMapData(DataChunkInput &file, DataChunkInfo *inf
m_borderSize = 0;
}

if (!isValidMapSize(m_width, m_height, m_borderSize)) {
throw ERROR_CORRUPT_FILE_FORMAT;
}

if (info->version >= K_HEIGHT_MAP_VERSION_4) {
Int numBorders = file.readInt();
m_boundaries.resize(numBorders);
Expand All @@ -871,11 +893,12 @@ Bool WorldHeightMap::ParseHeightMapData(DataChunkInput &file, DataChunkInfo *inf
}

m_dataSize = file.readInt();
m_data = MSGNEW("WorldHeightMap_ParseHeightMapData") UnsignedByte[m_dataSize];
if (m_dataSize <= 0 || (m_dataSize != (m_width*m_height))) {
if (!isValidHeightDataSize(file, m_dataSize, m_width, m_height)) {
throw ERROR_CORRUPT_FILE_FORMAT ;
}

m_data = MSGNEW("WorldHeightMap_ParseHeightMapData") UnsignedByte[m_dataSize];
Comment thread
tintinhamans marked this conversation as resolved.
Comment thread
tintinhamans marked this conversation as resolved.

Int numBytesX = (m_width+7)/8; //how many bytes to fit all bitflags
Int numBytesY = m_height;
m_seismicUpdateWidth=numBytesX;
Expand Down Expand Up @@ -931,6 +954,10 @@ Bool WorldHeightMap::ParseSizeOnly(DataChunkInput &file, DataChunkInfo *info, vo
m_borderSize = 0;
}

if (!isValidMapSize(m_width, m_height, m_borderSize)) {
throw ERROR_CORRUPT_FILE_FORMAT;
}

if (info->version >= K_HEIGHT_MAP_VERSION_4) {
Int numBorders = file.readInt();
m_boundaries.resize(numBorders);
Expand All @@ -945,10 +972,11 @@ Bool WorldHeightMap::ParseSizeOnly(DataChunkInput &file, DataChunkInfo *info, vo
}

m_dataSize = file.readInt();
m_data = MSGNEW("WorldHeightMap_ParseSizeOnly") UnsignedByte[m_dataSize];
if (m_dataSize <= 0 || (m_dataSize != (m_width*m_height))) {
if (!isValidHeightDataSize(file, m_dataSize, m_width, m_height)) {
throw ERROR_CORRUPT_FILE_FORMAT ;
}

m_data = MSGNEW("WorldHeightMap_ParseSizeOnly") UnsignedByte[m_dataSize];
file.readArrayOfBytes((char *)m_data, m_dataSize);
// Resize me.
if (info->version == K_HEIGHT_MAP_VERSION_1) {
Expand Down
Loading