shithub: scc

Download patch

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)