Module Name: src Committed By: rillig Date: Fri Jun 25 16:10:07 UTC 2021
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: prevent newline injection in .for loops When a value of a .for loop contained a literal newline, such as from the expression ${.newline}, that newline was passed verbatim to the "expanded current body" of the .for loop. There it was interpreted as a literal newline, which ended the current line and started a new one. This resulted in several syntax errors. In cases like these, print a more precise error message. To generate a diff of this commit: cvs rdiff -u -r1.143 -r1.144 src/usr.bin/make/for.c cvs rdiff -u -r1.10 -r1.11 \ src/usr.bin/make/unit-tests/directive-for-escape.exp cvs rdiff -u -r1.9 -r1.10 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.143 src/usr.bin/make/for.c:1.144 --- src/usr.bin/make/for.c:1.143 Thu Jun 24 23:19:52 2021 +++ src/usr.bin/make/for.c Fri Jun 25 16:10:07 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: for.c,v 1.143 2021/06/24 23:19:52 rillig Exp $ */ +/* $NetBSD: for.c,v 1.144 2021/06/25 16:10:07 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.143 2021/06/24 23:19:52 rillig Exp $"); +MAKE_RCSID("$NetBSD: for.c,v 1.144 2021/06/25 16:10:07 rillig Exp $"); /* One of the variables to the left of the "in" in a .for loop. */ @@ -325,7 +325,8 @@ NeedsEscapes(const char *value, char end const char *p; for (p = value; *p != '\0'; p++) { - if (*p == ':' || *p == '$' || *p == '\\' || *p == endc) + if (*p == ':' || *p == '$' || *p == '\\' || *p == endc || + *p == '\n') return true; } return false; @@ -360,6 +361,10 @@ Buf_AddEscaped(Buffer *cmds, const char Buf_AddByte(cmds, '\\'); } else if (ch == ':' || ch == '\\' || ch == endc) Buf_AddByte(cmds, '\\'); + else if (ch == '\n') { + Parse_Error(PARSE_FATAL, "newline in .for value"); + ch = ' '; /* prevent newline injection */ + } Buf_AddByte(cmds, ch); } } Index: src/usr.bin/make/unit-tests/directive-for-escape.exp diff -u src/usr.bin/make/unit-tests/directive-for-escape.exp:1.10 src/usr.bin/make/unit-tests/directive-for-escape.exp:1.11 --- src/usr.bin/make/unit-tests/directive-for-escape.exp:1.10 Fri Jun 25 15:56:02 2021 +++ src/usr.bin/make/unit-tests/directive-for-escape.exp Fri Jun 25 16:10:07 2021 @@ -80,17 +80,13 @@ make: "directive-for-escape.mk" line 118 make: "directive-for-escape.mk" line 119: eight dollardollardollardollar and no cents. make: "directive-for-escape.mk" line 128: eight and no cents. For: end for 1 +make: "directive-for-escape.mk" line 135: newline in .for value +make: "directive-for-escape.mk" line 135: newline in .for value For: loop body: -. info short: ${:U" -"} -. info long: ${:U" -"} -make: Unclosed variable expression, expecting '}' for modifier "U"" of variable "" with value """ -make: "directive-for-escape.mk" line 134: short: " -make: "directive-for-escape.mk" line 135: Invalid line type -make: Unclosed variable expression, expecting '}' for modifier "U"" of variable "" with value """ -make: "directive-for-escape.mk" line 136: long: " -make: "directive-for-escape.mk" line 137: Invalid line type +. info short: ${:U" "} +. info long: ${:U" "} +make: "directive-for-escape.mk" line 136: short: " " +make: "directive-for-escape.mk" line 137: long: " " 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.9 src/usr.bin/make/unit-tests/directive-for-escape.mk:1.10 --- src/usr.bin/make/unit-tests/directive-for-escape.mk:1.9 Fri Jun 25 15:56:02 2021 +++ src/usr.bin/make/unit-tests/directive-for-escape.mk Fri Jun 25 16:10:07 2021 @@ -1,4 +1,4 @@ -# $NetBSD: directive-for-escape.mk,v 1.9 2021/06/25 15:56:02 rillig Exp $ +# $NetBSD: directive-for-escape.mk,v 1.10 2021/06/25 16:10:07 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 @@ -128,8 +128,10 @@ ${closing-brace}= <closing-brace> # alte .info eight ${$}${$}${$}${$} and no cents. # What happens if the values from the .for loop contain a literal newline? -# Oops, the newline is added verbatim to the loop body, where it is later -# interpreted as an ordinary newline. +# Before for.c 1.144 from 2021-06-25, the newline was passed verbatim to the +# body of the .for loop, where it was then interpreted as a literal newline, +# leading to syntax errors such as "Unclosed variable expression" in the upper +# line and "Invalid line type" in the lower line. .for i in "${.newline}" . info short: $i . info long: ${i}