From c75a9539bac624b5e524c74ffa37a065f532585a Mon Sep 17 00:00:00 2001 From: dbrotz <43593771+dbrotz@users.noreply.github.com> Date: Wed, 26 Jun 2019 17:36:12 -0700 Subject: [PATCH] Don't append invalid characters to symbol name When a macro arg appears in a symbol name, the contents are appended. However, the contents of the macro arg were not being validated. Any character, regardless of whether it was allowed in a symbol name, would be appended. With this change, the contents of the macro arg are now validated character by character. The symbol name is considered to end at the last valid character. The remainder of the macro arg is treated as though it followed the symbol name in the asm source code. --- src/asm/globlex.c | 123 +++++++++++++++++++++--------- src/asm/lexer.c | 2 - test/asm/label-macro-arg.asm | 27 +++++++ test/asm/label-macro-arg.out | 4 + test/asm/label-macro-arg.out.pipe | 4 + 5 files changed, 121 insertions(+), 39 deletions(-) create mode 100644 test/asm/label-macro-arg.asm create mode 100644 test/asm/label-macro-arg.out create mode 100644 test/asm/label-macro-arg.out.pipe diff --git a/src/asm/globlex.c b/src/asm/globlex.c index e707bcd9..36f67290 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -124,19 +124,19 @@ static int32_t ascii2bin(char *s) uint32_t ParseFixedPoint(char *s, uint32_t size) { - uint32_t i = 0, dot = 0; + uint32_t i; + uint32_t dot = 0; - while (size && dot != 2) { - if (s[i] == '.') - dot += 1; + for (i = 0; i < size; i++) { + if (s[i] == '.') { + dot++; - if (dot < 2) { - size -= 1; - i += 1; + if (dot == 2) + break; } } - yyunputbytes(size); + yyskipbytes(i); yylval.nConstValue = (int32_t)(atof(s) * 65536); @@ -147,56 +147,100 @@ uint32_t ParseNumber(char *s, uint32_t size) { char dest[256]; + if (size > 255) + fatalerror("Number token too long"); + strncpy(dest, s, size); dest[size] = 0; yylval.nConstValue = ascii2bin(dest); + yyskipbytes(size); + return 1; } +/* + * If the symbol name ends before the end of the macro arg, return true + * and point "rest" to the rest of the macro arg. + * Otherwise, return false. + */ +bool AppendMacroArg(char whichArg, char *dest, size_t *destIndex, char **rest) +{ + char *marg; + + if (whichArg == '@') + marg = sym_FindMacroArg(-1); + else if (whichArg >= '0' && whichArg <= '9') + marg = sym_FindMacroArg(whichArg - '0'); + else + fatalerror("Malformed ID"); + + if (!marg) + fatalerror("Macro argument '\\%c' not defined", whichArg); + + char ch; + + while ((ch = *marg) != 0) { + if ((ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9') + || ch == '_' + || ch == '@' + || ch == '#') { + if (*destIndex >= MAXSYMLEN) + fatalerror("Symbol too long"); + + dest[*destIndex] = ch; + (*destIndex)++; + } else { + *rest = marg; + return true; + } + + marg++; + } + + return false; +} + uint32_t ParseSymbol(char *src, uint32_t size) { char dest[MAXSYMLEN + 1]; - int32_t copied = 0, size_backup = size; + size_t srcIndex = 0; + size_t destIndex = 0; + char *rest = NULL; - while (size && copied < MAXSYMLEN) { - if (*src == '\\') { - char *marg; + while (srcIndex < size) { + char ch = src[srcIndex++]; - src += 1; - size -= 1; + if (ch == '\\') { + /* + * We don't check if srcIndex is still less than size, + * but that can only fail to be true when the + * following char is neither '@' nor a digit. + * In that case, AppendMacroArg() will catch the error. + */ + ch = src[srcIndex++]; - if (*src == '@') { - marg = sym_FindMacroArg(-1); - } else if (*src >= '0' && *src <= '9') { - marg = sym_FindMacroArg(*src - '0'); - } else { - fatalerror("Malformed ID"); - return 0; - } - - src += 1; - size -= 1; - - if (marg) { - while (*marg) - dest[copied++] = *marg++; - } + if (AppendMacroArg(ch, dest, &destIndex, &rest)) + break; } else { - dest[copied++] = *src++; - size -= 1; + if (destIndex >= MAXSYMLEN) + fatalerror("Symbol too long"); + dest[destIndex++] = ch; } } - if (copied >= MAXSYMLEN) - fatalerror("Symbol too long"); - - dest[copied] = 0; + dest[destIndex] = 0; if (!oDontExpandStrings && sym_isString(dest)) { char *s; - yyskipbytes(size_backup); + yyskipbytes(srcIndex); + + if (rest) + yyunputstr(rest); + yyunputstr(s = sym_GetStringValue(dest)); while (*s) { @@ -206,6 +250,11 @@ uint32_t ParseSymbol(char *src, uint32_t size) return 0; } + yyskipbytes(srcIndex); + + if (rest) + yyunputstr(rest); + strcpy(yylval.tzSym, dest); return 1; } diff --git a/src/asm/lexer.c b/src/asm/lexer.c index a98fef81..84b7ab50 100644 --- a/src/asm/lexer.c +++ b/src/asm/lexer.c @@ -803,8 +803,6 @@ scanagain: goto scanagain; } - pLexBuffer += nFloatLen; - if (token->nToken == T_ID && linestart) return T_LABEL; else diff --git a/test/asm/label-macro-arg.asm b/test/asm/label-macro-arg.asm new file mode 100644 index 00000000..06b70c15 --- /dev/null +++ b/test/asm/label-macro-arg.asm @@ -0,0 +1,27 @@ +m1: MACRO +x\1 +ENDM + +S EQUS "y" +S2 EQUS "yy" + +m2: MACRO +S\1 +ENDM + + m1 = 5 + m2 = 6 + m1 x = 7 + m2 2 = 8 + + printv x + printt "\n" + + printv y + printt "\n" + + printv xx + printt "\n" + + printv yy + printt "\n" diff --git a/test/asm/label-macro-arg.out b/test/asm/label-macro-arg.out new file mode 100644 index 00000000..bff88bdc --- /dev/null +++ b/test/asm/label-macro-arg.out @@ -0,0 +1,4 @@ +$5 +$6 +$7 +$8 diff --git a/test/asm/label-macro-arg.out.pipe b/test/asm/label-macro-arg.out.pipe new file mode 100644 index 00000000..bff88bdc --- /dev/null +++ b/test/asm/label-macro-arg.out.pipe @@ -0,0 +1,4 @@ +$5 +$6 +$7 +$8