Closed Bug 1401420 Opened 7 years ago Closed 7 years ago

AddressSanitizer: use-after-poison [@ GetNextSibling] with READ of size 8 in layout/generic/nsIFrame.h:1431:45

Categories

(Core :: Layout, defect, P2)

52 Branch
defect

Tracking

()

RESOLVED FIXED
mozilla58
Tracking Status
firefox-esr52 --- wontfix
firefox55 --- wontfix
firefox56 --- wontfix
firefox57 - wontfix
firefox58 + fixed

People

(Reporter: jkratzer, Assigned: xidorn)

References

(Blocks 2 open bugs)

Details

(5 keywords, Whiteboard: [adv-main58+][post-critsmash-triage])

Attachments

(7 files)

Found while fuzzing mozilla-esr rev d6f78b1349b7.  I will update with a testcase shortly.

==11421==ERROR: AddressSanitizer: use-after-poison on address 0x625000887360 at pc 0x7fbcc0682388 bp 0x7ffc0db05320 sp 0x7ffc0db05318
READ of size 8 at 0x625000887360 thread T0
    #0 0x7fbcc0682387 in GetNextSibling /home/worker/workspace/build/src/layout/generic/nsIFrame.h:1431:45
    #1 0x7fbcc0682387 in RemoveFrame /home/worker/workspace/build/src/layout/generic/nsFrameList.cpp:80
    #2 0x7fbcc0682387 in RemoveFirstChild /home/worker/workspace/build/src/layout/generic/nsFrameList.cpp:127
    #3 0x7fbcc0682387 in DestroyFramesFrom /home/worker/workspace/build/src/layout/generic/nsFrameList.cpp:56
    #4 0x7fbcc0682387 in nsBlockFrame::DestroyFrom(nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsBlockFrame.cpp:323
    #5 0x7fbcc0682d78 in DestroyFramesFrom /home/worker/workspace/build/src/layout/generic/nsFrameList.cpp:57:5
    #6 0x7fbcc0682d78 in nsContainerFrame::DestroyFrom(nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsContainerFrame.cpp:221
    #7 0x7fbcc0682d78 in DestroyFramesFrom /home/worker/workspace/build/src/layout/generic/nsFrameList.cpp:57:5
    #8 0x7fbcc0682d78 in nsContainerFrame::DestroyFrom(nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsContainerFrame.cpp:221
    #9 0x7fbcc06e3915 in nsCanvasFrame::DestroyFrom(nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsCanvasFrame.cpp:153:3
    #10 0x7fbcc0682d78 in DestroyFramesFrom /home/worker/workspace/build/src/layout/generic/nsFrameList.cpp:57:5
    #11 0x7fbcc0682d78 in nsContainerFrame::DestroyFrom(nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsContainerFrame.cpp:221
    #12 0x7fbcc06f6cca in Destroy /home/worker/workspace/build/src/layout/generic/nsIFrame.h:576:20
    #13 0x7fbcc06f6cca in nsContainerFrame::RemoveFrame(mozilla::layout::FrameChildListID, nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsContainerFrame.cpp:170
    #14 0x7fbcc0523506 in nsFrameManager::RemoveFrame(mozilla::layout::FrameChildListID, nsIFrame*) /home/worker/workspace/build/src/layout/base/nsFrameManager.cpp:506:5
    #15 0x7fbcc03f19bb in nsCSSFrameConstructor::ContentRemoved(nsIContent*, nsIContent*, nsIContent*, nsCSSFrameConstructor::RemoveFlags, bool*, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:8507:5
    #16 0x7fbcc036643e in nsCSSFrameConstructor::RecreateFramesForContent(nsIContent*, bool, nsCSSFrameConstructor::RemoveFlags, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:9694:10
    #17 0x7fbcc03847f6 in mozilla::RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList&) /home/worker/workspace/build/src/layout/base/RestyleManagerBase.cpp:1176:7
    #18 0x7fbcc0366a14 in mozilla::RestyleManager::ComputeAndProcessStyleChange(nsIFrame*, nsChangeHint, mozilla::RestyleTracker&, nsRestyleHint, mozilla::RestyleHintData const&) /home/worker/workspace/build/src/layout/base/RestyleManager.cpp:3804:3
    #19 0x7fbcc0365055 in mozilla::RestyleManager::RestyleElement(mozilla::dom::Element*, nsIFrame*, nsChangeHint, mozilla::RestyleTracker&, nsRestyleHint, mozilla::RestyleHintData const&) /home/worker/workspace/build/src/layout/base/RestyleManager.cpp:152:5
    #20 0x7fbcc038b64c in ProcessOneRestyle /home/worker/workspace/build/src/layout/base/RestyleTracker.cpp:97:5
    #21 0x7fbcc038b64c in mozilla::RestyleTracker::DoProcessRestyles() /home/worker/workspace/build/src/layout/base/RestyleTracker.cpp:266
    #22 0x7fbcc036d5d4 in ProcessRestyles /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RestyleManager.h:490:7
    #23 0x7fbcc036d5d4 in mozilla::RestyleManager::ProcessPendingRestyles() /home/worker/workspace/build/src/layout/base/RestyleManager.cpp:834
    #24 0x7fbcc05af3ce in ProcessPendingRestyles /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RestyleManagerHandleInlines.h:74:3
    #25 0x7fbcc05af3ce in PresShell::FlushPendingNotifications(mozilla::ChangesToFlush) /home/worker/workspace/build/src/layout/base/nsPresShell.cpp:4167
    #26 0x7fbcbc42a490 in nsDocument::FlushPendingNotifications(mozFlushType) /home/worker/workspace/build/src/dom/base/nsDocument.cpp:7781:7
    #27 0x7fbcbc1e7760 in GetPrimaryFrame /home/worker/workspace/build/src/dom/base/Element.cpp:2194:5
    #28 0x7fbcbc1e7760 in mozilla::dom::Element::GetBoundingClientRect() /home/worker/workspace/build/src/dom/base/Element.cpp:979
    #29 0x7fbcbd9ecbcc in mozilla::dom::ElementBinding::getBoundingClientRect(JSContext*, JS::Handle<JSObject*>, mozilla::dom::Element*, JSJitMethodCallArgs const&) /home/worker/workspace/build/src/obj-firefox/dom/bindings/ElementBinding.cpp:2048:53
    #30 0x7fbcbdf3e6b9 in mozilla::dom::GenericBindingMethod(JSContext*, unsigned int, JS::Value*) /home/worker/workspace/build/src/dom/bindings/BindingUtils.cpp:2904:13
    #31 0x7fbcc42c7e55 in CallJSNative /home/worker/workspace/build/src/js/src/jscntxtinlines.h:239:15
    #32 0x7fbcc42c7e55 in js::InternalCallOrConstruct(JSContext*, JS::CallArgs const&, js::MaybeConstruct) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:447
    #33 0x7fbcc42a825f in CallFromStack /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:510:12
    #34 0x7fbcc42a825f in Interpret(JSContext*, js::RunState&) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:2922
    #35 0x7fbcc428d41d in js::RunScript(JSContext*, js::RunState&) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:405:12
    #36 0x7fbcc42ca342 in js::ExecuteKernel(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value const&, js::AbstractFramePtr, JS::Value*) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:686:15
    #37 0x7fbcc42cabdb in js::Execute(JSContext*, JS::Handle<JSScript*>, JSObject&, JS::Value*) /home/worker/workspace/build/src/js/src/vm/Interpreter.cpp:718:12
    #38 0x7fbcc3dac3b4 in Evaluate(JSContext*, js::ScopeKind, JS::Handle<JSObject*>, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/worker/workspace/build/src/js/src/jsapi.cpp:4439:19
    #39 0x7fbcc3dad10b in Evaluate /home/worker/workspace/build/src/js/src/jsapi.cpp:4466:12
    #40 0x7fbcc3dad10b in JS::Evaluate(JSContext*, JS::AutoObjectVector&, JS::ReadOnlyCompileOptions const&, JS::SourceBufferHolder&, JS::MutableHandle<JS::Value>) /home/worker/workspace/build/src/js/src/jsapi.cpp:4524
    #41 0x7fbcbc52fe10 in nsJSUtils::EvaluateString(JSContext*, JS::SourceBufferHolder&, JS::Handle<JSObject*>, JS::CompileOptions&, nsJSUtils::EvaluateOptions const&, JS::MutableHandle<JS::Value>, void**) /home/worker/workspace/build/src/dom/base/nsJSUtils.cpp:207:12
    #42 0x7fbcbc530f29 in nsJSUtils::EvaluateString(JSContext*, JS::SourceBufferHolder&, JS::Handle<JSObject*>, JS::CompileOptions&, void**) /home/worker/workspace/build/src/dom/base/nsJSUtils.cpp:274:10
    #43 0x7fbcbc5c78a1 in nsScriptLoader::EvaluateScript(nsScriptLoadRequest*) /home/worker/workspace/build/src/dom/base/nsScriptLoader.cpp:2193:14
    #44 0x7fbcbc5c47ae in nsScriptLoader::ProcessRequest(nsScriptLoadRequest*) /home/worker/workspace/build/src/dom/base/nsScriptLoader.cpp:1979:10
    #45 0x7fbcbc5abb05 in nsScriptLoader::ProcessScriptElement(nsIScriptElement*) /home/worker/workspace/build/src/dom/base/nsScriptLoader.cpp:1712:10
    #46 0x7fbcbc5a8471 in nsScriptElement::MaybeProcessScript() /home/worker/workspace/build/src/dom/base/nsScriptElement.cpp:149:10
    #47 0x7fbcbb619a43 in AttemptToExecute /home/worker/workspace/build/src/dom/base/nsIScriptElement.h:222:18
    #48 0x7fbcbb619a43 in nsHtml5TreeOpExecutor::RunScript(nsIContent*) /home/worker/workspace/build/src/parser/html/nsHtml5TreeOpExecutor.cpp:666
    #49 0x7fbcbb6181c5 in nsHtml5TreeOpExecutor::RunFlushLoop() /home/worker/workspace/build/src/parser/html/nsHtml5TreeOpExecutor.cpp:489:7
    #50 0x7fbcbb61e00f in nsHtml5ExecutorReflusher::Run() /home/worker/workspace/build/src/parser/html/nsHtml5TreeOpExecutor.cpp:58:7
    #51 0x7fbcb97af7bb in nsThread::ProcessNextEvent(bool, bool*) /home/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1216:7
    #52 0x7fbcb98318fc in NS_ProcessNextEvent(nsIThread*, bool) /home/worker/workspace/build/src/xpcom/glue/nsThreadUtils.cpp:361:10
    #53 0x7fbcba5ea57f in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /home/worker/workspace/build/src/ipc/glue/MessagePump.cpp:96:21
    #54 0x7fbcba55c0d8 in RunInternal /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:232:3
    #55 0x7fbcba55c0d8 in RunHandler /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:225
    #56 0x7fbcba55c0d8 in MessageLoop::Run() /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:205
    #57 0x7fbcbfbf4fff in nsBaseAppShell::Run() /home/worker/workspace/build/src/widget/nsBaseAppShell.cpp:156:3
    #58 0x7fbcc1c72d31 in nsAppStartup::Run() /home/worker/workspace/build/src/toolkit/components/startup/nsAppStartup.cpp:283:19
    #59 0x7fbcc1e0a047 in XREMain::XRE_mainRun() /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4488:10
    #60 0x7fbcc1e0b7bd in XREMain::XRE_main(int, char**, nsXREAppData const*) /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4621:8
    #61 0x7fbcc1e0c67c in XRE_main /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4712:16
    #62 0x4df91a in do_main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:282:10
    #63 0x4df91a in main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:415
    #64 0x7fbcd595b82f in __libc_start_main /build/glibc-bfm8X4/glibc-2.23/csu/../csu/libc-start.c:291
    #65 0x41ba88 in _start (/home/forb1dden/builds/esr-asan/firefox+0x41ba88)

0x625000887360 is located 2656 bytes inside of 8192-byte region [0x625000886900,0x625000888900)
allocated by thread T0 here:
    #0 0x4b24fb in malloc /builds/slave/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:52:3
    #1 0x7fbcd2bfda24 in PL_ArenaAllocate /home/worker/workspace/build/src/nsprpub/lib/ds/plarena.c:127:27
    #2 0x7fbcc02b8041 in nsPresArena::Allocate(unsigned int, unsigned long) /home/worker/workspace/build/src/layout/base/nsPresArena.cpp:165:3
    #3 0x7fbcc022be19 in AllocateByObjectID /home/worker/workspace/build/src/layout/base/nsPresArena.h:65:12
    #4 0x7fbcc022be19 in AllocateByObjectID /home/worker/workspace/build/src/layout/base/nsIPresShell.h:250
    #5 0x7fbcc022be19 in operator new /home/worker/workspace/build/src/layout/style/nsStyleStruct.h:2770
    #6 0x7fbcc022be19 in nsStyleContext::GetUniqueStyleData(nsStyleStructID const&) /home/worker/workspace/build/src/layout/style/nsStyleContext.cpp:539
    #7 0x7fbcc02265ad in nsStyleContext::ApplyStyleFixups(bool) /home/worker/workspace/build/src/layout/style/nsStyleContext.cpp:843:41
    #8 0x7fbcc0235b88 in NS_NewStyleContext(nsStyleContext*, nsIAtom*, mozilla::CSSPseudoElementType, nsRuleNode*, bool) /home/worker/workspace/build/src/layout/style/nsStyleContext.cpp:1435:5
    #9 0x7fbcc02411a6 in nsStyleSet::GetContext(nsStyleContext*, nsRuleNode*, nsRuleNode*, nsIAtom*, mozilla::CSSPseudoElementType, mozilla::dom::Element*, unsigned int) /home/worker/workspace/build/src/layout/style/nsStyleSet.cpp:943:14
    #10 0x7fbcc02464a3 in nsStyleSet::ResolveStyleFor(mozilla::dom::Element*, nsStyleContext*, TreeMatchContext&) /home/worker/workspace/build/src/layout/style/nsStyleSet.cpp:1392:10
    #11 0x7fbcc0245cd9 in nsStyleSet::ResolveStyleFor(mozilla::dom::Element*, nsStyleContext*) /home/worker/workspace/build/src/layout/style/nsStyleSet.cpp:1350:10
    #12 0x7fbcc058184f in ResolveStyleFor /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/StyleSetHandleInlines.h:84:3
    #13 0x7fbcc058184f in GetPropagatedScrollbarStylesForViewport(nsPresContext*, mozilla::ScrollbarStyles*) /home/worker/workspace/build/src/layout/base/nsPresContext.cpp:1382
    #14 0x7fbcc0580df9 in nsPresContext::UpdateViewportScrollbarStylesOverride() /home/worker/workspace/build/src/layout/base/nsPresContext.cpp:1430:7
    #15 0x7fbcc03f042f in nsCSSFrameConstructor::ContentRemoved(nsIContent*, nsIContent*, nsIContent*, nsCSSFrameConstructor::RemoveFlags, bool*, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:8253:5
    #16 0x7fbcc036643e in nsCSSFrameConstructor::RecreateFramesForContent(nsIContent*, bool, nsCSSFrameConstructor::RemoveFlags, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:9694:10
    #17 0x7fbcc03f332e in nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame*, nsCSSFrameConstructor::RemoveFlags, nsresult*, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:9437:18
    #18 0x7fbcc03660da in nsCSSFrameConstructor::RecreateFramesForContent(nsIContent*, bool, nsCSSFrameConstructor::RemoveFlags, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:9668:16
    #19 0x7fbcc03f357a in nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame*, nsCSSFrameConstructor::RemoveFlags, nsresult*, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:9484:16
    #20 0x7fbcc03660da in nsCSSFrameConstructor::RecreateFramesForContent(nsIContent*, bool, nsCSSFrameConstructor::RemoveFlags, nsIContent**) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:9668:16
    #21 0x7fbcc03ee9ee in nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState&, nsIFrame*, nsIFrame*, nsCSSFrameConstructor::FrameConstructionItemList&, bool, nsIFrame*) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:12214:5
    #22 0x7fbcc03eb996 in nsCSSFrameConstructor::ContentAppended(nsIContent*, nsIContent*, bool) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:7500:7
    #23 0x7fbcc03e6a98 in nsCSSFrameConstructor::CreateNeededFrames(nsIContent*) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:7165:5
    #24 0x7fbcc03e6b45 in nsCSSFrameConstructor::CreateNeededFrames(nsIContent*) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:7172:7
    #25 0x7fbcc03e6b45 in nsCSSFrameConstructor::CreateNeededFrames(nsIContent*) /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:7172:7
    #26 0x7fbcc036d4c6 in CreateNeededFrames /home/worker/workspace/build/src/layout/base/nsCSSFrameConstructor.cpp:7187:5
    #27 0x7fbcc036d4c6 in mozilla::RestyleManager::ProcessPendingRestyles() /home/worker/workspace/build/src/layout/base/RestyleManager.cpp:793
    #28 0x7fbcc05af3ce in ProcessPendingRestyles /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RestyleManagerHandleInlines.h:74:3
    #29 0x7fbcc05af3ce in PresShell::FlushPendingNotifications(mozilla::ChangesToFlush) /home/worker/workspace/build/src/layout/base/nsPresShell.cpp:4167
    #30 0x7fbcc02c102c in nsRefreshDriver::Tick(long, mozilla::TimeStamp) /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:1836:11
    #31 0x7fbcc02cd871 in mozilla::RefreshDriverTimer::TickRefreshDrivers(long, mozilla::TimeStamp, nsTArray<RefPtr<nsRefreshDriver> >&) /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:295:7
    #32 0x7fbcc02cd305 in mozilla::RefreshDriverTimer::Tick(long, mozilla::TimeStamp) /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:316:5
    #33 0x7fbcc02cfe2e in applyImpl<mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver, void (mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::*)(mozilla::TimeStamp), StoreCopyPassByValue<mozilla::TimeStamp> , 0> /home/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:775:12
    #34 0x7fbcc02cfe2e in apply<mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver, void (mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::*)(mozilla::TimeStamp)> /home/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:781
    #35 0x7fbcc02cfe2e in mozilla::detail::RunnableMethodImpl<void (mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::*)(mozilla::TimeStamp), true, false, mozilla::TimeStamp>::Run() /home/worker/workspace/build/src/obj-firefox/dist/include/nsThreadUtils.h:810
    #36 0x7fbcb97af7bb in nsThread::ProcessNextEvent(bool, bool*) /home/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1216:7
    #37 0x7fbcb98318fc in NS_ProcessNextEvent(nsIThread*, bool) /home/worker/workspace/build/src/xpcom/glue/nsThreadUtils.cpp:361:10

SUMMARY: AddressSanitizer: use-after-poison /home/worker/workspace/build/src/layout/generic/nsIFrame.h:1431:45 in GetNextSibling
Shadow bytes around the buggy address:
  0x0c4a80108e10: 00 00 00 00 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7
  0x0c4a80108e20: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c4a80108e30: f7 f7 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c4a80108e40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f7 f7
  0x0c4a80108e50: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 00 00
=>0x0c4a80108e60: 00 00 00 00 00 00 f7 f7 f7 f7 f7 f7[f7]f7 f7 f7
  0x0c4a80108e70: f7 f7 f7 f7 f7 00 00 00 00 00 00 00 00 00 00 00
  0x0c4a80108e80: f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7 f7
  0x0c4a80108e90: f7 f7 f7 f7 f7 f7 f7 f7 00 00 00 00 00 00 00 00
  0x0c4a80108ea0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c4a80108eb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
==11421==ABORTING
Flags: in-testsuite?
Attached file trigger.html —
Also crashes a Nightly opt build with a null-deref: bp-2b973f39-3394-45b6-aa20-259840170921

Did we fix this UAF on trunk and my crash is something else, or is that just the normal opt symptom for this testcase?

If it doesn't repro on trunk then finding out where this got fixed will help us identify a potential patch to backport.
Group: core-security → layout-core-security
Flags: needinfo?(jkratzer)
Version: unspecified → 52 Branch
(In reply to Daniel Veditz [:dveditz] from comment #2)
> Also crashes a Nightly opt build with a null-deref:
> bp-2b973f39-3394-45b6-aa20-259840170921
> 
> Did we fix this UAF on trunk and my crash is something else, or is that just
> the normal opt symptom for this testcase?
> 
> If it doesn't repro on trunk then finding out where this got fixed will help
> us identify a potential patch to backport.

I thought I had tested this against mozilla-central (that's why I submitted it against ESR) but apparently, I did not.  I just confirmed that this triggers the same crash on mozilla-central rev 47f7b6c64265 (2017-09-21).
Flags: needinfo?(jkratzer)
Changing the test case from display:ruby-base-container to display:block prevents the crash. 

Xidorn: WDYT?
Flags: needinfo?(xidorn+moz)
On debug builds, this hits:
Assertion failure: aFloat->GetParent() == mBlock || (aFloat->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT) (float should be in this block unless it was marked as pushed float), at /builds/worker/workspace/build/src/layout/generic/BlockReflowInput.cpp:581

Also, this definitely crashes ESR52 builds as well, so re-marking that as affected.
(In reply to Ryan VanderMeulen [:RyanVM] from comment #5)
> On debug builds, this hits:
> Assertion failure: aFloat->GetParent() == mBlock || (aFloat->GetStateBits()
> & NS_FRAME_IS_PUSHED_FLOAT) (float should be in this block unless it was
> marked as pushed float), at
> /builds/worker/workspace/build/src/layout/generic/BlockReflowInput.cpp:581

This... sounds like bug 1229437...

I'll have a look.
Assignee: nobody → xidorn+moz
Flags: needinfo?(xidorn+moz)
Attached file simplified testcase —
I tried to simplify the original testcase, but couldn't make it work without having a somehow weird tree structure (column-width on <html>, and <script> is used as text at the same time as being a script, etc.)

So I tried to look at the frame tree and realized that the key is to have two ruby base containers. This is a much simpler testcase built on top of this assumption, which triggers the same crash.
So this seems to be because that we are pushing children to next-in-flow without reparenting the floats.

My plan of fixing this is
* always push to overflow list rather than push to next-in-flow directly
* reparent floats when stealing overflow frames from prev-in-flow

This will match how nsInlineFrame handles moving children.

I'll investigate whether there is any code that can be shared between nsInlineFrame and the ruby frames.
Attachment #8912510 - Flags: review?(dholbert)
It is still unclear to me, though, why this can lead to a use-after-poison (or use-after-free).

The stack in comment 0 shows one path to free the frame, but it doesn't show the other path. From the code, I don't see why a mis-parented float would be released twice.
OK so the problem here is that, the frame is added into multiple frame lists.

This is because nsLineLayout::ReflowFrame tracks the float frame via placeholder frame, and calls into BlockReflowInput::AddFloat for floats it finds. The latter may call into BlockReflowInput::PushFloatPastBreak to push the float into next continuation.

BlockReflowInput::PushFloatPastBreak calls nsBlockFrame::StealFrame to remove the float frame from its current frame list and add it to the pushed float list. Since the float frame is not a children of the block frame being called in this case, the float frame is still referenced by another frame list. It means at the end of BlockReflowInput::PushFloatPastBreak, we would have two frame list referencing the same float frame.

I'm not sure whether having a use-after-free on frame is a serious issue (e.g. do we poison frame memory when we free it?), if it is, probably we want to also do some special handling (or just release assert) in places like nsBlockFrame::StealFrame to avoid creating multiple strong references to a single frame.
I realized this via commenting out the assertion for
> aFloat->GetParent() == mBlock || (aFloat->GetStateBits() & NS_FRAME_IS_PUSHED_FLOAT)
and rerun the testcase, then I hit another assertion
> aChild->GetParent() == this
which leads to the analysis in comment 16.

It seems that both the original testcase and the simplified one in comment 7 (the testcase I add as crashtest in part 5) can trigger the same series of assertions, which means landing that crashtest has certain risk of exposing the security problem here.
Comment on attachment 8912505 [details] [diff] [review]
part 1 - Move ReparentFloatsForInlineChild from nsInlineFrame to nsContainerFrame

Review of attachment 8912505 [details] [diff] [review]:
-----------------------------------------------------------------

r=me
Attachment #8912505 - Flags: review?(dholbert) → review+
Comment on attachment 8912506 [details] [diff] [review]
part 2 - Remove some duplicate function comment from nsContainerFrame

Review of attachment 8912506 [details] [diff] [review]:
-----------------------------------------------------------------

r=me
Attachment #8912506 - Flags: review?(dholbert) → review+
Comment on attachment 8912507 [details] [diff] [review]
part 3 - Add nsContainerFrame::PushChildrenToOverflow

Review of attachment 8912507 [details] [diff] [review]:
-----------------------------------------------------------------

r=me
Attachment #8912507 - Flags: review?(dholbert) → review+
Comment on attachment 8912509 [details] [diff] [review]
part 4 - Have ruby frames only push children to overflow list, and reparent floats when adopting children from prev-in-flow

Review of attachment 8912509 [details] [diff] [review]:
-----------------------------------------------------------------

r=me
Attachment #8912509 - Flags: review?(dholbert) → review+
Comment on attachment 8912510 [details] [diff] [review]
part 5 - Add crashtest for this bug

Review of attachment 8912510 [details] [diff] [review]:
-----------------------------------------------------------------

r=me
Attachment #8912510 - Flags: review?(dholbert) → review+
(In reply to Xidorn Quan [:xidorn] UTC+10 from comment #16)
> I'm not sure whether having a use-after-free on frame is a serious issue
> (e.g. do we poison frame memory when we free it?)

It shouldn't be too serious -- we do indeed poison frame memory when we free it.  So UAF of a nsFrame shouldn't be too bad, as far as I know. (It'll crash safely.)

(Specifically:
 - nsFrame::DestroyFrom() calls shell->FreeFrame() right after invoking the ~nsFrame destructor.
 - That calls nsPresArena::FreeByFrameID
 - ...which calls nsPresArena::Free
 - ...which calls the mfbt mozWritePoison API, here:
https://dxr.mozilla.org/mozilla-central/rev/35fbf14b96a633c3f66ea13c1a163a3f3a4219b9/layout/base/nsPresArena.cpp#160
Comment on attachment 8912509 [details] [diff] [review]
part 4 - Have ruby frames only push children to overflow list, and reparent floats when adopting children from prev-in-flow

[Security approval request comment]
How easily could an exploit be constructed based on the patch?
This is a frame use-after-free. Based on information from comment 23 that frames are poisoned after being freed, it is probably not exploitable.

Do comments in the patch, the check-in comment, or tests included in the patch paint a bulls-eye on the security problem?
I don't think the patch itself indicates any security issue (it is very similar to bugs like bug 1229437, which can simply just be a fix to assertion). But it's from a security-sensitive bug can probably be a problem. As indicated in comment 17, the testcase can lead to an assertion (with another assertion commented out) which can indicate this use-after-free.

Which older supported branches are affected by this flaw?
All supported branches.

If not all supported branches, which bug introduced the flaw?

Do you have backports for the affected branches? If not, how different, hard to create, and risky will they be?
This patchset should mostly be upliftable. I'm not aware of any significant refactor happened in the related code, so if they cannot be applied cleanly, it shouldn't be hard to create backport patch either.

How likely is this patch to cause regressions; how much testing does it need?
It shouldn't be risky, as it doesn't change behavior in general. Only edge case is affected (from crash to normal).
Attachment #8912509 - Flags: sec-approval?
(Only request sec-approval for part 4 because that's the real fix. All parts before are just some simple refactoring for the fix.)

If this isn't really exploitable, I would suggest that we land the crashtest together with the patches.
(In reply to Xidorn Quan [:xidorn] UTC+10 from comment #24)
> [Security approval request comment]
> How easily could an exploit be constructed based on the patch?
> This is a frame use-after-free. Based on information from comment 23 that
> frames are poisoned after being freed, it is probably not exploitable.

In an opt build I crash on a null deref (in 57), and rax and rcx are clearly frame-poisoned values: 0x7ffffffff0dea7ff. I agree with that assessment -- no one has yet discovered a bypass for framepoisoning that we know of.

I crash on ESR-52 but it's not submitting reports. We should double-check that it's the same crash as on 56/57 but I'm not too concerned and we probably don't need the fix on that branch.
Comment on attachment 8912509 [details] [diff] [review]
part 4 - Have ruby frames only push children to overflow list, and reparent floats when adopting children from prev-in-flow

Clearing sec-approval. As a low risk bug, this can just go into trunk.
Attachment #8912509 - Flags: sec-approval?
Comment on attachment 8912509 [details] [diff] [review]
part 4 - Have ruby frames only push children to overflow list, and reparent floats when adopting children from prev-in-flow

Approval Request Comment
[Feature/Bug causing the regression]: CSS Ruby
[User impact if declined]: may crash in some edge cases
[Is this code covered by automated tests?]: yes
[Has the fix been verified in Nightly?]: just landed on inbound
[Needs manual test from QE? If yes, steps to reproduce]: no
[List of other uplifts needed for the feature/fix]: all patches in this bug
[Is the change risky?]: no
[Why is the change risky/not risky?]: it shouldn't change behavior in general, just some edge case. And I believe CSS ruby has a decent test coverage.
[String changes made/needed]: n/a
Attachment #8912509 - Flags: approval-mozilla-beta?
https://hg.mozilla.org/mozilla-central/rev/8f3f409faf2f
https://hg.mozilla.org/mozilla-central/rev/14fe3196aa1e
https://hg.mozilla.org/mozilla-central/rev/2164d769710e
https://hg.mozilla.org/mozilla-central/rev/14190aa23ce6
https://hg.mozilla.org/mozilla-central/rev/32eb992ba469

Probably not worth backporting to ESR52 since it's only a sec-low. Let's get it on Beta still, though.
Status: NEW → RESOLVED
Closed: 7 years ago
Flags: in-testsuite? → in-testsuite+
Resolution: --- → FIXED
Target Milestone: --- → mozilla58
Depends on: 1404179
Comment on attachment 8912509 [details] [diff] [review]
part 4 - Have ruby frames only push children to overflow list, and reparent floats when adopting children from prev-in-flow

looks like it's more risky than I thought.
Attachment #8912509 - Flags: approval-mozilla-beta?
Group: layout-core-security → core-security-release
This seems a wontfix for 57 based on the previous comment. Lemme know if I am wrong. Xidorn, Dan, FYI.
Flags: needinfo?(xidorn+moz)
Flags: needinfo?(dveditz)
Right, I think it is wontfix for 57 since this is sec-low that just an edge case which could cause crash, and it is more risky given there's a test intermittent introduced by this.
Flags: needinfo?(xidorn+moz)
Flags: needinfo?(dveditz)
Whiteboard: [adv-main58+]
Flags: qe-verify-
Whiteboard: [adv-main58+] → [adv-main58+][post-critsmash-triage]
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: