From 5ae02ff8c10e611aca7d5c6f60d3461aa0746694 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Tue, 3 Jan 2023 02:14:24 -0500 Subject: [PATCH] [SV 63609] Avoid buffer overrun in --warn-undefined-variables Reported by Dmitry Goncharov * src/variable.c (struct defined_vars): Create a struct that holds the name and length of each variable name. (warn_undefined): Check the lengths before comparing the contents. * tests/scripts/options/warn-undefined-variables: Add a test. --- src/variable.c | 30 ++++++++++++++----- .../scripts/options/warn-undefined-variables | 11 +++++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/variable.c b/src/variable.c index a0299639..009ee540 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1793,20 +1793,34 @@ try_variable_definition (const floc *flocp, const char *line, /* These variables are internal to make, and so considered "defined" for the purposes of warn_undefined even if they are not really defined. */ -static const char *const defined_vars[] = { - "MAKECMDGOALS", "MAKE_RESTARTS", "MAKE_TERMOUT", "MAKE_TERMERR", - "MAKEOVERRIDES", ".DEFAULT", "-*-command-variables-*-", "-*-eval-flags-*-", - "VPATH", "GPATH", - NULL }; +struct defined_vars + { + const char *name; + size_t len; + }; + +static const struct defined_vars defined_vars[] = { + { STRING_SIZE_TUPLE ("MAKECMDGOALS") }, + { STRING_SIZE_TUPLE ("MAKE_RESTARTS") }, + { STRING_SIZE_TUPLE ("MAKE_TERMOUT") }, + { STRING_SIZE_TUPLE ("MAKE_TERMERR") }, + { STRING_SIZE_TUPLE ("MAKEOVERRIDES") }, + { STRING_SIZE_TUPLE (".DEFAULT") }, + { STRING_SIZE_TUPLE ("-*-command-variables-*-") }, + { STRING_SIZE_TUPLE ("-*-eval-flags-*-") }, + { STRING_SIZE_TUPLE ("VPATH") }, + { STRING_SIZE_TUPLE ("GPATH") }, + { NULL, 0 } +}; void warn_undefined (const char *name, size_t len) { if (warn_undefined_variables_flag) { - const char *const *cp; - for (cp = defined_vars; *cp != NULL; ++cp) - if (memcmp (*cp, name, len) == 0 && (*cp)[len] == '\0') + const struct defined_vars *dp; + for (dp = defined_vars; dp->name != NULL; ++dp) + if (dp->len == len && memcmp (dp->name, name, len) == 0) return; error (reading_file, len, _("warning: undefined variable '%.*s'"), diff --git a/tests/scripts/options/warn-undefined-variables b/tests/scripts/options/warn-undefined-variables index 9bd40865..d9653d2c 100644 --- a/tests/scripts/options/warn-undefined-variables +++ b/tests/scripts/options/warn-undefined-variables @@ -35,4 +35,15 @@ run_make_test(undef, '--warn-undefined-variables', #MAKEFILE#:9: warning: undefined variable 'UNDEFINED' ref"); +# sv 63609. +# Test for buffer overrun in warn_undefined. +run_make_test(q! +all:; +X := $(averyveryverylongvariablename) +!, + '--warn-undefined-variables', + "#MAKEFILE#:3: warning: undefined variable 'averyveryverylongvariablename' +#MAKE#: 'all' is up to date.\n" +); + 1;