Fix bug #2238: the read.c:eval() function was not entirely reentrant.

Apply patch #1022: fix a memory corruption on very long target-specific
variable definition lines.
This commit is contained in:
Paul Smith 2003-01-30 07:49:17 +00:00
parent b7c728046e
commit 1fa3db1468
6 changed files with 66 additions and 11 deletions

View File

@ -1,5 +1,13 @@
2003-01-30 Paul D. Smith <psmith@gnu.org> 2003-01-30 Paul D. Smith <psmith@gnu.org>
* read.c (eval): eval() was not fully reentrant, because the
collapsed buffer was static. Change it to be an automatic
variable so that eval() can be invoked recursively.
Fixes bug # 2238.
(eval): Apply patch # 1022: fix memory reference error on long
target-specific variable lines.
Patch provided by Steve Brown <Steve.Brown@macquarie.com>.
* function.c (check_numeric): Combine the is_numeric() function * function.c (check_numeric): Combine the is_numeric() function
into this function, since it's only called from one place. into this function, since it's only called from one place.
Constify this function. Have it print the incorrect string in the Constify this function. Have it print the incorrect string in the

18
read.c
View File

@ -452,8 +452,8 @@ eval_buffer (char *buffer)
static int static int
eval (struct ebuffer *ebuf, int set_default) eval (struct ebuffer *ebuf, int set_default)
{ {
static char *collapsed = 0; char *collapsed = 0;
static unsigned int collapsed_length = 0; unsigned int collapsed_length = 0;
unsigned int commands_len = 200; unsigned int commands_len = 200;
char *commands; char *commands;
unsigned int commands_idx = 0; unsigned int commands_idx = 0;
@ -566,9 +566,7 @@ eval (struct ebuffer *ebuf, int set_default)
if (collapsed_length < linelen+1) if (collapsed_length < linelen+1)
{ {
collapsed_length = linelen+1; collapsed_length = linelen+1;
if (collapsed != 0) collapsed = (char *) xrealloc (collapsed, collapsed_length);
free (collapsed);
collapsed = (char *) xmalloc (collapsed_length);
} }
strcpy (collapsed, line); strcpy (collapsed, line);
/* Collapse continuation lines. */ /* Collapse continuation lines. */
@ -1034,11 +1032,13 @@ eval (struct ebuffer *ebuf, int set_default)
of the unparsed section of p2, for later. */ of the unparsed section of p2, for later. */
if (*lb_next != '\0') if (*lb_next != '\0')
{ {
unsigned int l = p2 - variable_buffer; unsigned int l = p - variable_buffer;
unsigned int l2 = p2 - variable_buffer;
plen = strlen (p2); plen = strlen (p2);
(void) variable_buffer_output (p2+plen, (void) variable_buffer_output (p2+plen,
lb_next, strlen (lb_next)+1); lb_next, strlen (lb_next)+1);
p2 = variable_buffer + l; p = variable_buffer + l;
p2 = variable_buffer + l2;
} }
/* See if it's an "override" or "export" keyword; if so see if what /* See if it's an "override" or "export" keyword; if so see if what
@ -1069,9 +1069,11 @@ eval (struct ebuffer *ebuf, int set_default)
after it. */ after it. */
if (semip) if (semip)
{ {
unsigned int l = p - variable_buffer;
*(--semip) = ';'; *(--semip) = ';';
variable_buffer_output (p2 + strlen (p2), variable_buffer_output (p2 + strlen (p2),
semip, strlen (semip)+1); semip, strlen (semip)+1);
p = variable_buffer + l;
} }
record_target_var (filenames, p, two_colon, v_origin, exported, record_target_var (filenames, p, two_colon, v_origin, exported,
fstart); fstart);
@ -1234,6 +1236,8 @@ eval (struct ebuffer *ebuf, int set_default)
/* At eof, record the last rule. */ /* At eof, record the last rule. */
record_waiting_files (); record_waiting_files ();
if (collapsed)
free ((char *) collapsed);
free ((char *) commands); free ((char *) commands);
return 1; return 1;

View File

@ -1,5 +1,12 @@
2003-01-30 Paul D. Smith <psmith@gnu.org> 2003-01-30 Paul D. Smith <psmith@gnu.org>
* scripts/features/targetvars: Test very long target-specific
variable definition lines (longer than the default make buffer
length). Tests patch # 1022.
* scripts/functions/eval: Test very recursive $(eval ...) calls
with simple variable expansion (bug #2238).
* scripts/functions/word: Test error handling for word and * scripts/functions/word: Test error handling for word and
wordlist functions (bug #2407). wordlist functions (bug #2407).

View File

@ -248,4 +248,23 @@ $answer = "ok ok foo pat\nok ok foo pat\n";
&compare_output($answer, &get_logfile(1)); &compare_output($answer, &get_logfile(1));
# Test #16
# Test target-specific variables with very long command line
# (> make default buffer length)
$makefile7 = &get_tmpfile;
open(MAKEFILE, "> $makefile7");
print MAKEFILE <<'EOF';
base_metals_fmd_reports.sun5 base_metals_fmd_reports CreateRealPositions CreateMarginFunds deals_changed_since : BUILD_OBJ=$(shell if [ -f "build_information.generate" ]; then echo "$(OBJ_DIR)/build_information.o"; else echo "no build information"; fi )
deals_changed_since: ; @echo $(BUILD_OBJ)
EOF
close(MAKEFILE);
&run_make_with_options("$makefile7", '', &get_logfile);
$answer = "no build information\n";
&compare_output($answer, &get_logfile(1));
1; 1;

View File

@ -66,7 +66,6 @@ close(MAKEFILE);
&run_make_with_options($makefile, "", &get_logfile); &run_make_with_options($makefile, "", &get_logfile);
$answer = "foo bar\ndefault file file\nb d f\n\n\nb\nbar foo baz\nfoo bar baz blarp quux \n"; $answer = "foo bar\ndefault file file\nb d f\n\n\nb\nbar foo baz\nfoo bar baz blarp quux \n";
&compare_output($answer, &get_logfile(1)); &compare_output($answer, &get_logfile(1));
@ -94,10 +93,7 @@ EOF
close(MAKEFILE); close(MAKEFILE);
&run_make_with_options($makefile2, "", &get_logfile); &run_make_with_options($makefile2, "", &get_logfile);
# Create the answer to what should be produced by this Makefile
$answer = "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n"; $answer = "1 2 3 4 5 6 7 8 9\n1 2 3 4 5\n1 2 3\n1 2 3\n";
&compare_output($answer,&get_logfile(1)); &compare_output($answer,&get_logfile(1));
1; 1;

View File

@ -88,4 +88,25 @@ $answer = "it\n";
$answer = "it\nworked\n"; $answer = "it\nworked\n";
&compare_output($answer,&get_logfile(1)); &compare_output($answer,&get_logfile(1));
# TEST very recursive invocation of eval
$makefile3 = &get_tmpfile;
open(MAKEFILE,"> $makefile3");
print MAKEFILE <<'EOF';
..9 := 0 1 2 3 4 5 6 7 8 9
rev=$(eval res:=)$(foreach word,$1,$(eval res:=${word} ${res}))${res}
a:=$(call rev,${..9})
all: ; @echo '[$(a)]'
EOF
close(MAKEFILE);
&run_make_with_options($makefile3, "", &get_logfile);
$answer = "[ 9 8 7 6 5 4 3 2 1 0 ]\n";
&compare_output($answer,&get_logfile(1));
1; 1;