
CVE-2026-74943 · Use after free in Firefox RasterImage (sec-high)
Severity sec high. CWE 416. Fixed in Firefox 154 and ESR 140.14. Bugzilla 2057308. Reachable from an ordinary web page with no user interaction.
Firefox keeps decoded image surfaces in a SurfaceCache. The cache holds a raw non owning pointer to the owning image. When a surface is evicted the cache notifies that image on a decoder thread. The notification read the mIsBeingDestroyed atomic flag and only afterwards took RefPtr<RasterImage> image = this. Reading the flag and taking the reference are two separate operations. The main thread can drop the final reference between them. A dying object is resurrected and then read after it is freed.
Decoder thread (holds the SurfaceCache lock) Main thread
OnSurfaceDiscarded reads mIsBeingDestroyed = false
Release drops the refcount to zero and commits delete
~RasterImage sets the flag then blocks on the cache lock
RefPtr image = this (AddRef from zero to one)
queues the runnable and releases the lock
the destructor finishes and frees the 248 byte object
the runnable runs and reads freed mProgressTracker ==> use after free
The flag from an earlier fix narrows the window. It cannot close it. Observing the flag as false does not prove the refcount is still above zero because the flag is set inside the destructor strictly after the count already reached zero.
The two instructions that carry the bug appear plainly in the compiled function. The flag check and the reference count increment on this are separate.

Use an ASAN build of an affected version. Apply the prefs in prefs.js so the surface cache stays tiny and the decoder thread evicts surfaces constantly. Load uaf-reduced.html and leave it looping. This is a cross thread timing race so it reproduces intermittently.
AddressSanitizer: heap-use-after-free
READ of size 8, 8 bytes into a freed 248-byte RasterImage
use : RasterImage::OnSurfaceDiscardedInternal (main thread)
freed : RasterImage::Release() via imgRequest teardown
alloc : ImageFactory::CreateRasterImage() on the ImageIO thread
A heap use after free in the content process. It is reachable from a web page and needs no clicks or permissions. Controlled execution was not demonstrated on the tested builds. The object is resurrected and later freed a second time.
OnSurfaceDiscarded no longer references the image. It captures a strong reference to the separately reference counted ProgressTracker and recovers the image on the main thread through the tracker weak back reference. The recovery uses an atomic add if live. The obsolete flag is removed.
Abdulaziz Alasaiqah · https://azoz.my/writeups.html