scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit fea243a2851d05bb1036a542e4ef1aa714a87570
parent a7170f9dbfe2396631013b806e6c184ad1f01aee
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 20 Jan 2017 15:00:08 +0100

[cc1] Guard popctx() of dangling pointers in yylval.sym

When a context is popped all the symbols defined in it
are killed. Since the lexer reads a token ahead it
already read some token that maybe is an identifier
defined in the context, and it means that yylval.sym
is an invalid pointer. This new code detects the
situation and relookup the symbol again.

Diffstat:
Mcc1/symbol.c | 39++++++++++++++++++++++++++++++---------
1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -105,6 +105,23 @@ void popctx(void) { Symbol *next, *sym; + int dangling = 0; + + /* + * we have to be careful before popping the current + * context, because since the parser is one token + * ahead it may already have read an identifier at + * this point, and yylval.sym is a pointer to + * the symbol associated to such token. If that + * symbol is from the context that we are popping + * then we are going to generate a dangling pointer. + * We can detect this situation and call again to + * lookup. + */ + if ((yytoken == IDEN || yytoken == TYPEIDEN) && + yylval.sym->ctx == curctx) { + dangling = 1; + } for (sym = head; sym && sym->ctx == curctx; sym = next) { /* @@ -117,18 +134,22 @@ popctx(void) } head = sym; - if (--curctx != GLOBALCTX) - return; + if (--curctx == GLOBALCTX) { + for (sym = labels; sym; sym = next) { + next = sym->next; + killsym(sym); + } + labels = NULL; - for (sym = labels; sym; sym = next) { - next = sym->next; - killsym(sym); + if (curfun) { + free(curfun->u.pars); + curfun->u.pars = NULL; + } } - labels = NULL; - if (curfun) { - free(curfun->u.pars); - curfun->u.pars = NULL; + if (dangling) { + yylval.sym = lookup(namespace, yytext, ALLOC); + yytoken = yylval.sym->token; } }