[SV 54549] Don't free used set_lists during merge

When merging the variable_set_lists for two targets it could be
that the "from" set list is a subset of the "to" set list: check
for this situation to avoid freeing used memory.

* src/variable.c (merge_variable_set_lists): Walk the "to" list and
if the "from" list is contained in it, nothing to do.
* tests/scripts/features/se_explicit: Add a test.
This commit is contained in:
Paul Smith 2019-05-19 10:59:06 -04:00
parent 9ce370249b
commit f32ca1666f
2 changed files with 49 additions and 11 deletions

View file

@ -782,22 +782,34 @@ merge_variable_set_lists (struct variable_set_list **setlist0,
struct variable_set_list *last0 = 0;
/* If there's nothing to merge, stop now. */
if (!setlist1)
if (!setlist1 || setlist1 == &global_setlist)
return;
/* This loop relies on the fact that all setlists terminate with the global
setlist (before NULL). If that's not true, arguably we SHOULD die. */
if (to)
while (setlist1 != &global_setlist && to != &global_setlist)
{
struct variable_set_list *from = setlist1;
setlist1 = setlist1->next;
{
/* These loops rely on the fact that all setlists terminate with the
global setlist (before NULL). If not, arguably we SHOULD die. */
merge_variable_sets (to->set, from->set);
/* Make sure that setlist1 is not already a subset of setlist0. */
while (to != &global_setlist)
{
if (to == setlist1)
return;
to = to->next;
}
last0 = to;
to = to->next;
}
to = *setlist0;
while (setlist1 != &global_setlist && to != &global_setlist)
{
struct variable_set_list *from = setlist1;
setlist1 = setlist1->next;
merge_variable_sets (to->set, from->set);
last0 = to;
to = to->next;
}
}
if (setlist1 != &global_setlist)
{

View file

@ -164,4 +164,30 @@ foo: $$(@\\:%=%.bar); @echo '$^'
!,
'', "foo.bar\n");
# SV 54549 : Ensure we don't free used variable_sets
run_make_test(q!
foo: -lcat
# Removing second expansion prevents segfault
.SECONDEXPANSION:
foo: $$@.o ;
# Having an empty command here prevents segfault unless,
# the environment is empty. `env -i make foo`
# MFLAGS=-w or MAKEFLAGS=-w `env MFLAGS=-w make foo`
# libcat.a target calls an extra command, `@true \n @touch $@`
# odd.
%.o: ; @true
# Having an empty command prevents segfault.
-l%: lib%.a ; @true
# Not creating libcat.a here prevents segfault,
libcat.a: ; @touch $@
!,
'', q!#MAKEFILE#:16: Recipe was specified for file '-lcat' at #MAKEFILE#:19,
#MAKEFILE#:16: but '-lcat' is now considered the same file as 'libcat.a'.
#MAKEFILE#:16: Recipe for 'libcat.a' will be ignored in favor of the one for '-lcat'.!);
unlink('libcat.a');
1;