From 1c26adb74dd3c09b755dd8d224d7a028155b110e Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 2 Jun 2017 08:10:48 +0000 Subject: [PATCH] re PR libstdc++/80721 (Sorting/Merging of free EH-emergency buffer may wrong or uncomplete) 2017-06-02 Richard Biener Markus Eisenmann PR libstdc++/80721 * libsupc++/eh_alloc.cc (pool::free): Keep list properly sorted and add missing freelist item merging cases. Co-Authored-By: Markus Eisenmann From-SVN: r248816 --- libstdc++-v3/ChangeLog | 7 +++++++ libstdc++-v3/libsupc++/eh_alloc.cc | 22 +++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index dbbba5a17cb..d347561534c 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2017-06-02 Richard Biener + Markus Eisenmann + + PR libstdc++/80721 + * libsupc++/eh_alloc.cc (pool::free): Keep list properly + sorted and add missing freelist item merging cases. + 2017-06-01 Rainer Orth (GLIBCXX_CROSSCONFIG): Handle *-solaris* like *-linux* etc. diff --git a/libstdc++-v3/libsupc++/eh_alloc.cc b/libstdc++-v3/libsupc++/eh_alloc.cc index d03cbcef9b0..4b38f98845a 100644 --- a/libstdc++-v3/libsupc++/eh_alloc.cc +++ b/libstdc++-v3/libsupc++/eh_alloc.cc @@ -162,7 +162,7 @@ namespace allocated_entry *x; if ((*e)->size - size >= sizeof (free_entry)) { - // Slit block if it is too large. + // Split block if it is too large. free_entry *f = reinterpret_cast (reinterpret_cast (*e) + size); std::size_t sz = (*e)->size; @@ -194,13 +194,17 @@ namespace allocated_entry *e = reinterpret_cast (reinterpret_cast (data) - offsetof (allocated_entry, data)); std::size_t sz = e->size; - if (!first_free_entry) + if (!first_free_entry + || (reinterpret_cast (e) + sz + < reinterpret_cast (first_free_entry))) { - // If the free list is empty just put the entry there. + // If the free list is empty or the entry is before the + // first element and cannot be merged with it add it as + // the first free entry. free_entry *f = reinterpret_cast (e); new (f) free_entry; f->size = sz; - f->next = NULL; + f->next = first_free_entry; first_free_entry = f; } else if (reinterpret_cast (e) + sz @@ -224,9 +228,17 @@ namespace > reinterpret_cast (e) + sz); fe = &(*fe)->next) ; + // If we can merge the next block into us do so and continue + // with the cases below. + if (reinterpret_cast (e) + sz + == reinterpret_cast ((*fe)->next)) + { + sz += (*fe)->next->size; + (*fe)->next = (*fe)->next->next; + } if (reinterpret_cast (*fe) + (*fe)->size == reinterpret_cast (e)) - /* Merge with the freelist entry. */ + // Merge with the freelist entry. (*fe)->size += sz; else {