mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
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.
This commit is contained in:
@@ -274,14 +274,13 @@ static void copymacro(void)
|
||||
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')
|
||||
|
||||
@@ -158,7 +158,7 @@ void yy_delete_buffer(YY_BUFFER_STATE buf)
|
||||
* 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 @@ static void yy_buffer_append(YY_BUFFER_STATE buf, uint32_t capacity, char c)
|
||||
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,7 +195,9 @@ YY_BUFFER_STATE yy_scan_bytes(char *mem, uint32_t size)
|
||||
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 @@ YY_BUFFER_STATE yy_scan_bytes(char *mem, uint32_t size)
|
||||
pBuffer->pBufferStart = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
pBuffer->pBuffer = pBuffer->pBufferRealStart + SAFETYMARGIN;
|
||||
memcpy(pBuffer->pBuffer, mem, size);
|
||||
pBuffer->nBufferSize = size;
|
||||
pBuffer->oAtLineStart = 1;
|
||||
pBuffer->pBuffer[size] = 0;
|
||||
pBuffer->nBufferSize = size;
|
||||
yy_buffer_append_newlines(pBuffer, capacity);
|
||||
pBuffer->oAtLineStart = 1;
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
@@ -257,7 +281,7 @@ YY_BUFFER_STATE yy_create_buffer(FILE *f)
|
||||
|
||||
/* 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 @@ YY_BUFFER_STATE yy_create_buffer(FILE *f)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
7
test/asm/line-continuation-macro.asm
Normal file
7
test/asm/line-continuation-macro.asm
Normal file
@@ -0,0 +1,7 @@
|
||||
m: MACRO
|
||||
ENDM
|
||||
|
||||
m2: MACRO
|
||||
m \ ENDM
|
||||
|
||||
m2
|
||||
0
test/asm/line-continuation-macro.out
Normal file
0
test/asm/line-continuation-macro.out
Normal file
8
test/asm/line-continuation-rept.asm
Normal file
8
test/asm/line-continuation-rept.asm
Normal file
@@ -0,0 +1,8 @@
|
||||
m: MACRO
|
||||
ENDM
|
||||
|
||||
REPT 1
|
||||
m ENDR
|
||||
|
||||
REPT 1
|
||||
m \ ENDR
|
||||
0
test/asm/line-continuation-rept.out
Normal file
0
test/asm/line-continuation-rept.out
Normal file
Reference in New Issue
Block a user