diff options
author | Paul Smith <psmith@gnu.org> | 2019-05-19 10:59:06 -0400 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2019-05-19 15:27:26 -0400 |
commit | f32ca1666f12a053fece8f2ef5da45f3b1b5822c (patch) | |
tree | a363607af3a09a5767a74796e3f1be95febfc051 /src/variable.c | |
parent | 9ce370249bbdebfe246b04f9318b58852cfe0809 (diff) | |
download | make-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.c | 34 |
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) { |