shithub: rgbds

Download patch

ref: f36a3d5b2aab0fdfa9a1db0a10bc58677f18ac80
parent: 89eda89838755902482a0e6619dea77c06fd64a9
author: dbrotz <[email protected]>
date: Mon Sep 9 23:03:04 EDT 2019

Fix macro and rept buffer overflows
Macro and rept buffers were not always being terminated with newlines
and/or were vulnerable to the final newline being escaped, allowing
buffer overflows to occur. Now, they are terminated with newlines using
the same mechanism as the file buffer.

--- a/src/asm/asmy.y
+++ b/src/asm/asmy.y
@@ -274,14 +274,13 @@
 	src = pCurrentBuffer->pBuffer;
 	ulNewMacroSize = len;
 
-	tzNewMacro = (char *)malloc(ulNewMacroSize+2);
+	tzNewMacro = (char *)malloc(ulNewMacroSize + 1);
 	if (tzNewMacro == NULL)
 		fatalerror("Not enough memory for MACRO definition.");
 
 	uint32_t i;
 
-	tzNewMacro[ulNewMacroSize] = '\n';
-	tzNewMacro[ulNewMacroSize+1] = 0;
+	tzNewMacro[ulNewMacroSize] = 0;
 	for (i = 0; i < ulNewMacroSize; i += 1) {
 		tzNewMacro[i] = src[i];
 		if (src[i] == '\n')
--- a/src/asm/lexer.c
+++ b/src/asm/lexer.c
@@ -158,7 +158,7 @@
  * 2. The buffer is terminated with 0
  * 3. nBufferSize is the size without the terminator
  */
-static void yy_buffer_append(YY_BUFFER_STATE buf, uint32_t capacity, char c)
+static void yy_buffer_append(YY_BUFFER_STATE buf, size_t capacity, char c)
 {
 	assert(buf->pBufferStart[buf->nBufferSize] == 0);
 	assert(buf->nBufferSize + 1 < capacity);
@@ -167,6 +167,27 @@
 	buf->pBufferStart[buf->nBufferSize] = 0;
 }
 
+static void yy_buffer_append_newlines(YY_BUFFER_STATE buf, size_t capacity)
+{
+	/* Add newline if file doesn't end with one */
+	if (buf->nBufferSize == 0
+	 || buf->pBufferStart[buf->nBufferSize - 1] != '\n')
+		yy_buffer_append(buf, capacity, '\n');
+
+	/* Add newline if \ will eat the last newline */
+	if (buf->nBufferSize >= 2) {
+		size_t pos = buf->nBufferSize - 2;
+
+		/* Skip spaces and tabs */
+		while (pos > 0 && (buf->pBufferStart[pos] == ' '
+				|| buf->pBufferStart[pos] == '\t'))
+			pos--;
+
+		if (buf->pBufferStart[pos] == '\\')
+			yy_buffer_append(buf, capacity, '\n');
+	}
+}
+
 YY_BUFFER_STATE yy_scan_bytes(char *mem, uint32_t size)
 {
 	YY_BUFFER_STATE pBuffer = malloc(sizeof(struct yy_buffer_state));
@@ -174,8 +195,10 @@
 	if (pBuffer == NULL)
 		fatalerror("%s: Out of memory!", __func__);
 
-	pBuffer->pBufferRealStart = malloc(size + 1 + SAFETYMARGIN);
+	size_t capacity = size + 3; /* space for 2 newlines and terminator */
 
+	pBuffer->pBufferRealStart = malloc(capacity + SAFETYMARGIN);
+
 	if (pBuffer->pBufferRealStart == NULL)
 		fatalerror("%s: Out of memory for buffer!", __func__);
 
@@ -182,9 +205,10 @@
 	pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN;
 	pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN;
 	memcpy(pBuffer->pBuffer, mem, size);
+	pBuffer->pBuffer[size] = 0;
 	pBuffer->nBufferSize = size;
+	yy_buffer_append_newlines(pBuffer, capacity);
 	pBuffer->oAtLineStart = 1;
-	pBuffer->pBuffer[size] = 0;
 
 	return pBuffer;
 }
@@ -257,7 +281,7 @@
 
 	/* This is added here to make the buffer scaling above easy to express,
 	 * while taking the newline space into account
-	 * for the `yy_buffer_append`s below.
+	 * for the yy_buffer_append_newlines() call below.
 	 */
 	capacity += 3;
 
@@ -317,23 +341,7 @@
 		}
 	}
 
-	/* Add newline if file doesn't end with one */
-	if (size == 0 || pBuffer->pBufferStart[size - 1] != '\n')
-		yy_buffer_append(pBuffer, capacity, '\n');
-
-	/* Add newline if \ will eat the last newline */
-	if (pBuffer->nBufferSize >= 2) {
-		size_t pos = pBuffer->nBufferSize - 2;
-
-		/* Skip spaces and tabs */
-		while (pos > 0 && (pBuffer->pBufferStart[pos] == ' '
-				|| pBuffer->pBufferStart[pos] == '\t'))
-			pos--;
-
-		if (pBuffer->pBufferStart[pos] == '\\')
-			yy_buffer_append(pBuffer, capacity, '\n');
-	}
-
+	yy_buffer_append_newlines(pBuffer, capacity);
 	pBuffer->oAtLineStart = 1;
 	return pBuffer;
 }
--- /dev/null
+++ b/test/asm/line-continuation-macro.asm
@@ -1,0 +1,7 @@
+m: MACRO
+ENDM
+
+m2: MACRO
+	m \ ENDM
+
+	m2
--- /dev/null
+++ b/test/asm/line-continuation-rept.asm
@@ -1,0 +1,8 @@
+m: MACRO
+ENDM
+
+REPT 1
+	m ENDR
+
+REPT 1
+	m \ ENDR