[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.
This commit is contained in:
Paul Smith 2023-06-19 10:00:11 -04:00
parent 347316fdf6
commit 04f4c2b8d9
3 changed files with 13 additions and 8 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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) {