On 12/05/17 12:10 +0200, Richard Biener wrote:
It was pointed out by Markus that the EH emergency pool is not kept sorted and fully merged properly for the cases of freeing an entry before the first free entry and for the cases where merging with the immediate successor and for the case with merging with both successor and predecessor is possible. The following patch attempts to fix this. Bootstrap and regtest running on x86_64-unknown-linux-gnu. Ok for trunk? (given low / close to no testing coverage extra close eyes wanted!) Reporter says maybe it can't happen in real-life as it requires EH deallocation order not be the reverse of allocation order. I don't know enough here for a quick guess but "in C++ everything is possible" ;)
I think it's possible with this testcase: #include <exception> int main() { std::exception_ptr p[3]; for (auto& e : p) try { throw 1; } catch (...) { e = std::current_exception(); } p[1] = nullptr; p[0] = nullptr; p[2] = nullptr; } But to test it I had to hack the __cxa_allocate_exception function to never use malloc and always use the pool, so it's not suitable for the testsuite. With current trunk we create three exception objects with addresses, X, Y, and Z, with the first_free_entry pointing immediately after Z. The p[1] = nullptr statement frees Y, but after that we still have first_free_entry pointing after Z, and then its next pointer points to Y. (So if we threw again at that point, rather than using Y we would chop off the start of the free block, fragmenting the pool). When we free p[0] we add X to the list in between the first block and Y, but don't merge X and Y. The patch fixes the case above so we end up with a single block again after all the deallocations. OK for trunk, although please change s/Slit/Split/ in the comment on line 165.