Ensure variable_buffer is always nul-terminated

* src/expand.c (variable_buffer_output): Allocate an extra byte and
set it to nul.  For safety, add assert() on PTR.
(variable_expand_string): Don't call variable_buffer_output just to
add a nul byte.
(allocated_variable_append): Ditto.
This commit is contained in:
Paul Smith 2023-03-26 09:24:06 -04:00
parent 3088e3e698
commit a367c0640f
3 changed files with 24 additions and 22 deletions

View File

@ -46,29 +46,33 @@ const floc **expanding_var = &reading_file;
static size_t variable_buffer_length; static size_t variable_buffer_length;
char *variable_buffer; char *variable_buffer;
/* Subroutine of variable_expand and friends: /* Append LENGTH chars of STRING at PTR which must point into variable_buffer.
The text to add is LENGTH chars starting at STRING to the variable_buffer. The buffer will always be kept nul-terminated.
The text is added to the buffer at PTR, and the updated pointer into The updated pointer into the buffer is returned as the value. Thus, the
the buffer is returned as the value. Thus, the value returned by value returned by each call to variable_buffer_output should be the first
each call to variable_buffer_output should be the first argument to argument to the following call. */
the following call. */
char * char *
variable_buffer_output (char *ptr, const char *string, size_t length) variable_buffer_output (char *ptr, const char *string, size_t length)
{ {
size_t newlen = length + (ptr - variable_buffer); size_t newlen = length + (ptr - variable_buffer);
if ((newlen + VARIABLE_BUFFER_ZONE) > variable_buffer_length) assert (ptr >= variable_buffer);
assert (ptr < variable_buffer + variable_buffer_length);
if (newlen + VARIABLE_BUFFER_ZONE + 1 > variable_buffer_length)
{ {
size_t offset = ptr - variable_buffer; size_t offset = ptr - variable_buffer;
variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length variable_buffer_length = (newlen + 100 > 2 * variable_buffer_length
? newlen + 100 ? newlen + 100
: 2 * variable_buffer_length); : 2 * variable_buffer_length);
variable_buffer = xrealloc (variable_buffer, variable_buffer_length); variable_buffer = xrealloc (variable_buffer, variable_buffer_length + 1);
ptr = variable_buffer + offset; ptr = variable_buffer + offset;
} }
return mempcpy (ptr, string, length); ptr = mempcpy (ptr, string, length);
*ptr = '\0';
return ptr;
} }
/* Return a pointer to the beginning of the variable buffer. /* Return a pointer to the beginning of the variable buffer.
@ -83,9 +87,10 @@ initialize_variable_output ()
{ {
variable_buffer_length = 200; variable_buffer_length = 200;
variable_buffer = xmalloc (variable_buffer_length); variable_buffer = xmalloc (variable_buffer_length);
variable_buffer[0] = '\0';
} }
variable_buffer[0] = '\0';
return variable_buffer; return variable_buffer;
} }
@ -229,10 +234,7 @@ variable_expand_string (char *line, const char *string, size_t length)
line_offset = line - variable_buffer; line_offset = line - variable_buffer;
if (length == 0) if (length == 0)
{
variable_buffer_output (o, "", 1);
return variable_buffer; return variable_buffer;
}
/* We need a copy of STRING: due to eval, it's possible that it will get /* We need a copy of STRING: due to eval, it's possible that it will get
freed as we process it (it might be the value of a variable that's reset freed as we process it (it might be the value of a variable that's reset
@ -426,7 +428,6 @@ variable_expand_string (char *line, const char *string, size_t length)
free (save); free (save);
variable_buffer_output (o, "", 1);
return (variable_buffer + line_offset); return (variable_buffer + line_offset);
} }
@ -563,9 +564,8 @@ allocated_variable_append (const struct variable *v)
variable_buffer = 0; variable_buffer = 0;
val = variable_append (v->name, strlen (v->name), variable_append (v->name, strlen (v->name), current_variable_set_list, 1);
current_variable_set_list, 1);
variable_buffer_output (val, "", 1);
val = variable_buffer; val = variable_buffer;
variable_buffer = obuf; variable_buffer = obuf;
@ -604,7 +604,7 @@ install_variable_buffer (char **bufp, size_t *lenp)
*bufp = variable_buffer; *bufp = variable_buffer;
*lenp = variable_buffer_length; *lenp = variable_buffer_length;
variable_buffer = 0; variable_buffer = NULL;
initialize_variable_output (); initialize_variable_output ();
} }

View File

@ -2011,7 +2011,8 @@ static char *
func_eq (char *o, char **argv, char *funcname UNUSED) func_eq (char *o, char **argv, char *funcname UNUSED)
{ {
int result = ! strcmp (argv[0], argv[1]); int result = ! strcmp (argv[0], argv[1]);
o = variable_buffer_output (o, result ? "1" : "", result); if (result)
o = variable_buffer_output (o, "1", 1);
return o; return o;
} }
@ -2026,7 +2027,8 @@ func_not (char *o, char **argv, char *funcname UNUSED)
int result = 0; int result = 0;
NEXT_TOKEN (s); NEXT_TOKEN (s);
result = ! (*s); result = ! (*s);
o = variable_buffer_output (o, result ? "1" : "", result); if (result)
o = variable_buffer_output (o, "1", 1);
return o; return o;
} }
#endif #endif

View File

@ -1278,7 +1278,7 @@ shell_result (const char *p)
args[0] = (char *) p; args[0] = (char *) p;
args[1] = NULL; args[1] = NULL;
variable_buffer_output (func_shell_base (variable_buffer, args, 0), "\0", 1); func_shell_base (variable_buffer, args, 0);
result = strdup (variable_buffer); result = strdup (variable_buffer);
restore_variable_buffer (buf, len); restore_variable_buffer (buf, len);