From 1fa3db14684b18e50383be6a83a1f17f716b0788 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Thu, 30 Jan 2003 07:49:17 +0000 Subject: [PATCH] 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. --- ChangeLog | 8 ++++++++ read.c | 18 +++++++++++------- tests/ChangeLog | 7 +++++++ tests/scripts/features/targetvars | 19 +++++++++++++++++++ tests/scripts/functions/call | 4 ---- tests/scripts/functions/eval | 21 +++++++++++++++++++++ 6 files changed, 66 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8f7aef29..2b3ebc7e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,13 @@ 2003-01-30 Paul D. Smith + * 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 . + * function.c (check_numeric): Combine the is_numeric() function into this function, since it's only called from one place. Constify this function. Have it print the incorrect string in the diff --git a/read.c b/read.c index a0bf5caa..47d727b5 100644 --- a/read.c +++ b/read.c @@ -452,8 +452,8 @@ eval_buffer (char *buffer) static int eval (struct ebuffer *ebuf, int set_default) { - static char *collapsed = 0; - static unsigned int collapsed_length = 0; + char *collapsed = 0; + unsigned int collapsed_length = 0; unsigned int commands_len = 200; char *commands; unsigned int commands_idx = 0; @@ -566,9 +566,7 @@ eval (struct ebuffer *ebuf, int set_default) if (collapsed_length < linelen+1) { collapsed_length = linelen+1; - if (collapsed != 0) - free (collapsed); - collapsed = (char *) xmalloc (collapsed_length); + collapsed = (char *) xrealloc (collapsed, collapsed_length); } strcpy (collapsed, line); /* Collapse continuation lines. */ @@ -1034,11 +1032,13 @@ eval (struct ebuffer *ebuf, int set_default) of the unparsed section of p2, for later. */ 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); (void) variable_buffer_output (p2+plen, 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 @@ -1069,9 +1069,11 @@ eval (struct ebuffer *ebuf, int set_default) after it. */ if (semip) { + unsigned int l = p - variable_buffer; *(--semip) = ';'; variable_buffer_output (p2 + strlen (p2), semip, strlen (semip)+1); + p = variable_buffer + l; } record_target_var (filenames, p, two_colon, v_origin, exported, fstart); @@ -1234,6 +1236,8 @@ eval (struct ebuffer *ebuf, int set_default) /* At eof, record the last rule. */ record_waiting_files (); + if (collapsed) + free ((char *) collapsed); free ((char *) commands); return 1; diff --git a/tests/ChangeLog b/tests/ChangeLog index fe096107..39bf62fc 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,5 +1,12 @@ 2003-01-30 Paul D. Smith + * 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 wordlist functions (bug #2407). diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars index 2375f719..3989340c 100644 --- a/tests/scripts/features/targetvars +++ b/tests/scripts/features/targetvars @@ -248,4 +248,23 @@ $answer = "ok ok foo pat\nok ok foo pat\n"; &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; diff --git a/tests/scripts/functions/call b/tests/scripts/functions/call index efee4769..f3c54708 100644 --- a/tests/scripts/functions/call +++ b/tests/scripts/functions/call @@ -66,7 +66,6 @@ close(MAKEFILE); &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"; - &compare_output($answer, &get_logfile(1)); @@ -94,10 +93,7 @@ EOF close(MAKEFILE); &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"; - &compare_output($answer,&get_logfile(1)); 1; diff --git a/tests/scripts/functions/eval b/tests/scripts/functions/eval index 174767d7..cfb27b22 100644 --- a/tests/scripts/functions/eval +++ b/tests/scripts/functions/eval @@ -88,4 +88,25 @@ $answer = "it\n"; $answer = "it\nworked\n"; &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;