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