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.
This commit is contained in:
parent
aef5575359
commit
281951cf5a
|
@ -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 endc)
|
|||
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 *item, char endc)
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,17 +80,13 @@ make: "directive-for-escape.mk" line 118: eight $$$$ and no cents.
|
|||
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
|
||||
|
|
|
@ -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> # alternative interpretation
|
|||
.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}
|
||||
|
|
Loading…
Reference in New Issue