Save strings we're expanding in case an embedded eval causes them

to be freed (if they're the value of a variable that's reset for example).
See Savannah patch #7534
This commit is contained in:
Paul Smith 2011-08-29 16:20:19 +00:00
parent b06b8c64a2
commit e4d5d43424
4 changed files with 42 additions and 34 deletions

View file

@ -1,3 +1,11 @@
2011-08-29 Paul Smith <psmith@gnu.org>
* expand.c (variable_expand_string): Always allocate a new buffer
for a string we're expanding. The string we're working on can get
freed while we work on it (for example if it's the value of a
variable which modifies itself using an eval operation).
See Savannah patch #7534 for the original report by Lubomir Rintel.
2011-06-12 Paul Smith <psmith@gnu.org> 2011-06-12 Paul Smith <psmith@gnu.org>
* read.c (parse_file_seq): Move the check for empty members out of * read.c (parse_file_seq): Move the check for empty members out of

View file

@ -197,7 +197,7 @@ variable_expand_string (char *line, const char *string, long length)
{ {
struct variable *v; struct variable *v;
const char *p, *p1; const char *p, *p1;
char *abuf = NULL; char *save;
char *o; char *o;
unsigned int line_offset; unsigned int line_offset;
@ -212,16 +212,11 @@ variable_expand_string (char *line, const char *string, long length)
return (variable_buffer); return (variable_buffer);
} }
/* If we want a subset of the string, allocate a temporary buffer for it. /* We need a copy of STRING: due to eval, it's possible that it will get
Most of the functions we use here don't work with length limits. */ freed as we process it (it might be the value of a variable that's reset
if (length > 0 && string[length] != '\0') for example). Also having a nil-terminated string is handy. */
{ save = length < 0 ? xstrdup (string) : xstrndup (string, length);
abuf = xmalloc(length+1); p = save;
memcpy(abuf, string, length);
abuf[length] = '\0';
string = abuf;
}
p = string;
while (1) while (1)
{ {
@ -411,8 +406,7 @@ variable_expand_string (char *line, const char *string, long length)
++p; ++p;
} }
if (abuf) free (save);
free (abuf);
variable_buffer_output (o, "", 1); variable_buffer_output (o, "", 1);
return (variable_buffer + line_offset); return (variable_buffer + line_offset);

View file

@ -1,3 +1,8 @@
2011-08-29 Paul Smith <psmith@gnu.org>
* scripts/features/varnesting: Test resetting of variables while
expanding them. See Savannah patch #7534
2011-06-12 Paul Smith <psmith@gnu.org> 2011-06-12 Paul Smith <psmith@gnu.org>
* scripts/features/archives: Check archives with whitespace at the * scripts/features/archives: Check archives with whitespace at the

View file

@ -1,29 +1,30 @@
$description = "The following test creates a makefile to ..."; # -*-perl-*-
$description = "Test recursive variables";
$details = ""; $details = "";
open(MAKEFILE,"> $makefile"); run_make_test('
x = variable1
variable2 := Hello
y = $(subst 1,2,$(x))
z = y
a := $($($(z)))
all:
@echo $(a)
',
'', "Hello\n");
# The Contents of the MAKEFILE ... # This tests resetting the value of a variable while expanding it.
# You may only see problems with this if you're using valgrind or
# some other memory checker that poisons freed memory.
# See Savannah patch #7534
print MAKEFILE "x = variable1\n" run_make_test('
."variable2 := Hello\n" VARIABLE = $(eval VARIABLE := echo hi)$(VARIABLE)
."y = \$(subst 1,2,\$(x))\n" wololo:
."z = y\n" @$(VARIABLE)
."a := \$(\$(\$(z)))\n" ',
."all: \n" '', "hi\n");
."\t\@echo \$(a)\n";
# END of Contents of MAKEFILE
close(MAKEFILE);
&run_make_with_options($makefile,"",&get_logfile);
# Create the answer to what should be produced by this Makefile
$answer = "Hello\n";
&compare_output($answer,&get_logfile(1));
1; 1;