diff --git a/src/variable.c b/src/variable.c index e6822e44..841ff11b 100644 --- a/src/variable.c +++ b/src/variable.c @@ -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) { diff --git a/tests/scripts/features/se_explicit b/tests/scripts/features/se_explicit index 790017af..fad3da01 100644 --- a/tests/scripts/features/se_explicit +++ b/tests/scripts/features/se_explicit @@ -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;