Module Name:    src
Committed By:   rillig
Date:           Sun Jan  9 14:06:00 UTC 2022

Modified Files:
        src/usr.bin/make: for.c
        src/usr.bin/make/unit-tests: directive-for-escape.exp
            directive-for-escape.mk

Log Message:
make: fix crash for newline in .for value in -dp mode (since yesterday)


To generate a diff of this commit:
cvs rdiff -u -r1.163 -r1.164 src/usr.bin/make/for.c
cvs rdiff -u -r1.12 -r1.13 \
    src/usr.bin/make/unit-tests/directive-for-escape.exp \
    src/usr.bin/make/unit-tests/directive-for-escape.mk

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/for.c
diff -u src/usr.bin/make/for.c:1.163 src/usr.bin/make/for.c:1.164
--- src/usr.bin/make/for.c:1.163	Sun Jan  9 12:43:52 2022
+++ src/usr.bin/make/for.c	Sun Jan  9 14:06:00 2022
@@ -1,4 +1,4 @@
-/*	$NetBSD: for.c,v 1.163 2022/01/09 12:43:52 rillig Exp $	*/
+/*	$NetBSD: for.c,v 1.164 2022/01/09 14:06:00 rillig Exp $	*/
 
 /*
  * Copyright (c) 1992, The Regents of the University of California.
@@ -58,7 +58,7 @@
 #include "make.h"
 
 /*	"@(#)for.c	8.1 (Berkeley) 6/6/93"	*/
-MAKE_RCSID("$NetBSD: for.c,v 1.163 2022/01/09 12:43:52 rillig Exp $");
+MAKE_RCSID("$NetBSD: for.c,v 1.164 2022/01/09 14:06:00 rillig Exp $");
 
 
 typedef struct ForLoop {
@@ -367,8 +367,8 @@ AddEscaped(Buffer *cmds, Substring item,
  * expression like ${i} or ${i:...} or $(i) or $(i:...) with ":Uvalue".
  */
 static void
-ForLoop_SubstVarLong(ForLoop *f, Buffer *body, const char **pp,
-		     char endc, const char **inout_mark)
+ForLoop_SubstVarLong(ForLoop *f, unsigned int firstItem, Buffer *body,
+		     const char **pp, char endc, const char **inout_mark)
 {
 	size_t i;
 	const char *start = *pp;
@@ -392,7 +392,7 @@ ForLoop_SubstVarLong(ForLoop *f, Buffer 
 		 */
 		Buf_AddBytesBetween(body, *inout_mark, start);
 		Buf_AddStr(body, ":U");
-		AddEscaped(body, f->items.words[f->nextItem + i], endc);
+		AddEscaped(body, f->items.words[firstItem + i], endc);
 
 		*inout_mark = p;
 		*pp = p;
@@ -405,7 +405,7 @@ ForLoop_SubstVarLong(ForLoop *f, Buffer 
  * variable expressions like $i with their ${:U...} expansion.
  */
 static void
-ForLoop_SubstVarShort(ForLoop *f, Buffer *body,
+ForLoop_SubstVarShort(ForLoop *f, unsigned int firstItem, Buffer *body,
 		      const char *p, const char **inout_mark)
 {
 	const char ch = *p;
@@ -430,7 +430,7 @@ found:
 
 	/* Replace $<ch> with ${:U<value>} */
 	Buf_AddStr(body, "{:U");
-	AddEscaped(body, f->items.words[f->nextItem + i], '}');
+	AddEscaped(body, f->items.words[firstItem + i], '}');
 	Buf_AddByte(body, '}');
 }
 
@@ -448,7 +448,7 @@ found:
  * possible to contrive a makefile where an unwanted substitution happens.
  */
 static void
-ForLoop_SubstBody(ForLoop *f, Buffer *body)
+ForLoop_SubstBody(ForLoop *f, unsigned int firstItem, Buffer *body)
 {
 	const char *p, *end;
 	const char *mark;	/* where the last substitution left off */
@@ -461,9 +461,11 @@ ForLoop_SubstBody(ForLoop *f, Buffer *bo
 		if (p[1] == '{' || p[1] == '(') {
 			char endc = p[1] == '{' ? '}' : ')';
 			p += 2;
-			ForLoop_SubstVarLong(f, body, &p, endc, &mark);
+			ForLoop_SubstVarLong(f, firstItem, body,
+			    &p, endc, &mark);
 		} else if (p[1] != '\0') {
-			ForLoop_SubstVarShort(f, body, p + 1, &mark);
+			ForLoop_SubstVarShort(f, firstItem, body,
+			    p + 1, &mark);
 			p += 2;
 		} else
 			break;
@@ -482,9 +484,9 @@ For_NextIteration(ForLoop *f, Buffer *bo
 	if (f->nextItem == f->items.len)
 		return false;
 
-	ForLoop_SubstBody(f, body);
-	DEBUG1(FOR, "For: loop body:\n%s", body->data);
 	f->nextItem += (unsigned int)f->vars.len;
+	ForLoop_SubstBody(f, f->nextItem - (unsigned int)f->vars.len, body);
+	DEBUG1(FOR, "For: loop body:\n%s", body->data);
 	return true;
 }
 

Index: src/usr.bin/make/unit-tests/directive-for-escape.exp
diff -u src/usr.bin/make/unit-tests/directive-for-escape.exp:1.12 src/usr.bin/make/unit-tests/directive-for-escape.exp:1.13
--- src/usr.bin/make/unit-tests/directive-for-escape.exp:1.12	Thu Sep  2 07:02:08 2021
+++ src/usr.bin/make/unit-tests/directive-for-escape.exp	Sun Jan  9 14:06:00 2022
@@ -87,6 +87,22 @@ For: loop body:
 .  info long: ${:U" "}
 make: "directive-for-escape.mk" line 138: short: " "
 make: "directive-for-escape.mk" line 139: long: " "
+For: end for 1
+For: loop body:
+For: end for 1
+Parse_PushInput: .for loop in directive-for-escape.mk, line 152
+make: "directive-for-escape.mk" line 152: newline in .for value
+	in .for loop from directive-for-escape.mk:152 with i = "
+"
+For: loop body:
+: ${:U" "}
+SetFilenameVars: ${.PARSEDIR} = `<curdir>' ${.PARSEFILE} = `directive-for-escape.mk'
+Parsing line 153: : ${:U" "}
+ParseDependency(: " ")
+ParseEOF: returning to file directive-for-escape.mk, line 155
+SetFilenameVars: ${.PARSEDIR} = `<curdir>' ${.PARSEFILE} = `directive-for-escape.mk'
+Parsing line 155: .MAKEFLAGS: -d0
+ParseDependency(.MAKEFLAGS: -d0)
 make: Fatal errors encountered -- cannot continue
 make: stopped in unit-tests
 exit status 1
Index: src/usr.bin/make/unit-tests/directive-for-escape.mk
diff -u src/usr.bin/make/unit-tests/directive-for-escape.mk:1.12 src/usr.bin/make/unit-tests/directive-for-escape.mk:1.13
--- src/usr.bin/make/unit-tests/directive-for-escape.mk:1.12	Sun Dec  5 11:40:03 2021
+++ src/usr.bin/make/unit-tests/directive-for-escape.mk	Sun Jan  9 14:06:00 2022
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-escape.mk,v 1.12 2021/12/05 11:40:03 rillig Exp $
+# $NetBSD: directive-for-escape.mk,v 1.13 2022/01/09 14:06:00 rillig Exp $
 #
 # Test escaping of special characters in the iteration values of a .for loop.
 # These values get expanded later using the :U variable modifier, and this
@@ -139,4 +139,19 @@ ${closing-brace}=	<closing-brace>	# alte
 .  info long: ${i}
 .endfor
 
+# No error since the newline character is not actually used.
+.for i in "${.newline}"
+.endfor
+
+# Between for.c 1.161 from 2022-01-08 and before for.c 1.163 from 2022-01-09,
+# a newline character in a .for loop led to a crash since at the point where
+# the error message including the stack trace is printed, the body of the .for
+# loop is assembled, and at that point, ForLoop.nextItem had already been
+# advanced.
+.MAKEFLAGS: -dp
+.for i in "${.newline}"
+: $i
+.endfor
+.MAKEFLAGS: -d0
+
 all:

Reply via email to