A reference to an invalid macro argument (\ not followed by a digit
between 1 and 9) will cause an access outside of the bounds of the
currentmacroargs array in sym_FindMacroArg().
Macro arg references are processed in two places:
In CopyMacroArg(): called when scanning tokens between "", {} and
arguments of a macro call. The only problem here is that it accepts \0
as valid and so calls sym_FindMacroArg with a invalid value.
In PutMacroArg(): called by the lexer automata when it encounters a
token matching \\[0-9]? (in other cases than above). So not only it
accepts \0 but also \ alone.
Memo: In setuplex(), a rule is defined with a regex composed of up to
three ranges of chars and takes the form:
[FirstRange]
or [FirstRange][SecondRange]?
or [FirstRange]([SecondRange][Range]*)?
On scanning, when several rules match, the first longuest one is
choosen.
Regression test:
1)
SECTION "HOME", HOME
db "\0"
2)
SECTION "HOME", HOME
db \A
3)
SECTION "HOME", HOME
db \
The problem occurs when \@ is accessed outside the definition of a
macro and is not between "" or {}, or when it is used in an argument of
a macro call, i.e. when the access is processed by PutUniqueArg().
PutUniqueArg(), puts back the string value of \@ to the lexer's buffer
(to substitute \@ by the unique label string).
When \@ is not defined, sym_FindMacroArg(-1) returns NULL, which
yyunputstr() doesn't expect and crashes.
Solution:
Generate an error when \@ is not defined.
Regression test:
SECTION "HOME", HOME
ld a,\@
Will segfault.
On the fixed version, it will return an error as \@ is not available.
- separated the lexer into multiple functions so it is more readable
- fixed issue with long label names in macro arguments
- added error checking code to prevent buffer overflows
On Linux, valgrind complains about the overflow like this:
Pass 1...
==20054== Invalid read of size 1
==20054== at 0x406CDA: yylex (lexer.c:396)
==20054== by 0x40207C: yyparse (asmy.c:2921)
==20054== by 0x4086AF: main (main.c:351)
==20054== Address 0x503a102 is 0 bytes after a block of size 23,538 alloc'd
==20054== at 0x402994D: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20054== by 0x406411: yy_create_buffer (lexer.c:147)
==20054== by 0x404FE3: fstk_RunInclude (fstack.c:243)
==20054== by 0x4025F5: yyparse (asmy.y:744)
==20054== by 0x4086AF: main (main.c:351)
==20054==
This is a bit of a crude fix which simply exits the hashing loop when
we reach the end of the string. We should probably do some kind of
length calculation on the buffer instead.
Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com>