MozJSImplScope::ASANHandles is used to track the addresses of allocations within mozjs.
Prior to the ESR115 upgrade, the implementation was done in a thread local fashion, with each thread getting its own ASANHandles tracker.
After the ESR115 upgrade, the implementation had to be changed to a global singleton shared by all threads. This introduces additional complexity, as contending threads could be modifying the internal address map simultaneously.
Whenever an allocation (or deallocation) takes place within mozjs, the corresponding allocated/freed address is added or removed from the map within ASANHandles.
The map within ASANHandles is guarded by a lock, however, since the allocate/free operation is not under the same lock, it is possible that we could find ourselves in a situation where one thread still has to remove its pointer from the map (but the memory has already been freed), while a separate thread has received the same address during an allocation, and is inserting into the map.
BF-32781 detects this exact scenario.
As a quick fix, we will use an unordered_map (instead of the current unordered_set) to keep track of the current usage of allocated memory, allowing multiple threads to add a reference count to the tracked handled.
As an alternative, ASANHandles could be refactored to ensure allocations are performed under the same lock as the address map, however this would cause unnecessary lengthening of the critical section under the lock, which is undesirable. Given that this code is only active in ASAN builds, we would like to minimize any significant impact on the release builds.
It is important to note that this code does not affect any runtime logic or behaviour, it is in place to appease the ASAN build by keeping the addresses in memory.