summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2003-01-30 07:49:17 +0000
committerPaul Smith <psmith@gnu.org>2003-01-30 07:49:17 +0000
commit1fa3db14684b18e50383be6a83a1f17f716b0788 (patch)
tree8ba77c275874f57a1429145c1f4381135bc80820
parentb7c728046e3f32cd93b04fa4a19a69cf6135e6e4 (diff)
downloadgunmake-1fa3db14684b18e50383be6a83a1f17f716b0788.tar.gz
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.
-rw-r--r--ChangeLog8
-rw-r--r--read.c18
-rw-r--r--tests/ChangeLog7
-rw-r--r--tests/scripts/features/targetvars19
-rw-r--r--tests/scripts/functions/call4
-rw-r--r--tests/scripts/functions/eval21
6 files changed, 66 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index 8f7aef2..2b3ebc7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
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
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 a0bf5ca..47d727b 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 fe09610..39bf62f 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,5 +1,12 @@
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
wordlist functions (bug #2407).
diff --git a/tests/scripts/features/targetvars b/tests/scripts/features/targetvars
index 2375f71..3989340 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 efee476..f3c5470 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 174767d..cfb27b2 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;