mirror of
https://github.com/mirror/make.git
synced 2025-03-10 01:30:37 +08:00
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:
parent
b7c728046e
commit
1fa3db1468
@ -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
18
read.c
@ -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;
|
||||||
|
@ -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).
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user