shithub: scc

Download patch

ref: aafa864b25db5f16d6b49f96b0aaa96661dc5b08
parent: 72996baa32cf2e7d7e26bbc3cca1ca4340a35f7d
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Jan 20 10:00:08 EST 2017

[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.

--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -105,7 +105,24 @@
 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) {
 		/*
 		 * Since we are unlinking them in the inverse order
@@ -117,18 +134,22 @@
 	}
 	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;
 	}
 }