summaryrefslogtreecommitdiff
path: root/src/variable.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2019-05-19 10:59:06 -0400
committerPaul Smith <psmith@gnu.org>2019-05-19 15:27:26 -0400
commitf32ca1666f12a053fece8f2ef5da45f3b1b5822c (patch)
treea363607af3a09a5767a74796e3f1be95febfc051 /src/variable.c
parent9ce370249bbdebfe246b04f9318b58852cfe0809 (diff)
downloadmake-git-f32ca1666f12a053fece8f2ef5da45f3b1b5822c.tar.gz
[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.
Diffstat (limited to 'src/variable.c')
-rw-r--r--src/variable.c34
1 files changed, 23 insertions, 11 deletions
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)
{