ref: 0abc10c55a5366e6fdad4c775e5f18b39c14eec6
parent: 443674874420ec21d4c1322e6f8450cd20996a03
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Nov 12 16:57:31 EST 2021
cc1: Fix double free() error The current code was too complex without a good reason. The lexer was not trying to concatenate consecutive strings, and this work was done in the expression parser. This was an error because it introduced complexity due to the memory allocation needed to concatenate the strings, and the only reason to do this was to avoid moving lineno variable that could produce more difficult to read error messages because they could be moved to different lines. That problem must be solved in a different way, where the variable line that is used in error reporting must be updated only when the beginning of a new token is detected.
--- a/src/cmd/cc/cc1/expr.c
+++ b/src/cmd/cc/cc1/expr.c
@@ -589,34 +589,6 @@
return install(sym->ns, yylval.sym);
}
-static Symbol *
-adjstrings(Symbol *sym)
-{
- char *s, *t;
- size_t len, n;
- Type *tp;
-
- tp = sym->type;
- s = sym->u.s;
- for (len = strlen(s);; len += n) {
- next();
- if (yytoken != STRING)
- break;
- t = yylval.sym->u.s;
- n = strlen(t);
- s = xrealloc(s, len + n + 1);
- memcpy(s+len, t, n);
- s[len + n] = '\0';
- killsym(yylval.sym);
- }
- ++len;
- if (tp->n.elem != len) {
- sym->type = mktype(chartype, ARY, len, NULL);
- sym->u.s = s;
- }
- return sym;
-}
-
/*************************************************************
* grammar functions *
*************************************************************/
@@ -630,11 +602,12 @@
sym = yylval.sym;
switch (yytoken) {
case STRING:
- np = constnode(adjstrings(sym));
+ np = constnode(sym);
sym->flags |= SHASINIT;
emit(ODECL, sym);
emit(OINIT, np);
- return varnode(sym);
+ np = varnode(sym);
+ break;
case BUILTIN:
fun = sym->u.fun;
next();
--- a/src/cmd/cc/cc1/lex.c
+++ b/src/cmd/cc/cc1/lex.c
@@ -544,6 +544,42 @@
}
/*
+ * skip all the spaces until the next token. When we are in
+ * CPPMODE \n is not considered a whitespace
+ */
+static int
+skipspaces(void)
+{
+ int c;
+
+ for (;;) {
+ switch (c = *input->p) {
+ case '\n':
+ if (lexmode == CPPMODE)
+ goto return_byte;
+ ++input->p;
+ case '\0':
+ if (!moreinput())
+ return EOF;
+ break;
+ case ' ':
+ case '\t':
+ case '\v':
+ case '\r':
+ case '\f':
+ ++input->p;
+ break;
+ default:
+ goto return_byte;
+ }
+ }
+
+return_byte:
+ input->begin = input->p;
+ return c;
+}
+
+/*
* string() parses a constant string, and convert all the
* escape sequences into single characters. This behaviour
* is correct except when we parse a #define, where we want
@@ -559,6 +595,8 @@
*bp++ = '"';
esc = 0;
+
+repeat:
for (++input->p; ; ++input->p) {
c = *input->p;
@@ -593,6 +631,10 @@
}
input->begin = ++input->p;
+
+ if (skipspaces() == '"')
+ goto repeat;
+
*bp = '\0';
yylen = bp - yytext + 1;
@@ -755,42 +797,6 @@
}
/* TODO: Ensure that namespace is NS_IDEN after a recovery */
-
-/*
- * skip all the spaces until the next token. When we are in
- * CPPMODE \n is not considered a whitespace
- */
-static int
-skipspaces(void)
-{
- int c;
-
- for (;;) {
- switch (c = *input->p) {
- case '\n':
- if (lexmode == CPPMODE)
- goto return_byte;
- ++input->p;
- case '\0':
- if (!moreinput())
- return EOF;
- break;
- case ' ':
- case '\t':
- case '\v':
- case '\r':
- case '\f':
- ++input->p;
- break;
- default:
- goto return_byte;
- }
- }
-
-return_byte:
- input->begin = input->p;
- return c;
-}
int
next(void)