shithub: scc

Download patch

ref: e732e73904098e6063403a6516c29fe536534549
parent: 19b99b76f3636603e12eaefee2254a81449be0ec
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Nov 13 04:03:27 EST 2021

cc1: Escape " in stringizer operator

The stringizer operator works at the preprocessor level, and it means that
adding " at eh beginning and at the end can modify the structure of the code.
For this reason it is needed to escape the quotation marks within the expansion.

--- a/src/cmd/cc/cc1/cpp.c
+++ b/src/cmd/cc/cc1/cpp.c
@@ -183,11 +183,11 @@
 static size_t
 copymacro(char *buffer, char *s, size_t bufsiz, char *arglist[])
 {
-	int delim, prevc, c, esc;
+	int delim, c, esc;
 	char *p, *arg, *bp = buffer;
 	size_t size;
 
-	for (prevc = '\0'; c = *s; prevc = c, ++s) {
+	for (; c = *s; ++s) {
 		switch (c) {
 		case '$':
 			while (bp[-1] == ' ')
@@ -194,7 +194,6 @@
 				--bp, ++bufsiz;
 			while (s[1] == ' ')
 				++s;
-		case '#':
 			break;
 		case '\'':
 			delim = '\'';
@@ -219,21 +218,41 @@
 			bufsiz -= size;
 			bp += size;
 			break;
+		case '#':
+			arg = arglist[atoi(s += 2)];
+			s += 2;
+
+			if (bufsiz < 3)
+				goto expansion_too_long;
+
+			*bp++ = '"';
+			while ((c = *arg++) != '\0') {
+				if (c == '"') {
+					if (bufsiz < 3)
+						goto expansion_too_long;
+					*bp++ = '\\';
+					*bp++ = '"';
+					bufsiz -= 2;
+				} else {
+					if (bufsiz < 2)
+						goto expansion_too_long;
+					*bp++ = c;
+					bufsiz--;
+				}
+			}
+			*bp++ = '"';
+
+			break;
 		case '@':
-			if (prevc == '#')
-				bufsiz -= 2;
 			arg = arglist[atoi(++s)];
+			s += 2;
+
 			size = strlen(arg);
 			if (size > bufsiz)
 				goto expansion_too_long;
-			if (prevc == '#')
-				*bp++ = '"';
 			memcpy(bp, arg, size);
 			bp += size;
-			if (prevc == '#')
-				*bp++ = '"';
 			bufsiz -= size;
-			s += 2;
 			break;
 		default:
 			if (bufsiz-- == 0)