Fix double-delete in content service worker code when using libstdc++
This is probably best illustrated by the following piece of stack trace obtained from chromium 87.0.4276.2 built against libstdc++ instead of libcxx: # base::debug::CollectStackTrace() # base::debug::StackTrace::StackTrace() # logging::LogMessage::~LogMessage() # logging::LogMessage::~LogMessage() # base::internal::LockImpl::Try() # base::SequenceCheckerImpl::CalledOnValidSequence() # base::internal::WeakReference::Flag::Invalidate() # base::internal::WeakReferenceOwner::~WeakReferenceOwner() # content::ServiceWorkerRegistrationObjectHost::~ServiceWorkerRegistrationObjectHost() # std::unique_ptr<>::~unique_ptr() # std::_Rb_tree<>::_M_drop_node() # std::_Rb_tree<>::_M_erase() # content::ServiceWorkerContainerHost::~ServiceWorkerContainerHost() # std::default_delete<>::operator()() # content::ServiceWorkerHost::~ServiceWorkerHost() # std::default_delete<>::operator()() # std::unique_ptr<>::~unique_ptr() # content::ServiceWorkerVersion::~ServiceWorkerVersion() # content::ServiceWorkerRegistration::~ServiceWorkerRegistration() # content::ServiceWorkerRegistrationObjectHost::~ServiceWorkerRegistrationObjectHost() Its important to note here that all the calls to the ~ServiceWrokerRegistrationObjectHost happen with the same "this" object, meaning this is a double-delete bug. It only happens with libstdc++ due to a difference in std::map::erase method implementation. The difference is illustrated by the following example. #include <map> #include <memory> #include <stdio.h> struct A; std::map<int, std::unique_ptr<A>> g_map; struct A { ~A() { printf("Map size on A DTOR call: %zd\n", g_map.size()); } }; int main(int argc, char* argv[]) { g_map[0] = std::make_unique<A>(); g_map.erase(0); } When compiled with clang trunk on goldbot.org with -stdlib=libc++ command line argument the size of std::map is reported as 0. When using the same compiler but with -stdlib=libstdc++ arg specified instead, the size is reported as 1. As far as I can tell the behavior here is not defined by any C++ standard version, its an implementation detail. Bug: 957519, 1135070 Change-Id: Ic7d354c2129cdf790f4731a01f8c995021d23eff Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2509793 Commit-Queue: Piotr Tworek <ptworek@vewd.com> Reviewed-by:Kenichi Ishibashi <bashi@chromium.org> Cr-Commit-Position: refs/heads/master@{#823974}
Showing
Please register or sign in to comment