Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/make make(1): treat malformed :range, :ts and :[...]...
details: https://anonhg.NetBSD.org/src/rev/d21a3a281ef2
branches: trunk
changeset: 945564:d21a3a281ef2
user: rillig <rillig%NetBSD.org@localhost>
date: Sun Nov 01 14:36:25 2020 +0000
description:
make(1): treat malformed :range, :ts and :[...] as errors
Before, integer overflow in the :[1..2] modifier had not been detected,
and the actual behavior varied between ILP64 and LP64I32 machines.
Before, the :ts modifier accepted character literals like \012345 and
\x1F600, which don't fit in a single character and were thus truncated.
Before, the :range modifier issued an "Unknown modifier" error message
for :range=x, which was not quite correct. The error message in this
case is now "Invalid number".
diffstat:
usr.bin/make/unit-tests/moderrs.exp | 3 +-
usr.bin/make/unit-tests/moderrs.mk | 24 +++-
usr.bin/make/unit-tests/varmod-range.exp | 13 +-
usr.bin/make/unit-tests/varmod-range.mk | 12 +-
usr.bin/make/unit-tests/varmod-to-separator.exp | 20 ++-
usr.bin/make/unit-tests/varmod-to-separator.mk | 6 +-
usr.bin/make/var.c | 109 +++++++++++++++++++----
7 files changed, 136 insertions(+), 51 deletions(-)
diffs (truncated from 336 to 300 lines):
diff -r ed02a7ac2802 -r d21a3a281ef2 usr.bin/make/unit-tests/moderrs.exp
--- a/usr.bin/make/unit-tests/moderrs.exp Sun Nov 01 14:30:12 2020 +0000
+++ b/usr.bin/make/unit-tests/moderrs.exp Sun Nov 01 14:36:25 2020 +0000
@@ -45,7 +45,8 @@
make: Unfinished modifier for UNDEF (']' missing)
13=
-12345=ok
+make: Bad modifier `:[123451234512345123451234512345]' for UNDEF
+12345=S,^ok,:S,^3ok,}
exclam:
want: Unfinished modifier for VARNAME ('!' missing)
diff -r ed02a7ac2802 -r d21a3a281ef2 usr.bin/make/unit-tests/moderrs.mk
--- a/usr.bin/make/unit-tests/moderrs.mk Sun Nov 01 14:30:12 2020 +0000
+++ b/usr.bin/make/unit-tests/moderrs.mk Sun Nov 01 14:36:25 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: moderrs.mk,v 1.23 2020/11/01 10:56:08 rillig Exp $
+# $NetBSD: moderrs.mk,v 1.24 2020/11/01 14:36:25 rillig Exp $
#
# various modifier error tests
@@ -74,15 +74,21 @@
# Word index out of bounds.
#
- # On LP64I32, strtol returns LONG_MAX,
- # which is then truncated to int (undefined behavior),
- # typically resulting in -1.
- # This -1 is interpreted as "the last word".
+ # Until 2020-11-01, the behavior in this case depended upon the size
+ # of unsigned long.
+ #
+ # On LP64I32, strtol returns LONG_MAX, which was then truncated to
+ # int (undefined behavior), typically resulting in -1. This -1 was
+ # interpreted as "the last word".
#
- # On ILP32, strtol returns LONG_MAX,
- # which is a large number.
- # This results in a range from LONG_MAX - 1 to 3,
- # which is empty.
+ # On ILP32, strtol returns LONG_MAX, which is a large number. This
+ # resulted in a range from LONG_MAX - 1 to 3, which was empty.
+ #
+ # Since 2020-11-01, the numeric overflow is detected and generates an
+ # error. In the remainder of the text, the '$,' is no longer parsed
+ # as part of a variable modifier, where it would have been interpreted
+ # as an anchor to the :S modifier, but as a normal variable named ','.
+ # That variable is undefined, resulting in an empty string.
@echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,}
exclam: print-header print-footer
diff -r ed02a7ac2802 -r d21a3a281ef2 usr.bin/make/unit-tests/varmod-range.exp
--- a/usr.bin/make/unit-tests/varmod-range.exp Sun Nov 01 14:30:12 2020 +0000
+++ b/usr.bin/make/unit-tests/varmod-range.exp Sun Nov 01 14:36:25 2020 +0000
@@ -1,13 +1,14 @@
+make: "varmod-range.mk" line 53: Invalid number: x}Rest" != "Rest"
+
+make: "varmod-range.mk" line 53: Malformed conditional ("${:U:range=x}Rest" != "Rest")
make: Unknown modifier 'x'
-make: "varmod-range.mk" line 49: Malformed conditional ("${:U:range=x}Rest" != "Rest")
-make: Unknown modifier 'x'
-make: "varmod-range.mk" line 58: Malformed conditional ("${:U:range=0x0}Rest" != "Rest")
+make: "varmod-range.mk" line 62: Malformed conditional ("${:U:range=0x0}Rest" != "Rest")
make: Unknown modifier 'r'
-make: "varmod-range.mk" line 74: Malformed conditional ("${a b c:L:rang}Rest" != "Rest")
+make: "varmod-range.mk" line 78: Malformed conditional ("${a b c:L:rang}Rest" != "Rest")
make: Unknown modifier 'r'
-make: "varmod-range.mk" line 81: Malformed conditional ("${a b c:L:rango}Rest" != "Rest")
+make: "varmod-range.mk" line 85: Malformed conditional ("${a b c:L:rango}Rest" != "Rest")
make: Unknown modifier 'r'
-make: "varmod-range.mk" line 88: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest")
+make: "varmod-range.mk" line 92: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest")
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff -r ed02a7ac2802 -r d21a3a281ef2 usr.bin/make/unit-tests/varmod-range.mk
--- a/usr.bin/make/unit-tests/varmod-range.mk Sun Nov 01 14:30:12 2020 +0000
+++ b/usr.bin/make/unit-tests/varmod-range.mk Sun Nov 01 14:36:25 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-range.mk,v 1.6 2020/11/01 13:55:31 rillig Exp $
+# $NetBSD: varmod-range.mk,v 1.7 2020/11/01 14:36:25 rillig Exp $
#
# Tests for the :range variable modifier, which generates sequences
# of integers from the given range.
@@ -43,9 +43,13 @@
#.endif
# The :range modifier requires a number as parameter.
-# As of 2020-11-01, the parser tries to read the 'x' as a number, fails and
-# stops there. It then tries to parse the next modifier at that point,
-# which fails with the message "Unknown modifier".
+#
+# Until 2020-11-01, the parser tried to read the 'x' as a number, failed and
+# stopped there. It then tried to parse the next modifier at that point,
+# which failed with the message "Unknown modifier".
+#
+# Since 2020-11-01, the parser issues a more precise "Invalid number" error
+# instead.
.if "${:U:range=x}Rest" != "Rest"
. error
.else
diff -r ed02a7ac2802 -r d21a3a281ef2 usr.bin/make/unit-tests/varmod-to-separator.exp
--- a/usr.bin/make/unit-tests/varmod-to-separator.exp Sun Nov 01 14:30:12 2020 +0000
+++ b/usr.bin/make/unit-tests/varmod-to-separator.exp Sun Nov 01 14:36:25 2020 +0000
@@ -1,17 +1,21 @@
-make: "varmod-to-separator.mk" line 106: warning: The separator \400 is accepted even though it is out of bounds.
-make: "varmod-to-separator.mk" line 118: warning: The separator \x100 is accepted even though it is out of bounds.
+make: "varmod-to-separator.mk" line 107: Invalid character number: 400:tu}
+
+make: "varmod-to-separator.mk" line 107: Malformed conditional (${WORDS:[1..3]:ts\400:tu})
+make: "varmod-to-separator.mk" line 121: Invalid character number: 100:tu}
+
+make: "varmod-to-separator.mk" line 121: Malformed conditional (${WORDS:[1..3]:ts\x100:tu})
make: Bad modifier `:ts\-300' for WORDS
-make: "varmod-to-separator.mk" line 124: Malformed conditional (${WORDS:[1..3]:ts\-300:tu})
+make: "varmod-to-separator.mk" line 128: Malformed conditional (${WORDS:[1..3]:ts\-300:tu})
make: Bad modifier `:ts\8' for 1 2 3
-make: "varmod-to-separator.mk" line 132: Malformed conditional (${1 2 3:L:ts\8:tu})
+make: "varmod-to-separator.mk" line 136: Malformed conditional (${1 2 3:L:ts\8:tu})
make: Bad modifier `:ts\100L' for 1 2 3
-make: "varmod-to-separator.mk" line 139: Malformed conditional (${1 2 3:L:ts\100L})
+make: "varmod-to-separator.mk" line 143: Malformed conditional (${1 2 3:L:ts\100L})
make: Bad modifier `:ts\x40g' for 1 2 3
-make: "varmod-to-separator.mk" line 146: Malformed conditional (${1 2 3:L:ts\x40g})
+make: "varmod-to-separator.mk" line 150: Malformed conditional (${1 2 3:L:ts\x40g})
make: Bad modifier `:tx' for WORDS
-make: "varmod-to-separator.mk" line 154: Malformed conditional (${WORDS:tx} != "anything")
+make: "varmod-to-separator.mk" line 158: Malformed conditional (${WORDS:tx} != "anything")
make: Bad modifier `:t\X' for WORDS
-make: "varmod-to-separator.mk" line 161: Malformed conditional (${WORDS:t\X} != "anything")
+make: "varmod-to-separator.mk" line 165: Malformed conditional (${WORDS:t\X} != "anything")
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff -r ed02a7ac2802 -r d21a3a281ef2 usr.bin/make/unit-tests/varmod-to-separator.mk
--- a/usr.bin/make/unit-tests/varmod-to-separator.mk Sun Nov 01 14:30:12 2020 +0000
+++ b/usr.bin/make/unit-tests/varmod-to-separator.mk Sun Nov 01 14:36:25 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-to-separator.mk,v 1.5 2020/11/01 13:28:50 rillig Exp $
+# $NetBSD: varmod-to-separator.mk,v 1.6 2020/11/01 14:36:25 rillig Exp $
#
# Tests for the :ts variable modifier, which joins the words of the variable
# using an arbitrary character as word separator.
@@ -102,6 +102,8 @@
# The value of the separator character must not be outside the value space
# for an unsigned character though.
+#
+# Since 2020-11-01, these out-of-bounds values are rejected.
.if ${WORDS:[1..3]:ts\400:tu}
. warning The separator \400 is accepted even though it is out of bounds.
.else
@@ -114,6 +116,8 @@
.endif
# The hexadecimal number must be in the range of an unsigned char.
+#
+# Since 2020-11-01, these out-of-bounds values are rejected.
.if ${WORDS:[1..3]:ts\x100:tu}
. warning The separator \x100 is accepted even though it is out of bounds.
.else
diff -r ed02a7ac2802 -r d21a3a281ef2 usr.bin/make/var.c
--- a/usr.bin/make/var.c Sun Nov 01 14:30:12 2020 +0000
+++ b/usr.bin/make/var.c Sun Nov 01 14:36:25 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.634 2020/11/01 13:55:31 rillig Exp $ */
+/* $NetBSD: var.c,v 1.635 2020/11/01 14:36:25 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -130,7 +130,7 @@
#include "metachar.h"
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.634 2020/11/01 13:55:31 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.635 2020/11/01 14:36:25 rillig Exp $");
#define VAR_DEBUG1(fmt, arg1) DEBUG1(VAR, fmt, arg1)
#define VAR_DEBUG2(fmt, arg1, arg2) DEBUG2(VAR, fmt, arg1, arg2)
@@ -2006,6 +2006,66 @@
(mod[n] == endc || mod[n] == ':' || mod[n] == '=');
}
+static Boolean
+TryParseIntBase0(const char **pp, int *out_num)
+{
+ char *end;
+ long n;
+
+ errno = 0;
+ n = strtol(*pp, &end, 0);
+ if ((n == LONG_MIN || n == LONG_MAX) && errno == ERANGE)
+ return FALSE;
+ if (n < INT_MIN || n > INT_MAX)
+ return FALSE;
+
+ *pp = end;
+ *out_num = (int)n;
+ return TRUE;
+}
+
+static Boolean
+TryParseSize(const char **pp, size_t *out_num)
+{
+ char *end;
+ unsigned long n;
+
+ if (!ch_isdigit(**pp))
+ return FALSE;
+
+ errno = 0;
+ n = strtoul(*pp, &end, 10);
+ if (n == ULONG_MAX && errno == ERANGE)
+ return FALSE;
+ if (n > SIZE_MAX)
+ return FALSE;
+
+ *pp = end;
+ *out_num = (size_t)n;
+ return TRUE;
+}
+
+static Boolean
+TryParseChar(const char **pp, int base, char *out_ch)
+{
+ char *end;
+ unsigned long n;
+
+ if (!ch_isalnum(**pp))
+ return FALSE;
+
+ errno = 0;
+ n = strtoul(*pp, &end, base);
+ if (n == ULONG_MAX && errno == ERANGE)
+ return FALSE;
+ if (n > UCHAR_MAX)
+ return FALSE;
+
+ *pp = end;
+ *out_ch = (char)n;
+ return TRUE;
+}
+
/* :@var@...${var}...@ */
static ApplyModifierResult
ApplyModifier_Loop(const char **pp, ApplyModifiersState *st)
@@ -2263,9 +2323,12 @@
return AMR_UNKNOWN;
if (mod[5] == '=') {
- char *ep;
- n = (size_t)strtoul(mod + 6, &ep, 10);
- *pp = ep;
+ const char *p = mod + 6;
+ if (!TryParseSize(&p, &n)) {
+ Parse_Error(PARSE_FATAL, "Invalid number: %s\n", mod + 6);
+ return AMR_CLEANUP;
+ }
+ *pp = p;
} else {
n = 0;
*pp = mod + 5;
@@ -2562,24 +2625,27 @@
/* ":ts\x40" or ":ts\100" */
{
- const char *numStart = sep + 1;
+ const char *p = sep + 1;
int base = 8; /* assume octal */
- char *end;
if (sep[1] == 'x') {
base = 16;
- numStart++;
+ p++;
} else if (!ch_isdigit(sep[1])) {
(*pp)++; /* just for backwards compatibility */
return AMR_BAD; /* ":ts<backslash><unrecognised>". */
}
- st->sep = (char)strtoul(numStart, &end, base);
- if (*end != ':' && *end != st->endc) {
+ if (!TryParseChar(&p, base, &st->sep)) {
+ Parse_Error(PARSE_FATAL, "Invalid character number: %s\n", p);
+ return AMR_CLEANUP;
+ }
+ if (*p != ':' && *p != st->endc) {
(*pp)++; /* just for backwards compatibility */
return AMR_BAD;
}
- *pp = end;
+
+ *pp = p;
}
ok:
@@ -2653,9 +2719,9 @@
ApplyModifier_Words(const char **pp, ApplyModifiersState *st)
{
Home |
Main Index |
Thread Index |
Old Index