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/366a6079c424
branches:  trunk
changeset: 941902:366a6079c424
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 23d3a3c4c7ba -r 366a6079c424 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 23d3a3c4c7ba -r 366a6079c424 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 23d3a3c4c7ba -r 366a6079c424 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 23d3a3c4c7ba -r 366a6079c424 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 23d3a3c4c7ba -r 366a6079c424 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 23d3a3c4c7ba -r 366a6079c424 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 23d3a3c4c7ba -r 366a6079c424 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