From 37270c871e39cef5cb3ee022f270921cd365d21f Mon Sep 17 00:00:00 2001
From: Lactozilla <jp6781615@gmail.com>
Date: Tue, 4 Jun 2024 02:08:25 -0300
Subject: [PATCH] Raise TEXTMAP parser limits

---
 src/p_setup.c | 60 ++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 45 insertions(+), 15 deletions(-)

diff --git a/src/p_setup.c b/src/p_setup.c
index c4b4a35b3..e888ec5a5 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -1554,11 +1554,41 @@ static void P_LoadThings(UINT8 *data)
 }
 
 // Stores positions for relevant map data spread through a TEXTMAP.
-UINT32 mapthingsPos[UINT16_MAX];
-UINT32 linesPos[UINT16_MAX];
-UINT32 sidesPos[UINT16_MAX];
-UINT32 vertexesPos[UINT16_MAX];
-UINT32 sectorsPos[UINT16_MAX];
+typedef struct textmap_block_s
+{
+	UINT32 *pos;
+	size_t capacity;
+} textmap_block_t;
+
+static textmap_block_t mapthingBlocks;
+static textmap_block_t linedefBlocks;
+static textmap_block_t sidedefBlocks;
+static textmap_block_t vertexBlocks;
+static textmap_block_t sectorBlocks;
+
+static void TextmapStorePos(textmap_block_t *blocks, size_t *count)
+{
+	size_t locCount = (*count) + 1;
+
+	if (blocks->pos == NULL)
+	{
+		// Initial capacity (half of the former one.)
+		blocks->capacity = UINT16_MAX / 2;
+
+		Z_Calloc(sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
+	}
+	else if (locCount >= blocks->capacity)
+	{
+		// If we hit the list's capacity, make space for 1024 more blocks
+		blocks->capacity += 1024;
+
+		Z_Realloc(blocks->pos, sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
+	}
+
+	blocks->pos[locCount - 1] = M_TokenizerGetEndPos();
+
+	(*count) = locCount;
+}
 
 // Determine total amount of map data in TEXTMAP.
 static boolean TextmapCount(size_t size)
@@ -1602,15 +1632,15 @@ static boolean TextmapCount(size_t size)
 			brackets++;
 		// Check for valid fields.
 		else if (fastcmp(tkn, "thing"))
-			mapthingsPos[nummapthings++] = M_TokenizerGetEndPos();
+			TextmapStorePos(&mapthingBlocks, &nummapthings);
 		else if (fastcmp(tkn, "linedef"))
-			linesPos[numlines++] = M_TokenizerGetEndPos();
+			TextmapStorePos(&linedefBlocks, &numlines);
 		else if (fastcmp(tkn, "sidedef"))
-			sidesPos[numsides++] = M_TokenizerGetEndPos();
+			TextmapStorePos(&sidedefBlocks, &numsides);
 		else if (fastcmp(tkn, "vertex"))
-			vertexesPos[numvertexes++] = M_TokenizerGetEndPos();
+			TextmapStorePos(&vertexBlocks, &numvertexes);
 		else if (fastcmp(tkn, "sector"))
-			sectorsPos[numsectors++] = M_TokenizerGetEndPos();
+			TextmapStorePos(&sectorBlocks, &numsectors);
 		else
 			CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn);
 	}
@@ -2944,7 +2974,7 @@ static void P_LoadTextmap(void)
 		vt->floorzset = vt->ceilingzset = false;
 		vt->floorz = vt->ceilingz = 0;
 
-		TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter);
+		TextmapParse(vertexBlocks.pos[i], i, ParseTextmapVertexParameter);
 
 		if (vt->x == INT32_MAX)
 			I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i));
@@ -3001,7 +3031,7 @@ static void P_LoadTextmap(void)
 		textmap_planefloor.defined = 0;
 		textmap_planeceiling.defined = 0;
 
-		TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
+		TextmapParse(sectorBlocks.pos[i], i, ParseTextmapSectorParameter);
 
 		P_InitializeSector(sc);
 		if (textmap_colormap.used)
@@ -3050,7 +3080,7 @@ static void P_LoadTextmap(void)
 		ld->sidenum[0] = NO_SIDEDEF;
 		ld->sidenum[1] = NO_SIDEDEF;
 
-		TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter);
+		TextmapParse(linedefBlocks.pos[i], i, ParseTextmapLinedefParameter);
 
 		if (!ld->v1)
 			I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i));
@@ -3077,7 +3107,7 @@ static void P_LoadTextmap(void)
 		sd->sector = NULL;
 		sd->repeatcnt = 0;
 
-		TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter);
+		TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter);
 
 		if (!sd->sector)
 			I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i));
@@ -3101,7 +3131,7 @@ static void P_LoadTextmap(void)
 		memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
 		mt->mobj = NULL;
 
-		TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
+		TextmapParse(mapthingBlocks.pos[i], i, ParseTextmapThingParameter);
 	}
 }
 
-- 
GitLab