Buffer Overflow @ [gfxTextRun::AddGlyphRun]

RESOLVED FIXED

Status

()

Core
Graphics: Text
--
critical
RESOLVED FIXED
9 months ago
9 months ago

People

(Reporter: jkratzer, Assigned: jfkthame)

Tracking

(Blocks: 1 bug, 5 keywords)

unspecified
crash, csectype-bounds, regression, sec-high, testcase
Points:
---
Dependency tree / graph
Bug Flags:
in-testsuite ?

Firefox Tracking Flags

(firefox-esr52 unaffected, firefox53 unaffected, firefox54 unaffected, firefox55 fixed)

Details

Attachments

(3 attachments)

(Reporter)

Description

9 months ago
Created attachment 8863764 [details]
Testcase

Testcase found while fuzzing mozilla-inbound rev 20170502-82f7bbcf6129.  Current testcase is not fully reduced - will update shortly.  Testcase also requires the fuzzPriv extension in order to resize the window to 800x600:

https://github.com/MozillaSecurity/funfuzz/tree/master/dom/extension

==884==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7fd6c199c608 at pc 0x7fd6b55b1d8f bp 0x7ffc3e62f910 sp 0x7ffc3e62f908
READ of size 8 at 0x7fd6c199c608 thread T0
    #0 0x7fd6b55b1d8e in operator-- /home/worker/workspace/build/src/obj-firefox/dist/include/nsISupportsImpl.h:300:34
    #1 0x7fd6b55b1d8e in Release /home/worker/workspace/build/src/gfx/thebes/gfxFont.h:1375
    #2 0x7fd6b55b1d8e in Release /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RefPtr.h:40
    #3 0x7fd6b55b1d8e in Release /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RefPtr.h:395
    #4 0x7fd6b55b1d8e in assign_assuming_AddRef /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RefPtr.h:65
    #5 0x7fd6b55b1d8e in assign_with_AddRef /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RefPtr.h:56
    #6 0x7fd6b55b1d8e in operator= /home/worker/workspace/build/src/obj-firefox/dist/include/mozilla/RefPtr.h:191
    #7 0x7fd6b55b1d8e in gfxTextRun::AddGlyphRun(gfxFont*, unsigned char, unsigned int, bool, unsigned short) /home/worker/workspace/build/src/gfx/thebes/gfxTextRun.cpp:1347
    #8 0x7fd6b9eb694c in MergeCharactersInTextRun(gfxTextRun*, gfxTextRun*, bool const*, bool const*) /home/worker/workspace/build/src/layout/generic/nsTextRunTransformations.cpp:140:26
    #9 0x7fd6b9ebad26 in nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun*, mozilla::gfx::DrawTarget*, gfxMissingFontRecorder*) /home/worker/workspace/build/src/layout/generic/nsTextRunTransformations.cpp:702:5
    #10 0x7fd6b9e63271 in FinishSettingProperties /home/worker/workspace/build/src/layout/generic/nsTextRunTransformations.h:152:17
    #11 0x7fd6b9e63271 in BuildTextRunsScanner::BreakSink::Finish(gfxMissingFontRecorder*) /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:1128
    #12 0x7fd6b9e62ff2 in BuildTextRunsScanner::FlushLineBreaks(gfxTextRun*) /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:1655:21
    #13 0x7fd6b9e5af73 in BuildTextRunsScanner::FlushFrames(bool, bool) /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:1634:5
    #14 0x7fd6b9e6539c in BuildTextRunsScanner::ScanFrame(nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:1902:5
    #15 0x7fd6b9e6598f in BuildTextRunsScanner::ScanFrame(nsIFrame*) /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:1912:5
    #16 0x7fd6b9e6d00b in BuildTextRuns /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:1530:15
    #17 0x7fd6b9e6d00b in nsTextFrame::EnsureTextRun(nsTextFrame::TextRunType, mozilla::gfx::DrawTarget*, nsIFrame*, nsLineList_iterator const*, unsigned int*) /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:2830
    #18 0x7fd6b9eabb65 in nsTextFrame::ReflowText(nsLineLayout&, int, mozilla::gfx::DrawTarget*, mozilla::ReflowOutput&, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/nsTextFrame.cpp:9217:5
    #19 0x7fd6b9db145b in nsLineLayout::ReflowFrame(nsIFrame*, nsReflowStatus&, mozilla::ReflowOutput*, bool&) /home/worker/workspace/build/src/layout/generic/nsLineLayout.cpp:924:7
    #20 0x7fd6b9daf6a2 in nsInlineFrame::ReflowInlineFrame(nsPresContext*, mozilla::ReflowInput const&, nsInlineFrame::InlineReflowInput&, nsIFrame*, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/nsInlineFrame.cpp:798:15
    #21 0x7fd6b9dadc66 in nsInlineFrame::ReflowFrames(nsPresContext*, mozilla::ReflowInput const&, nsInlineFrame::InlineReflowInput&, mozilla::ReflowOutput&, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/nsInlineFrame.cpp:681:7
    #22 0x7fd6b9dacee9 in nsInlineFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/nsInlineFrame.cpp:460:3
    #23 0x7fd6b9db15b5 in nsLineLayout::ReflowFrame(nsIFrame*, nsReflowStatus&, mozilla::ReflowOutput*, bool&) /home/worker/workspace/build/src/layout/generic/nsLineLayout.cpp:921:13
    #24 0x7fd6b9c3a7c4 in nsBlockFrame::ReflowInlineFrame(mozilla::BlockReflowInput&, nsLineLayout&, nsLineList_iterator, nsIFrame*, LineReflowStatus*) /home/worker/workspace/build/src/layout/generic/nsBlockFrame.cpp:4215:15
    #25 0x7fd6b9c395ac in nsBlockFrame::DoReflowInlineFrames(mozilla::BlockReflowInput&, nsLineLayout&, nsLineList_iterator, nsFlowAreaRect&, int&, nsFloatManager::SavedState*, bool*, LineReflowStatus*, bool) /home/worker/workspace/build/src/layout/generic/nsBlockFrame.cpp:4016:5
    #26 0x7fd6b9c30d06 in nsBlockFrame::ReflowInlineFrames(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /home/worker/workspace/build/src/layout/generic/nsBlockFrame.cpp:3890:9
    #27 0x7fd6b9c2a778 in nsBlockFrame::ReflowLine(mozilla::BlockReflowInput&, nsLineList_iterator, bool*) /home/worker/workspace/build/src/layout/generic/nsBlockFrame.cpp:2876:5
    #28 0x7fd6b9c204e0 in nsBlockFrame::ReflowDirtyLines(mozilla::BlockReflowInput&) /home/worker/workspace/build/src/layout/generic/nsBlockFrame.cpp:2412:7
    #29 0x7fd6b9c16fca in nsBlockFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/nsBlockFrame.cpp:1232:3
    #30 0x7fd6b9c72b4a in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, nsReflowStatus&, nsOverflowContinuationTracker*) /home/worker/workspace/build/src/layout/generic/nsContainerFrame.cpp:898:14
    #31 0x7fd6b9c714be in nsCanvasFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/nsCanvasFrame.cpp:740:5
    #32 0x7fd6b9c72b4a in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, mozilla::WritingMode const&, mozilla::LogicalPoint const&, nsSize const&, unsigned int, nsReflowStatus&, nsOverflowContinuationTracker*) /home/worker/workspace/build/src/layout/generic/nsContainerFrame.cpp:898:14
    #33 0x7fd6b9d1a92d in nsHTMLScrollFrame::ReflowScrolledFrame(mozilla::ScrollReflowInput*, bool, bool, mozilla::ReflowOutput*, bool) /home/worker/workspace/build/src/layout/generic/nsGfxScrollFrame.cpp:549:3
    #34 0x7fd6b9d1bff3 in nsHTMLScrollFrame::ReflowContents(mozilla::ScrollReflowInput*, mozilla::ReflowOutput const&) /home/worker/workspace/build/src/layout/generic/nsGfxScrollFrame.cpp:661:3
    #35 0x7fd6b9d1f086 in nsHTMLScrollFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/nsGfxScrollFrame.cpp:1037:3
    #36 0x7fd6b9bff0c3 in nsContainerFrame::ReflowChild(nsIFrame*, nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, int, int, unsigned int, nsReflowStatus&, nsOverflowContinuationTracker*) /home/worker/workspace/build/src/layout/generic/nsContainerFrame.cpp:942:14
    #37 0x7fd6b9bfdb9f in mozilla::ViewportFrame::Reflow(nsPresContext*, mozilla::ReflowOutput&, mozilla::ReflowInput const&, nsReflowStatus&) /home/worker/workspace/build/src/layout/generic/ViewportFrame.cpp:328:7
    #38 0x7fd6b9a179be in mozilla::PresShell::DoReflow(nsIFrame*, bool) /home/worker/workspace/build/src/layout/base/PresShell.cpp:9317:11
    #39 0x7fd6b9a2a751 in mozilla::PresShell::ProcessReflowCommands(bool) /home/worker/workspace/build/src/layout/base/PresShell.cpp:9490:24
    #40 0x7fd6b9a298b2 in mozilla::PresShell::DoFlushPendingNotifications(mozilla::ChangesToFlush) /home/worker/workspace/build/src/layout/base/PresShell.cpp:4213:11
    #41 0x7fd6b999f5f3 in FlushPendingNotifications /home/worker/workspace/build/src/layout/base/nsIPresShell.h:599:5
    #42 0x7fd6b999f5f3 in nsRefreshDriver::Tick(long, mozilla::TimeStamp) /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:1858
    #43 0x7fd6b99ad9a3 in mozilla::RefreshDriverTimer::TickRefreshDrivers(long, mozilla::TimeStamp, nsTArray<RefPtr<nsRefreshDriver> >&) /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:300:7
    #44 0x7fd6b99ad662 in mozilla::RefreshDriverTimer::Tick(long, mozilla::TimeStamp) /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:321:5
    #45 0x7fd6b99afc9b in RunRefreshDrivers /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:752:5
    #46 0x7fd6b99afc9b in mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::TickRefreshDriver(mozilla::TimeStamp) /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:665
    #47 0x7fd6b99ab097 in mozilla::VsyncRefreshDriverTimer::RefreshDriverVsyncObserver::ParentProcessVsyncNotifier::Run() /home/worker/workspace/build/src/layout/base/nsRefreshDriver.cpp:512:20
    #48 0x7fd6b3376790 in nsThread::ProcessNextEvent(bool, bool*) /home/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1270:14
    #49 0x7fd6b33731d8 in NS_ProcessNextEvent(nsIThread*, bool) /home/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:393:10
    #50 0x7fd6b4103861 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /home/worker/workspace/build/src/ipc/glue/MessagePump.cpp:96:21
    #51 0x7fd6b4066d60 in RunInternal /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:238:10
    #52 0x7fd6b4066d60 in RunHandler /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:231
    #53 0x7fd6b4066d60 in MessageLoop::Run() /home/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:211
    #54 0x7fd6b930383f in nsBaseAppShell::Run() /home/worker/workspace/build/src/widget/nsBaseAppShell.cpp:156:27
    #55 0x7fd6bc743331 in nsAppStartup::Run() /home/worker/workspace/build/src/toolkit/components/startup/nsAppStartup.cpp:283:30
    #56 0x7fd6bc903414 in XREMain::XRE_mainRun() /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4541:22
    #57 0x7fd6bc904e6c in XREMain::XRE_main(int, char**, mozilla::BootstrapConfig const&) /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4721:8
    #58 0x7fd6bc90606c in XRE_main(int, char**, mozilla::BootstrapConfig const&) /home/worker/workspace/build/src/toolkit/xre/nsAppRunner.cpp:4814:21
    #59 0x4eb3c3 in do_main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:236:22
    #60 0x4eb3c3 in main /home/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:307
    #61 0x7fd6ceb0b82f in __libc_start_main /build/glibc-Qz8a69/glibc-2.23/csu/../csu/libc-start.c:291
    #62 0x41cf18 in _start (/home/forb1dden/Shared/Mozilla/builds/asan-inbound/firefox+0x41cf18)

0x7fd6c199c608 is located 56 bytes to the left of global variable 'tPath' defined in '/home/worker/workspace/build/src/xpcom/io/SpecialSystemDirectory.cpp:502:26' (0x7fd6c199c640) of size 8
0x7fd6c199c608 is located 0 bytes to the right of global variable 'nsTArrayHeader::sEmptyHdr' defined in '/home/worker/workspace/build/src/xpcom/ds/nsTArray.cpp:14:32' (0x7fd6c199c600) of size 8
SUMMARY: AddressSanitizer: global-buffer-overflow /home/worker/workspace/build/src/obj-firefox/dist/include/nsISupportsImpl.h:300:34 in operator--
Shadow bytes around the buggy address:
  0x0ffb5832b870: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffb5832b880: 00 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9
  0x0ffb5832b890: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffb5832b8a0: 00 f9 f9 f9 f9 f9 f9 f9 01 f9 f9 f9 f9 f9 f9 f9
  0x0ffb5832b8b0: 04 f9 f9 f9 f9 f9 f9 f9 00 00 00 00 00 00 00 00
=>0x0ffb5832b8c0: 00[f9]f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffb5832b8d0: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffb5832b8e0: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffb5832b8f0: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffb5832b900: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
  0x0ffb5832b910: 00 f9 f9 f9 f9 f9 f9 f9 00 f9 f9 f9 f9 f9 f9 f9
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
==884==ABORTING
Flags: in-testsuite?
Group: core-security → layout-core-security
read of a pointer-sized object during Release() doesn't sound like an integer overflow symptom.
Keywords: csectype-intoverflow
(Reporter)

Comment 2

9 months ago
Created attachment 8864223 [details]
Updated Testcase

Attached reduced testcase.
Component: Layout: View Rendering → Graphics: Text
(Assignee)

Comment 3

9 months ago
Regression from bug 1360620, almost certainly.
Blocks: 1360620
Keywords: regression
(Assignee)

Comment 4

9 months ago
Created attachment 8864525 [details] [diff] [review]
Use ConvertFromGlyphRunArray to implement ResetGlyphRuns

The bug here is that ResetGlyphRuns leaves the mSingleGlyphRun/mGlyphRunArray union in the wrong state if there were multiple glyphruns in the target textrun: it clears the mHasGlyphRunArray flag, but the union still holds the empty nsTArray, so the mSingleGlyphRun.mFont field is not a valid RefPtr, and we will crash or corrupt something next time anyone tries to modify it. We could fix this by explicitly re-constructing the mSingleGlyphRun field with a placement-new, but I think it's better to just leverage the existing ConvertFromGlyphRunArray method which already does this correctly.
Attachment #8864525 - Flags: review?(jmuizelaar)
(Assignee)

Updated

9 months ago
Assignee: nobody → jfkthame
Status: NEW → ASSIGNED
(Assignee)

Updated

9 months ago
Duplicate of this bug: 1361648
Attachment #8864525 - Flags: review?(jmuizelaar) → review+
Keywords: csectype-bounds, sec-high
(Assignee)

Comment 6

9 months ago
https://hg.mozilla.org/integration/mozilla-inbound/rev/7d01a99fc2f923f9adc9c92e1eaf0995099d8dbe
Bug 1361395 - Use ConvertFromGlyphRunArray to implement ResetGlyphRuns. r=jrmuizel
https://hg.mozilla.org/mozilla-central/rev/7d01a99fc2f9
Status: ASSIGNED → RESOLVED
Last Resolved: 9 months ago
status-firefox55: --- → fixed
Resolution: --- → FIXED
status-firefox53: --- → unaffected
status-firefox54: --- → unaffected
status-firefox-esr52: --- → unaffected
(Assignee)

Updated

9 months ago
Duplicate of this bug: 1362311
Group: layout-core-security
You need to log in before you can comment on or make changes to this bug.