From 04f4c2b8d95e895270b612b5ea3841ee4d3dcc26 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Mon, 19 Jun 2023 10:00:11 -0400 Subject: [PATCH] [SV 64124] Avoid stack overflows for large command lines Modify areas dealing with large command lines to use the heap rather than relying on alloca / stack space. * src/main.c (main): Allocate potentially large buffers with xmalloc. (decode_env_switches): Ditto. * src/function.c (func_error): Replace alloca with xmalloc/free. * tests/scripts/features/expand: Add a newline for readable diffs. --- src/function.c | 3 ++- src/main.c | 14 +++++++++----- tests/scripts/features/expand | 4 ++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/function.c b/src/function.c index d4636d73..3b355a33 100644 --- a/src/function.c +++ b/src/function.c @@ -1175,11 +1175,12 @@ func_error (char *o, char **argv, const char *funcname) case 'i': { size_t len = strlen (argv[0]); - char *msg = alloca (len + 2); + char *msg = xmalloc (len + 2); memcpy (msg, argv[0], len); msg[len] = '\n'; msg[len + 1] = '\0'; outputs (0, msg); + free (msg); break; } diff --git a/src/main.c b/src/main.c index 39e511ff..1fba1c21 100644 --- a/src/main.c +++ b/src/main.c @@ -1879,7 +1879,7 @@ main (int argc, char **argv, char **envp) } /* Now allocate a buffer big enough and fill it. */ - p = value = alloca (len); + p = value = xmalloc (len); for (cv = command_variables; cv != 0; cv = cv->next) { v = cv->variable; @@ -1895,6 +1895,7 @@ main (int argc, char **argv, char **envp) /* Define an unchangeable variable with a name that no POSIX.2 makefile could validly use for its own variable. */ define_variable_cname ("-*-command-variables-*-", value, o_automatic, 0); + free (value); /* Define the variable; this will not override any user definition. Normally a reference to this variable is written into the value of @@ -2041,7 +2042,7 @@ main (int argc, char **argv, char **envp) free (p); } - p = endp = value = alloca (len); + p = endp = value = xmalloc (len); for (i = 0; i < eval_strings->idx; ++i) { p = stpcpy (p, "--eval="); @@ -2052,6 +2053,7 @@ main (int argc, char **argv, char **envp) *endp = '\0'; define_variable_cname ("-*-eval-flags-*-", value, o_automatic, 0); + free (value); } { @@ -3374,8 +3376,8 @@ decode_env_switches (const char *envar, size_t len, enum variable_origin origin) if (len == 0) return; - /* Allocate a vector that is definitely big enough. */ - argv = alloca ((1 + len + 1) * sizeof (char *)); + /* Allocate an array that is definitely big enough. */ + argv = xmalloc ((1 + len + 1) * sizeof (char *)); /* getopt will look at the arguments starting at ARGV[1]. Prepend a spacer word. */ @@ -3384,7 +3386,7 @@ decode_env_switches (const char *envar, size_t len, enum variable_origin origin) /* We need a buffer to copy the value into while we split it into words and unquote it. Set up in case we need to prepend a dash later. */ - buf = alloca (1 + len + 1); + buf = xmalloc (1 + len + 1); buf[0] = '-'; p = buf+1; argv[argc] = p; @@ -3415,6 +3417,8 @@ decode_env_switches (const char *envar, size_t len, enum variable_origin origin) /* Parse those words. */ decode_switches (argc, argv, origin); + free (buf); + free (argv); } /* Quote the string IN so that it will be interpreted as a single word with diff --git a/tests/scripts/features/expand b/tests/scripts/features/expand index 64b9a890..1d933530 100644 --- a/tests/scripts/features/expand +++ b/tests/scripts/features/expand @@ -7,9 +7,9 @@ $description = "Test variable expansion."; # 200 is the initial size of variable_buffer. # Value bigger than 200 bytes causes a realloc of variable_buffer. # In this test the variable being expanded is MAKEFLAGS and its value occupies -# 11, 550 and 110000 bytes. +# 12, 600 and 120000 bytes. -my $s = "hello_world"; +my $s = "hello_world\n"; my @mult = (1, 50, 10000); for my $m (@mult) { -- 2.47.3