(Hidden by Administrator)
Bug 1936613 Comment 0 Edit History
Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.
Steps to reproduce: Please note: This bug is subject to a 90-day disclosure deadline. If a fix for this issue is made available to users before the end of the 90-day deadline, this bug report will become public 30 days after the fix was made available. Otherwise, this bug report will become public at the deadline. The scheduled deadline is 2025-03-11. For more details, see the Project Zero vulnerability disclosure policy: https://googleprojectzero.blogspot.com/p/vulnerability-disclosure- policy.html For the discovery of the issue, please credit Ivan Fratric of Google Project Zero There is a use-after-free vulnerability in Firefox in txMozillaXSLTProcessor. The vulnerability was reproduced with an ASAN build from the latest source code. The PoC is attached. The correspondin ASAN log can be found at the end of this report. Root cause analysis follows. txMozillaXSLTProcessor contains several fields that are relevant for understanding the vulnerability: ```c++ class txMozillaXSLTProcessor final : public nsIDocumentTransformer, public nsStubMutationObserver, public nsWrapperCache { ... RefPtr<txStylesheet> mStylesheet; mozilla::dom::Document* mStylesheetDocument; // weak nsCOMPtr<nsIContent> mEmbeddedStylesheetRoot; ... nsresult mCompileResult; }; ``` mStylesheet is the compiled stylesheet, mStylesheetDocument is the document that contains the stylesheet and, if a node is passed to XSLTProcessor.importStylesheet rather than a document, then mEmbeddedStylesheetRoot contains a pointer to that node. mCompileResult contains the compilation result but is only set by some of the functions that perform compilation (we'll come back to that later). Most notably, mStylesheetDocument is the raw pointer to the Document object. In order to prevent cases where the Document gets freed but is still referenced by txMozillaXSLTProcessor, txMozillaXSLTProcessor registers itself as a MutationObserver and implements the following function, which will be called before the document gets freed: ```c++ void txMozillaXSLTProcessor::NodeWillBeDestroyed(nsINode* aNode) { nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this); if (NS_FAILED(mCompileResult)) { return; } mCompileResult = ensureStylesheet(); mStylesheetDocument = nullptr; mEmbeddedStylesheetRoot = nullptr; } ``` As can be seen, before the document gets deleted, mStylesheetDocument gets set to nullptr. However, we only proceed to that point if not NS_FAILED(mCompileResult). And we can only set mCompileResult to failed from txMozillaXSLTProcessor::NodeWillBeDestroyed, at which point the mStylesheetDocument has already been set to nullptr. But what if we can set mStylesheetDocument to *another* document *after* mCompileResult became FAILED. This would prevent the mutation observer from correctly executing for the second document. Normally, we are not allowed to set mStylesheetDocument after it has been set previously. txMozillaXSLTProcessor::ImportStylesheet is meant to prevent that: ```c++ void txMozillaXSLTProcessor::ImportStylesheet(nsINode& aStyle, mozilla::ErrorResult& aRv) { // We don't support importing multiple stylesheets yet. if (NS_WARN_IF(mStylesheetDocument || mStylesheet)) { aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); return; } ... }; ``` As can be seen, txMozillaXSLTProcessor::ImportStylesheet will fail if either mStylesheetDocument or mStylesheet are set. But we already saw that we can unset mStylesheetDocument in txMozillaXSLTProcessor::NodeWillBeDestroyed observer callback. And mStylesheet can also be unset by other observer callbacks, for example: ```c++ void txMozillaXSLTProcessor::ContentWillBeRemoved(nsIContent* aChild) { mStylesheet = nullptr; } ``` So by using observer callbacks, we can get txMozillaXSLTProcessor to a state where both mStylesheetDocument and mStylesheet are NULL, but mCompileResult is FAILED. Another hurdle to overcome before triggering the bug is that mCompileResult can only be set to FAILED during NodeWillBeDestroyed callback. But at this point, the document being destroyed is empty and the compilation of the empty document will actually succeed. To overcome this, we also set the mEmbeddedStylesheetRoot property (by calling txMozillaXSLTProcessor::ImportStylesheet on a node rather than a document), but we later detatch mEmbeddedStylesheetRoot from mStylesheetDocument using Document.adoptNode so that mStylesheetDocument could be freed (otherwise, mEmbeddedStylesheetRoot would hold a reference to mStylesheetDocument which would prevent freeing). The entire exploit flow goes somewhat like this: 1. We call txMozillaXSLTProcessor::ImportStylesheet on a node. All of mStylesheet, mStylesheetDocument and mEmbeddedStylesheetRoot get set. 2. We detatch mEmbeddedStylesheetRoot from mStylesheetDocument by calling adoptNode on a different document. 3. We change the content of mEmbeddedStylesheetRoot so that compilation fails the next time. This also result in one of the observer callbacks setting mStylesheet to NULL. 4. We delete all other references to mStylesheetDocument. Garbage collector runs. txMozillaXSLTProcessor::NodeWillBeDestroyed runs. mCompileResult becomes FAILED, while mStylesheetDocument and mEmbeddedStylesheetRoot become NULL. 5. We call txMozillaXSLTProcessor::ImportStylesheet with a new document. 6. We drop all other references to the new document. txMozillaXSLTProcessor::NodeWillBeDestroyed runs but returns early due to NS_FAILED(mCompileResult). Document gets deleted and mStylesheetDocument points to freed memoy. 7. We call txMozillaXSLTProcessor::Reset. mStylesheetDocument->RemoveMutationObserver(this); is called with mStylesheetDocument being freed, resulting in a use-after-free. ASAN log: ``` ================================================================= ==766789==ERROR: AddressSanitizer: heap-use-after-free on address 0x51e0000180e0 at pc 0x7f0504a31b6e bp 0x7ffdba15e4a0 sp 0x7ffdba15e498 READ of size 8 at 0x51e0000180e0 thread T0 (file:// Content) #0 0x7f0504a31b6d in GetExistingSlots firefox-source/dom/base/nsINode.h:2413:46 #1 0x7f0504a31b6d in RemoveMutationObserver firefox-source/dom/base/nsINode.h:1276:18 #2 0x7f0504a31b6d in txMozillaXSLTProcessor::Reset() firefox-source/dom/xslt/xslt/txMozillaXSLTProcessor.cpp:881:26 #3 0x7f04ff4b4fc8 in mozilla::dom::XSLTProcessor_Binding::reset(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) firefox-source/objdir-ff-asan/dom/bindings/./XSLTProcessorBinding.cpp:1344:24 #4 0x7f04ffe530ea in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) firefox-source/dom/bindings/BindingUtils.cpp:3290:13 #5 0x7f050783480f in CallJSNative firefox-source/js/src/vm/Interpreter.cpp:532:13 #6 0x7f050783480f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) firefox-source/js/src/vm/Interpreter.cpp:628:12 #7 0x7f050784e27b in InternalCall firefox-source/js/src/vm/Interpreter.cpp:695:10 #8 0x7f050784e27b in CallFromStack firefox-source/js/src/vm/Interpreter.cpp:700:10 #9 0x7f050784e27b in js::Interpret(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:3338:16 #10 0x7f05078335ce in MaybeEnterInterpreterTrampoline firefox-source/js/src/vm/Interpreter.cpp:433:10 #11 0x7f05078335ce in js::RunScript(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:502:13 #12 0x7f050783878f in ExecuteKernel firefox-source/js/src/vm/Interpreter.cpp:893:13 #13 0x7f050783878f in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/Interpreter.cpp:926:10 #14 0x7f05079a5ba0 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:601:10 #15 0x7f05079a5e60 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:625:10 #16 0x7f0504c951c7 in ExecuteCompiledScript firefox-source/dom/script/ScriptLoader.cpp:2653:8 #17 0x7f0504c951c7 in mozilla::dom::ScriptLoader::EvaluateScript(nsIGlobalObject*, JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:3137:7 #18 0x7f0504c93f08 in mozilla::dom::ScriptLoader::EvaluateScriptElement(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2722:10 #19 0x7f0504c8c524 in mozilla::dom::ScriptLoader::ProcessRequest(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2354:10 #20 0x7f0504c89523 in mozilla::dom::ScriptLoader::ProcessInlineScript(nsIScriptElement*, JS::loader::ScriptKind) firefox-source/dom/script/ScriptLoader.cpp:1605:10 #21 0x7f0504c71660 in mozilla::dom::ScriptLoader::ProcessScriptElement(nsIScriptElement*) firefox-source/dom/script/ScriptLoader.cpp:1201:10 #22 0x7f0504c70f72 in mozilla::dom::ScriptElement::MaybeProcessScript() firefox-source/dom/script/ScriptElement.cpp:210:18 #23 0x7f04fb36fdc6 in AttemptToExecute firefox-source/objdir-ff-asan/dist/include/nsIScriptElement.h:224:18 #24 0x7f04fb36fdc6 in nsHtml5TreeOpExecutor::RunScript(nsIContent*, bool) firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:900:22 #25 0x7f04fb36b85a in nsHtml5TreeOpExecutor::RunFlushLoop() firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:685:7 #26 0x7f04fb3afccb in nsHtml5ExecutorFlusher::Run() firefox-source/parser/html/nsHtml5StreamParser.cpp:161:18 #27 0x7f04f911ff0a in mozilla::RunnableTask::Run() firefox-source/xpcom/threads/TaskController.cpp:688:16 #28 0x7f04f90fff3d in mozilla::TaskController::RunTask(mozilla::Task*) firefox-source/xpcom/threads/TaskController.cpp:215:19 #29 0x7f04f9106ea0 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:1015:20 #30 0x7f04f91048a8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:838:15 #31 0x7f04f9104ec6 in mozilla::TaskController::ProcessPendingMTTask(bool) firefox-source/xpcom/threads/TaskController.cpp:624:36 #32 0x7f04f910ea51 in operator() firefox-source/xpcom/threads/TaskController.cpp:336:37 #33 0x7f04f910ea51 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() firefox-source/xpcom/threads/nsThreadUtils.h:548:5 #34 0x7f04f91502bf in nsThread::ProcessNextEvent(bool, bool*) firefox-source/xpcom/threads/nsThread.cpp:1159:16 #35 0x7f04f915a6c0 in NS_ProcessNextEvent(nsIThread*, bool) firefox-source/xpcom/threads/nsThreadUtils.cpp:480:10 #36 0x7f04faae72ff in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) firefox-source/ipc/glue/MessagePump.cpp:85:21 #37 0x7f04fa92ac94 in RunInternal firefox-source/ipc/chromium/src/base/message_loop.cc:369:10 #38 0x7f04fa92ac94 in RunHandler firefox-source/ipc/chromium/src/base/message_loop.cc:362:3 #39 0x7f04fa92ac94 in MessageLoop::Run() firefox-source/ipc/chromium/src/base/message_loop.cc:344:3 #40 0x7f0505188ccc in nsBaseAppShell::Run() firefox-source/widget/nsBaseAppShell.cpp:148:27 #41 0x7f050536096c in nsAppShell::Run() firefox-source/widget/gtk/nsAppShell.cpp:469:33 #42 0x7f05074312f5 in XRE_RunAppShell() firefox-source/toolkit/xre/nsEmbedFunctions.cpp:646:20 #43 0x7f04fa92ac94 in RunInternal firefox-source/ipc/chromium/src/base/message_loop.cc:369:10 #44 0x7f04fa92ac94 in RunHandler firefox-source/ipc/chromium/src/base/message_loop.cc:362:3 #45 0x7f04fa92ac94 in MessageLoop::Run() firefox-source/ipc/chromium/src/base/message_loop.cc:344:3 #46 0x7f0507430b82 in XRE_InitChildProcess(int, char**, XREChildData const*) firefox-source/toolkit/xre/nsEmbedFunctions.cpp:584:34 #47 0x55c511826849 in main firefox-source/browser/app/nsBrowserApp.cpp:397:22 #48 0x7f0517840c89 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #49 0x7f0517840d44 in __libc_start_main csu/../csu/libc-start.c:360:3 #50 0x55c511745ef8 in _start (firefox-source/objdir-ff-asan/dist/bin/firefox+0xccef8) (BuildId: 113c3f167b1e04b8ec5edf06452c0bb9) 0x51e0000180e0 is located 96 bytes inside of 2808-byte region [0x51e000018080,0x51e000018b78) freed by thread T0 (file:// Content) here: #0 0x55c5117e3556 in free /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3 #1 0x7f04f8f7e1c1 in MaybeKillObject firefox-source/xpcom/base/nsCycleCollector.cpp:2625:29 #2 0x7f04f8f7e1c1 in SnowWhiteKiller::~SnowWhiteKiller() firefox-source/xpcom/base/nsCycleCollector.cpp:2612:7 #3 0x7f04f8f65aef in nsCycleCollector::FreeSnowWhite(bool) firefox-source/xpcom/base/nsCycleCollector.cpp:2802:3 #4 0x7f04f8f6affb in nsCycleCollector::CleanupAfterCollection() firefox-source/xpcom/base/nsCycleCollector.cpp:3501:3 #5 0x7f04f8f6c18b in nsCycleCollector::Collect(mozilla::CCReason, ccIsManual, JS::SliceBudget&, nsICycleCollectorListener*, bool) firefox-source/xpcom/base/nsCycleCollector.cpp:3653:9 #6 0x7f04f8f70379 in nsCycleCollector_collect(mozilla::CCReason, nsICycleCollectorListener*) firefox-source/xpcom/base/nsCycleCollector.cpp:4154:28 #7 0x7f04fdceacc3 in nsJSContext::CycleCollectNow(mozilla::CCReason, nsICycleCollectorListener*) firefox-source/dom/base/nsJSEnvironment.cpp:1110:3 #8 0x7f04ffb23308 in mozilla::dom::FuzzingFunctions_Binding::cycleCollect(JSContext*, unsigned int, JS::Value*) firefox-source/objdir-ff-asan/dom/bindings/./FuzzingFunctionsBinding.cpp:133:3 #9 0x7f050783480f in CallJSNative firefox-source/js/src/vm/Interpreter.cpp:532:13 #10 0x7f050783480f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) firefox-source/js/src/vm/Interpreter.cpp:628:12 #11 0x7f050784e27b in InternalCall firefox-source/js/src/vm/Interpreter.cpp:695:10 #12 0x7f050784e27b in CallFromStack firefox-source/js/src/vm/Interpreter.cpp:700:10 #13 0x7f050784e27b in js::Interpret(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:3338:16 #14 0x7f05078335ce in MaybeEnterInterpreterTrampoline firefox-source/js/src/vm/Interpreter.cpp:433:10 #15 0x7f05078335ce in js::RunScript(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:502:13 #16 0x7f050783878f in ExecuteKernel firefox-source/js/src/vm/Interpreter.cpp:893:13 #17 0x7f050783878f in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/Interpreter.cpp:926:10 #18 0x7f05079a5ba0 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:601:10 #19 0x7f05079a5e60 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:625:10 #20 0x7f0504c951c7 in ExecuteCompiledScript firefox-source/dom/script/ScriptLoader.cpp:2653:8 #21 0x7f0504c951c7 in mozilla::dom::ScriptLoader::EvaluateScript(nsIGlobalObject*, JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:3137:7 #22 0x7f0504c93f08 in mozilla::dom::ScriptLoader::EvaluateScriptElement(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2722:10 #23 0x7f0504c8c524 in mozilla::dom::ScriptLoader::ProcessRequest(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2354:10 #24 0x7f0504c89523 in mozilla::dom::ScriptLoader::ProcessInlineScript(nsIScriptElement*, JS::loader::ScriptKind) firefox-source/dom/script/ScriptLoader.cpp:1605:10 #25 0x7f0504c71660 in mozilla::dom::ScriptLoader::ProcessScriptElement(nsIScriptElement*) firefox-source/dom/script/ScriptLoader.cpp:1201:10 #26 0x7f0504c70f72 in mozilla::dom::ScriptElement::MaybeProcessScript() firefox-source/dom/script/ScriptElement.cpp:210:18 #27 0x7f04fb36fdc6 in AttemptToExecute firefox-source/objdir-ff-asan/dist/include/nsIScriptElement.h:224:18 #28 0x7f04fb36fdc6 in nsHtml5TreeOpExecutor::RunScript(nsIContent*, bool) firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:900:22 #29 0x7f04fb36b85a in nsHtml5TreeOpExecutor::RunFlushLoop() firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:685:7 #30 0x7f04fb3afccb in nsHtml5ExecutorFlusher::Run() firefox-source/parser/html/nsHtml5StreamParser.cpp:161:18 #31 0x7f04f911ff0a in mozilla::RunnableTask::Run() firefox-source/xpcom/threads/TaskController.cpp:688:16 #32 0x7f04f90fff3d in mozilla::TaskController::RunTask(mozilla::Task*) firefox-source/xpcom/threads/TaskController.cpp:215:19 #33 0x7f04f9106ea0 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:1015:20 #34 0x7f04f91048a8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:838:15 #35 0x7f04f9104ec6 in mozilla::TaskController::ProcessPendingMTTask(bool) firefox-source/xpcom/threads/TaskController.cpp:624:36 #36 0x7f04f910ea51 in operator() firefox-source/xpcom/threads/TaskController.cpp:336:37 #37 0x7f04f910ea51 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() firefox-source/xpcom/threads/nsThreadUtils.h:548:5 #38 0x7f04f91502bf in nsThread::ProcessNextEvent(bool, bool*) firefox-source/xpcom/threads/nsThread.cpp:1159:16 previously allocated by thread T0 (file:// Content) here: #0 0x55c5117e37ef in malloc /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3 #1 0x55c51182a88d in moz_xmalloc firefox-source/memory/mozalloc/mozalloc.cpp:52:15 #2 0x7f050499fc04 in operator new firefox-source/objdir-ff-asan/dist/include/mozilla/cxxalloc.h:33:10 #3 0x7f050499fc04 in operator new firefox-source/objdir-ff-asan/dist/include/mozilla/dom/Document.h:566:45 #4 0x7f050499fc04 in NS_NewXMLDocument firefox-source/dom/xml/XMLDocument.cpp:179:29 #5 0x7f050499fc04 in NS_NewDOMDocument(mozilla::dom::Document**, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::DocumentType*, nsIURI*, nsIURI*, nsIPrincipal*, bool, nsIGlobalObject*, DocumentFlavor) firefox-source/dom/xml/XMLDocument.cpp:74:10 #6 0x7f04fd732f77 in mozilla::dom::DOMImplementation::CreateDocument(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::DocumentType*, mozilla::dom::Document**) firefox-source/dom/base/DOMImplementation.cpp:100:8 #7 0x7f04fd7332bc in mozilla::dom::DOMImplementation::CreateDocument(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::DocumentType*, mozilla::ErrorResult&) firefox-source/dom/base/DOMImplementation.cpp:128:9 #8 0x7f04ff73af91 in mozilla::dom::DOMImplementation_Binding::createDocument(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) firefox-source/objdir-ff-asan/dom/bindings/./DOMImplementationBinding.cpp:162:75 #9 0x7f04ffe530ea in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) firefox-source/dom/bindings/BindingUtils.cpp:3290:13 #10 0x7f050783480f in CallJSNative firefox-source/js/src/vm/Interpreter.cpp:532:13 #11 0x7f050783480f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) firefox-source/js/src/vm/Interpreter.cpp:628:12 #12 0x7f050784e27b in InternalCall firefox-source/js/src/vm/Interpreter.cpp:695:10 #13 0x7f050784e27b in CallFromStack firefox-source/js/src/vm/Interpreter.cpp:700:10 #14 0x7f050784e27b in js::Interpret(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:3338:16 #15 0x7f05078335ce in MaybeEnterInterpreterTrampoline firefox-source/js/src/vm/Interpreter.cpp:433:10 #16 0x7f05078335ce in js::RunScript(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:502:13 #17 0x7f050783878f in ExecuteKernel firefox-source/js/src/vm/Interpreter.cpp:893:13 #18 0x7f050783878f in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/Interpreter.cpp:926:10 #19 0x7f05079a5ba0 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:601:10 #20 0x7f05079a5e60 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:625:10 #21 0x7f0504c951c7 in ExecuteCompiledScript firefox-source/dom/script/ScriptLoader.cpp:2653:8 #22 0x7f0504c951c7 in mozilla::dom::ScriptLoader::EvaluateScript(nsIGlobalObject*, JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:3137:7 #23 0x7f0504c93f08 in mozilla::dom::ScriptLoader::EvaluateScriptElement(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2722:10 #24 0x7f0504c8c524 in mozilla::dom::ScriptLoader::ProcessRequest(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2354:10 #25 0x7f0504c89523 in mozilla::dom::ScriptLoader::ProcessInlineScript(nsIScriptElement*, JS::loader::ScriptKind) firefox-source/dom/script/ScriptLoader.cpp:1605:10 #26 0x7f0504c71660 in mozilla::dom::ScriptLoader::ProcessScriptElement(nsIScriptElement*) firefox-source/dom/script/ScriptLoader.cpp:1201:10 #27 0x7f0504c70f72 in mozilla::dom::ScriptElement::MaybeProcessScript() firefox-source/dom/script/ScriptElement.cpp:210:18 #28 0x7f04fb36fdc6 in AttemptToExecute firefox-source/objdir-ff-asan/dist/include/nsIScriptElement.h:224:18 #29 0x7f04fb36fdc6 in nsHtml5TreeOpExecutor::RunScript(nsIContent*, bool) firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:900:22 #30 0x7f04fb36b85a in nsHtml5TreeOpExecutor::RunFlushLoop() firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:685:7 #31 0x7f04fb3afccb in nsHtml5ExecutorFlusher::Run() firefox-source/parser/html/nsHtml5StreamParser.cpp:161:18 #32 0x7f04f911ff0a in mozilla::RunnableTask::Run() firefox-source/xpcom/threads/TaskController.cpp:688:16 #33 0x7f04f90fff3d in mozilla::TaskController::RunTask(mozilla::Task*) firefox-source/xpcom/threads/TaskController.cpp:215:19 #34 0x7f04f9106ea0 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:1015:20 #35 0x7f04f91048a8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:838:15 #36 0x7f04f9104ec6 in mozilla::TaskController::ProcessPendingMTTask(bool) firefox-source/xpcom/threads/TaskController.cpp:624:36 #37 0x7f04f910ea51 in operator() firefox-source/xpcom/threads/TaskController.cpp:336:37 #38 0x7f04f910ea51 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() firefox-source/xpcom/threads/nsThreadUtils.h:548:5 #39 0x7f04f91502bf in nsThread::ProcessNextEvent(bool, bool*) firefox-source/xpcom/threads/nsThread.cpp:1159:16 #40 0x7f04f915a6c0 in NS_ProcessNextEvent(nsIThread*, bool) firefox-source/xpcom/threads/nsThreadUtils.cpp:480:10 SUMMARY: AddressSanitizer: heap-use-after-free firefox-source/dom/base/nsINode.h:2413:46 in GetExistingSlots Shadow bytes around the buggy address: 0x51e000017e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x51e000017e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x51e000017f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa 0x51e000017f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x51e000018000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x51e000018080: fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd 0x51e000018100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018300: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==766789==ABORTING ```
Steps to reproduce: Please note: This bug is subject to a 90-day disclosure deadline. If a fix for this issue is made available to users before the end of the 90-day deadline, this bug report will become public 30 days after the fix was made available. Otherwise, this bug report will become public at the deadline. The scheduled deadline is 2025-03-11. For more details, see the Project Zero vulnerability disclosure policy: https://googleprojectzero.blogspot.com/p/vulnerability-disclosure-policy.html For the discovery of the issue, please credit Ivan Fratric of Google Project Zero There is a use-after-free vulnerability in Firefox in txMozillaXSLTProcessor. The vulnerability was reproduced with an ASAN build from the latest source code. The PoC is attached. The correspondin ASAN log can be found at the end of this report. Root cause analysis follows. txMozillaXSLTProcessor contains several fields that are relevant for understanding the vulnerability: ```c++ class txMozillaXSLTProcessor final : public nsIDocumentTransformer, public nsStubMutationObserver, public nsWrapperCache { ... RefPtr<txStylesheet> mStylesheet; mozilla::dom::Document* mStylesheetDocument; // weak nsCOMPtr<nsIContent> mEmbeddedStylesheetRoot; ... nsresult mCompileResult; }; ``` mStylesheet is the compiled stylesheet, mStylesheetDocument is the document that contains the stylesheet and, if a node is passed to XSLTProcessor.importStylesheet rather than a document, then mEmbeddedStylesheetRoot contains a pointer to that node. mCompileResult contains the compilation result but is only set by some of the functions that perform compilation (we'll come back to that later). Most notably, mStylesheetDocument is the raw pointer to the Document object. In order to prevent cases where the Document gets freed but is still referenced by txMozillaXSLTProcessor, txMozillaXSLTProcessor registers itself as a MutationObserver and implements the following function, which will be called before the document gets freed: ```c++ void txMozillaXSLTProcessor::NodeWillBeDestroyed(nsINode* aNode) { nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this); if (NS_FAILED(mCompileResult)) { return; } mCompileResult = ensureStylesheet(); mStylesheetDocument = nullptr; mEmbeddedStylesheetRoot = nullptr; } ``` As can be seen, before the document gets deleted, mStylesheetDocument gets set to nullptr. However, we only proceed to that point if not NS_FAILED(mCompileResult). And we can only set mCompileResult to failed from txMozillaXSLTProcessor::NodeWillBeDestroyed, at which point the mStylesheetDocument has already been set to nullptr. But what if we can set mStylesheetDocument to *another* document *after* mCompileResult became FAILED. This would prevent the mutation observer from correctly executing for the second document. Normally, we are not allowed to set mStylesheetDocument after it has been set previously. txMozillaXSLTProcessor::ImportStylesheet is meant to prevent that: ```c++ void txMozillaXSLTProcessor::ImportStylesheet(nsINode& aStyle, mozilla::ErrorResult& aRv) { // We don't support importing multiple stylesheets yet. if (NS_WARN_IF(mStylesheetDocument || mStylesheet)) { aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); return; } ... }; ``` As can be seen, txMozillaXSLTProcessor::ImportStylesheet will fail if either mStylesheetDocument or mStylesheet are set. But we already saw that we can unset mStylesheetDocument in txMozillaXSLTProcessor::NodeWillBeDestroyed observer callback. And mStylesheet can also be unset by other observer callbacks, for example: ```c++ void txMozillaXSLTProcessor::ContentWillBeRemoved(nsIContent* aChild) { mStylesheet = nullptr; } ``` So by using observer callbacks, we can get txMozillaXSLTProcessor to a state where both mStylesheetDocument and mStylesheet are NULL, but mCompileResult is FAILED. Another hurdle to overcome before triggering the bug is that mCompileResult can only be set to FAILED during NodeWillBeDestroyed callback. But at this point, the document being destroyed is empty and the compilation of the empty document will actually succeed. To overcome this, we also set the mEmbeddedStylesheetRoot property (by calling txMozillaXSLTProcessor::ImportStylesheet on a node rather than a document), but we later detatch mEmbeddedStylesheetRoot from mStylesheetDocument using Document.adoptNode so that mStylesheetDocument could be freed (otherwise, mEmbeddedStylesheetRoot would hold a reference to mStylesheetDocument which would prevent freeing). The entire exploit flow goes somewhat like this: 1. We call txMozillaXSLTProcessor::ImportStylesheet on a node. All of mStylesheet, mStylesheetDocument and mEmbeddedStylesheetRoot get set. 2. We detatch mEmbeddedStylesheetRoot from mStylesheetDocument by calling adoptNode on a different document. 3. We change the content of mEmbeddedStylesheetRoot so that compilation fails the next time. This also result in one of the observer callbacks setting mStylesheet to NULL. 4. We delete all other references to mStylesheetDocument. Garbage collector runs. txMozillaXSLTProcessor::NodeWillBeDestroyed runs. mCompileResult becomes FAILED, while mStylesheetDocument and mEmbeddedStylesheetRoot become NULL. 5. We call txMozillaXSLTProcessor::ImportStylesheet with a new document. 6. We drop all other references to the new document. txMozillaXSLTProcessor::NodeWillBeDestroyed runs but returns early due to NS_FAILED(mCompileResult). Document gets deleted and mStylesheetDocument points to freed memoy. 7. We call txMozillaXSLTProcessor::Reset. mStylesheetDocument->RemoveMutationObserver(this); is called with mStylesheetDocument being freed, resulting in a use-after-free. ASAN log: ``` ================================================================= ==766789==ERROR: AddressSanitizer: heap-use-after-free on address 0x51e0000180e0 at pc 0x7f0504a31b6e bp 0x7ffdba15e4a0 sp 0x7ffdba15e498 READ of size 8 at 0x51e0000180e0 thread T0 (file:// Content) #0 0x7f0504a31b6d in GetExistingSlots firefox-source/dom/base/nsINode.h:2413:46 #1 0x7f0504a31b6d in RemoveMutationObserver firefox-source/dom/base/nsINode.h:1276:18 #2 0x7f0504a31b6d in txMozillaXSLTProcessor::Reset() firefox-source/dom/xslt/xslt/txMozillaXSLTProcessor.cpp:881:26 #3 0x7f04ff4b4fc8 in mozilla::dom::XSLTProcessor_Binding::reset(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) firefox-source/objdir-ff-asan/dom/bindings/./XSLTProcessorBinding.cpp:1344:24 #4 0x7f04ffe530ea in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) firefox-source/dom/bindings/BindingUtils.cpp:3290:13 #5 0x7f050783480f in CallJSNative firefox-source/js/src/vm/Interpreter.cpp:532:13 #6 0x7f050783480f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) firefox-source/js/src/vm/Interpreter.cpp:628:12 #7 0x7f050784e27b in InternalCall firefox-source/js/src/vm/Interpreter.cpp:695:10 #8 0x7f050784e27b in CallFromStack firefox-source/js/src/vm/Interpreter.cpp:700:10 #9 0x7f050784e27b in js::Interpret(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:3338:16 #10 0x7f05078335ce in MaybeEnterInterpreterTrampoline firefox-source/js/src/vm/Interpreter.cpp:433:10 #11 0x7f05078335ce in js::RunScript(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:502:13 #12 0x7f050783878f in ExecuteKernel firefox-source/js/src/vm/Interpreter.cpp:893:13 #13 0x7f050783878f in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/Interpreter.cpp:926:10 #14 0x7f05079a5ba0 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:601:10 #15 0x7f05079a5e60 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:625:10 #16 0x7f0504c951c7 in ExecuteCompiledScript firefox-source/dom/script/ScriptLoader.cpp:2653:8 #17 0x7f0504c951c7 in mozilla::dom::ScriptLoader::EvaluateScript(nsIGlobalObject*, JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:3137:7 #18 0x7f0504c93f08 in mozilla::dom::ScriptLoader::EvaluateScriptElement(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2722:10 #19 0x7f0504c8c524 in mozilla::dom::ScriptLoader::ProcessRequest(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2354:10 #20 0x7f0504c89523 in mozilla::dom::ScriptLoader::ProcessInlineScript(nsIScriptElement*, JS::loader::ScriptKind) firefox-source/dom/script/ScriptLoader.cpp:1605:10 #21 0x7f0504c71660 in mozilla::dom::ScriptLoader::ProcessScriptElement(nsIScriptElement*) firefox-source/dom/script/ScriptLoader.cpp:1201:10 #22 0x7f0504c70f72 in mozilla::dom::ScriptElement::MaybeProcessScript() firefox-source/dom/script/ScriptElement.cpp:210:18 #23 0x7f04fb36fdc6 in AttemptToExecute firefox-source/objdir-ff-asan/dist/include/nsIScriptElement.h:224:18 #24 0x7f04fb36fdc6 in nsHtml5TreeOpExecutor::RunScript(nsIContent*, bool) firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:900:22 #25 0x7f04fb36b85a in nsHtml5TreeOpExecutor::RunFlushLoop() firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:685:7 #26 0x7f04fb3afccb in nsHtml5ExecutorFlusher::Run() firefox-source/parser/html/nsHtml5StreamParser.cpp:161:18 #27 0x7f04f911ff0a in mozilla::RunnableTask::Run() firefox-source/xpcom/threads/TaskController.cpp:688:16 #28 0x7f04f90fff3d in mozilla::TaskController::RunTask(mozilla::Task*) firefox-source/xpcom/threads/TaskController.cpp:215:19 #29 0x7f04f9106ea0 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:1015:20 #30 0x7f04f91048a8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:838:15 #31 0x7f04f9104ec6 in mozilla::TaskController::ProcessPendingMTTask(bool) firefox-source/xpcom/threads/TaskController.cpp:624:36 #32 0x7f04f910ea51 in operator() firefox-source/xpcom/threads/TaskController.cpp:336:37 #33 0x7f04f910ea51 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() firefox-source/xpcom/threads/nsThreadUtils.h:548:5 #34 0x7f04f91502bf in nsThread::ProcessNextEvent(bool, bool*) firefox-source/xpcom/threads/nsThread.cpp:1159:16 #35 0x7f04f915a6c0 in NS_ProcessNextEvent(nsIThread*, bool) firefox-source/xpcom/threads/nsThreadUtils.cpp:480:10 #36 0x7f04faae72ff in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) firefox-source/ipc/glue/MessagePump.cpp:85:21 #37 0x7f04fa92ac94 in RunInternal firefox-source/ipc/chromium/src/base/message_loop.cc:369:10 #38 0x7f04fa92ac94 in RunHandler firefox-source/ipc/chromium/src/base/message_loop.cc:362:3 #39 0x7f04fa92ac94 in MessageLoop::Run() firefox-source/ipc/chromium/src/base/message_loop.cc:344:3 #40 0x7f0505188ccc in nsBaseAppShell::Run() firefox-source/widget/nsBaseAppShell.cpp:148:27 #41 0x7f050536096c in nsAppShell::Run() firefox-source/widget/gtk/nsAppShell.cpp:469:33 #42 0x7f05074312f5 in XRE_RunAppShell() firefox-source/toolkit/xre/nsEmbedFunctions.cpp:646:20 #43 0x7f04fa92ac94 in RunInternal firefox-source/ipc/chromium/src/base/message_loop.cc:369:10 #44 0x7f04fa92ac94 in RunHandler firefox-source/ipc/chromium/src/base/message_loop.cc:362:3 #45 0x7f04fa92ac94 in MessageLoop::Run() firefox-source/ipc/chromium/src/base/message_loop.cc:344:3 #46 0x7f0507430b82 in XRE_InitChildProcess(int, char**, XREChildData const*) firefox-source/toolkit/xre/nsEmbedFunctions.cpp:584:34 #47 0x55c511826849 in main firefox-source/browser/app/nsBrowserApp.cpp:397:22 #48 0x7f0517840c89 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #49 0x7f0517840d44 in __libc_start_main csu/../csu/libc-start.c:360:3 #50 0x55c511745ef8 in _start (firefox-source/objdir-ff-asan/dist/bin/firefox+0xccef8) (BuildId: 113c3f167b1e04b8ec5edf06452c0bb9) 0x51e0000180e0 is located 96 bytes inside of 2808-byte region [0x51e000018080,0x51e000018b78) freed by thread T0 (file:// Content) here: #0 0x55c5117e3556 in free /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:52:3 #1 0x7f04f8f7e1c1 in MaybeKillObject firefox-source/xpcom/base/nsCycleCollector.cpp:2625:29 #2 0x7f04f8f7e1c1 in SnowWhiteKiller::~SnowWhiteKiller() firefox-source/xpcom/base/nsCycleCollector.cpp:2612:7 #3 0x7f04f8f65aef in nsCycleCollector::FreeSnowWhite(bool) firefox-source/xpcom/base/nsCycleCollector.cpp:2802:3 #4 0x7f04f8f6affb in nsCycleCollector::CleanupAfterCollection() firefox-source/xpcom/base/nsCycleCollector.cpp:3501:3 #5 0x7f04f8f6c18b in nsCycleCollector::Collect(mozilla::CCReason, ccIsManual, JS::SliceBudget&, nsICycleCollectorListener*, bool) firefox-source/xpcom/base/nsCycleCollector.cpp:3653:9 #6 0x7f04f8f70379 in nsCycleCollector_collect(mozilla::CCReason, nsICycleCollectorListener*) firefox-source/xpcom/base/nsCycleCollector.cpp:4154:28 #7 0x7f04fdceacc3 in nsJSContext::CycleCollectNow(mozilla::CCReason, nsICycleCollectorListener*) firefox-source/dom/base/nsJSEnvironment.cpp:1110:3 #8 0x7f04ffb23308 in mozilla::dom::FuzzingFunctions_Binding::cycleCollect(JSContext*, unsigned int, JS::Value*) firefox-source/objdir-ff-asan/dom/bindings/./FuzzingFunctionsBinding.cpp:133:3 #9 0x7f050783480f in CallJSNative firefox-source/js/src/vm/Interpreter.cpp:532:13 #10 0x7f050783480f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) firefox-source/js/src/vm/Interpreter.cpp:628:12 #11 0x7f050784e27b in InternalCall firefox-source/js/src/vm/Interpreter.cpp:695:10 #12 0x7f050784e27b in CallFromStack firefox-source/js/src/vm/Interpreter.cpp:700:10 #13 0x7f050784e27b in js::Interpret(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:3338:16 #14 0x7f05078335ce in MaybeEnterInterpreterTrampoline firefox-source/js/src/vm/Interpreter.cpp:433:10 #15 0x7f05078335ce in js::RunScript(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:502:13 #16 0x7f050783878f in ExecuteKernel firefox-source/js/src/vm/Interpreter.cpp:893:13 #17 0x7f050783878f in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/Interpreter.cpp:926:10 #18 0x7f05079a5ba0 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:601:10 #19 0x7f05079a5e60 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:625:10 #20 0x7f0504c951c7 in ExecuteCompiledScript firefox-source/dom/script/ScriptLoader.cpp:2653:8 #21 0x7f0504c951c7 in mozilla::dom::ScriptLoader::EvaluateScript(nsIGlobalObject*, JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:3137:7 #22 0x7f0504c93f08 in mozilla::dom::ScriptLoader::EvaluateScriptElement(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2722:10 #23 0x7f0504c8c524 in mozilla::dom::ScriptLoader::ProcessRequest(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2354:10 #24 0x7f0504c89523 in mozilla::dom::ScriptLoader::ProcessInlineScript(nsIScriptElement*, JS::loader::ScriptKind) firefox-source/dom/script/ScriptLoader.cpp:1605:10 #25 0x7f0504c71660 in mozilla::dom::ScriptLoader::ProcessScriptElement(nsIScriptElement*) firefox-source/dom/script/ScriptLoader.cpp:1201:10 #26 0x7f0504c70f72 in mozilla::dom::ScriptElement::MaybeProcessScript() firefox-source/dom/script/ScriptElement.cpp:210:18 #27 0x7f04fb36fdc6 in AttemptToExecute firefox-source/objdir-ff-asan/dist/include/nsIScriptElement.h:224:18 #28 0x7f04fb36fdc6 in nsHtml5TreeOpExecutor::RunScript(nsIContent*, bool) firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:900:22 #29 0x7f04fb36b85a in nsHtml5TreeOpExecutor::RunFlushLoop() firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:685:7 #30 0x7f04fb3afccb in nsHtml5ExecutorFlusher::Run() firefox-source/parser/html/nsHtml5StreamParser.cpp:161:18 #31 0x7f04f911ff0a in mozilla::RunnableTask::Run() firefox-source/xpcom/threads/TaskController.cpp:688:16 #32 0x7f04f90fff3d in mozilla::TaskController::RunTask(mozilla::Task*) firefox-source/xpcom/threads/TaskController.cpp:215:19 #33 0x7f04f9106ea0 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:1015:20 #34 0x7f04f91048a8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:838:15 #35 0x7f04f9104ec6 in mozilla::TaskController::ProcessPendingMTTask(bool) firefox-source/xpcom/threads/TaskController.cpp:624:36 #36 0x7f04f910ea51 in operator() firefox-source/xpcom/threads/TaskController.cpp:336:37 #37 0x7f04f910ea51 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() firefox-source/xpcom/threads/nsThreadUtils.h:548:5 #38 0x7f04f91502bf in nsThread::ProcessNextEvent(bool, bool*) firefox-source/xpcom/threads/nsThread.cpp:1159:16 previously allocated by thread T0 (file:// Content) here: #0 0x55c5117e37ef in malloc /builds/worker/fetches/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:68:3 #1 0x55c51182a88d in moz_xmalloc firefox-source/memory/mozalloc/mozalloc.cpp:52:15 #2 0x7f050499fc04 in operator new firefox-source/objdir-ff-asan/dist/include/mozilla/cxxalloc.h:33:10 #3 0x7f050499fc04 in operator new firefox-source/objdir-ff-asan/dist/include/mozilla/dom/Document.h:566:45 #4 0x7f050499fc04 in NS_NewXMLDocument firefox-source/dom/xml/XMLDocument.cpp:179:29 #5 0x7f050499fc04 in NS_NewDOMDocument(mozilla::dom::Document**, nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::DocumentType*, nsIURI*, nsIURI*, nsIPrincipal*, bool, nsIGlobalObject*, DocumentFlavor) firefox-source/dom/xml/XMLDocument.cpp:74:10 #6 0x7f04fd732f77 in mozilla::dom::DOMImplementation::CreateDocument(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::DocumentType*, mozilla::dom::Document**) firefox-source/dom/base/DOMImplementation.cpp:100:8 #7 0x7f04fd7332bc in mozilla::dom::DOMImplementation::CreateDocument(nsTSubstring<char16_t> const&, nsTSubstring<char16_t> const&, mozilla::dom::DocumentType*, mozilla::ErrorResult&) firefox-source/dom/base/DOMImplementation.cpp:128:9 #8 0x7f04ff73af91 in mozilla::dom::DOMImplementation_Binding::createDocument(JSContext*, JS::Handle<JSObject*>, void*, JSJitMethodCallArgs const&) firefox-source/objdir-ff-asan/dom/bindings/./DOMImplementationBinding.cpp:162:75 #9 0x7f04ffe530ea in bool mozilla::dom::binding_detail::GenericMethod<mozilla::dom::binding_detail::NormalThisPolicy, mozilla::dom::binding_detail::ThrowExceptions>(JSContext*, unsigned int, JS::Value*) firefox-source/dom/bindings/BindingUtils.cpp:3290:13 #10 0x7f050783480f in CallJSNative firefox-source/js/src/vm/Interpreter.cpp:532:13 #11 0x7f050783480f in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct, js::CallReason) firefox-source/js/src/vm/Interpreter.cpp:628:12 #12 0x7f050784e27b in InternalCall firefox-source/js/src/vm/Interpreter.cpp:695:10 #13 0x7f050784e27b in CallFromStack firefox-source/js/src/vm/Interpreter.cpp:700:10 #14 0x7f050784e27b in js::Interpret(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:3338:16 #15 0x7f05078335ce in MaybeEnterInterpreterTrampoline firefox-source/js/src/vm/Interpreter.cpp:433:10 #16 0x7f05078335ce in js::RunScript(JSContext*, js::RunState&) firefox-source/js/src/vm/Interpreter.cpp:502:13 #17 0x7f050783878f in ExecuteKernel firefox-source/js/src/vm/Interpreter.cpp:893:13 #18 0x7f050783878f in js::Execute(JSContext*, JS::Handle<JSScript*>, JS::Handle<JSObject*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/Interpreter.cpp:926:10 #19 0x7f05079a5ba0 in ExecuteScript(JSContext*, JS::Handle<JSObject*>, JS::Handle<JSScript*>, JS::MutableHandle<JS::Value>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:601:10 #20 0x7f05079a5e60 in JS_ExecuteScript(JSContext*, JS::Handle<JSScript*>) firefox-source/js/src/vm/CompilationAndEvaluation.cpp:625:10 #21 0x7f0504c951c7 in ExecuteCompiledScript firefox-source/dom/script/ScriptLoader.cpp:2653:8 #22 0x7f0504c951c7 in mozilla::dom::ScriptLoader::EvaluateScript(nsIGlobalObject*, JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:3137:7 #23 0x7f0504c93f08 in mozilla::dom::ScriptLoader::EvaluateScriptElement(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2722:10 #24 0x7f0504c8c524 in mozilla::dom::ScriptLoader::ProcessRequest(JS::loader::ScriptLoadRequest*) firefox-source/dom/script/ScriptLoader.cpp:2354:10 #25 0x7f0504c89523 in mozilla::dom::ScriptLoader::ProcessInlineScript(nsIScriptElement*, JS::loader::ScriptKind) firefox-source/dom/script/ScriptLoader.cpp:1605:10 #26 0x7f0504c71660 in mozilla::dom::ScriptLoader::ProcessScriptElement(nsIScriptElement*) firefox-source/dom/script/ScriptLoader.cpp:1201:10 #27 0x7f0504c70f72 in mozilla::dom::ScriptElement::MaybeProcessScript() firefox-source/dom/script/ScriptElement.cpp:210:18 #28 0x7f04fb36fdc6 in AttemptToExecute firefox-source/objdir-ff-asan/dist/include/nsIScriptElement.h:224:18 #29 0x7f04fb36fdc6 in nsHtml5TreeOpExecutor::RunScript(nsIContent*, bool) firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:900:22 #30 0x7f04fb36b85a in nsHtml5TreeOpExecutor::RunFlushLoop() firefox-source/parser/html/nsHtml5TreeOpExecutor.cpp:685:7 #31 0x7f04fb3afccb in nsHtml5ExecutorFlusher::Run() firefox-source/parser/html/nsHtml5StreamParser.cpp:161:18 #32 0x7f04f911ff0a in mozilla::RunnableTask::Run() firefox-source/xpcom/threads/TaskController.cpp:688:16 #33 0x7f04f90fff3d in mozilla::TaskController::RunTask(mozilla::Task*) firefox-source/xpcom/threads/TaskController.cpp:215:19 #34 0x7f04f9106ea0 in mozilla::TaskController::DoExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:1015:20 #35 0x7f04f91048a8 in mozilla::TaskController::ExecuteNextTaskOnlyMainThreadInternal(mozilla::detail::BaseAutoLock<mozilla::Mutex&> const&) firefox-source/xpcom/threads/TaskController.cpp:838:15 #36 0x7f04f9104ec6 in mozilla::TaskController::ProcessPendingMTTask(bool) firefox-source/xpcom/threads/TaskController.cpp:624:36 #37 0x7f04f910ea51 in operator() firefox-source/xpcom/threads/TaskController.cpp:336:37 #38 0x7f04f910ea51 in mozilla::detail::RunnableFunction<mozilla::TaskController::TaskController()::$_0>::Run() firefox-source/xpcom/threads/nsThreadUtils.h:548:5 #39 0x7f04f91502bf in nsThread::ProcessNextEvent(bool, bool*) firefox-source/xpcom/threads/nsThread.cpp:1159:16 #40 0x7f04f915a6c0 in NS_ProcessNextEvent(nsIThread*, bool) firefox-source/xpcom/threads/nsThreadUtils.cpp:480:10 SUMMARY: AddressSanitizer: heap-use-after-free firefox-source/dom/base/nsINode.h:2413:46 in GetExistingSlots Shadow bytes around the buggy address: 0x51e000017e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x51e000017e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x51e000017f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fa 0x51e000017f80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x51e000018000: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa =>0x51e000018080: fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd 0x51e000018100: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018200: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018280: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x51e000018300: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==766789==ABORTING ```