Closed Bug 873249 Opened 12 years ago Closed 11 years ago

Use-after-free crash with linear gradients with Skia/GL

Categories

(Core :: Graphics: Canvas2D, defect)

x86_64
Linux
defect
Not set
critical

Tracking

()

RESOLVED WORKSFORME
Tracking Status
firefox22 --- disabled
firefox23 --- disabled
firefox24 --- disabled
firefox25 --- disabled
firefox-esr17 --- unaffected
b2g18 --- unaffected

People

(Reporter: bjacob, Assigned: gw280)

References

()

Details

(Keywords: crash, csectype-uaf, sec-critical)

Crash Data

STR: 1. using Linux x86-64 2. enable GL layers and Skia/GL 3. reload a few times (less than 10 times) this page: http://philip.html5.org/tests/canvas/suite/tests/framed.2d.gradient.interpolate.zerosize.html Result: segfault with this stack: (gdb) bt #0 0x00007f02cc22e83d in nanosleep () at ../sysdeps/unix/syscall-template.S:82 #1 0x00007f02cc22e6dc in __sleep (seconds=0) at ../sysdeps/unix/sysv/linux/sleep.c:138 #2 0x00007f02c6a54b96 in ah_crap_handler (signum=11) at /hack/mozilla-central/toolkit/xre/nsSigHandlers.cpp:88 #3 0x00007f02c6a5f2f6 in nsProfileLock::FatalSignalHandler (signo=11, info=0x7fff49e6b830, context=0x7fff49e6b700) at /hack/mozilla-central/obj-firefox-debug-dmd/toolkit/profile/nsProfileLock.cpp:190 #4 <signal handler called> #5 0x00007f02c92ac93e in GrTBinHashKey<AtlasEntry, 24ul>::compare (this=0x7f02a16f9908, key=...) at /hack/mozilla-central/gfx/skia/src/gpu/GrBinHashKey.h:74 #6 0x00007f02c92ab605 in AtlasEntry::compare (this=0x7f02a16f9908, key=...) at /hack/mozilla-central/gfx/skia/src/gpu/effects/GrTextureStripAtlas.cpp:32 #7 0x00007f02c92ad421 in GrTBinHashKey<AtlasEntry, 24ul>::LT (entry=..., key=...) at /hack/mozilla-central/gfx/skia/src/gpu/GrBinHashKey.h:85 #8 0x00007f02c92ad125 in GrTHashTable<AtlasEntry, GrTBinHashKey<AtlasEntry, 24ul>, 8ul>::searchArray (this=0x7f02cb7f1940, key=...) at /hack/mozilla-central/gfx/skia/src/gpu/GrTHashCache.h:88 #9 0x00007f02c92acb73 in GrTHashTable<AtlasEntry, GrTBinHashKey<AtlasEntry, 24ul>, 8ul>::insert (this=0x7f02cb7f1940, key=..., elem=0x7f02943c18f0) at /hack/mozilla-central/gfx/skia/src/gpu/GrTHashCache.h:130 #10 0x00007f02c92ab7a7 in GrTextureStripAtlas::GetAtlas (desc=...) at /hack/mozilla-central/gfx/skia/src/gpu/effects/GrTextureStripAtlas.cpp:49 #11 0x00007f02c921dff0 in GrGradientEffect::GrGradientEffect (this=0x7f029ceca038, ctx=0x7f02b30a65c0, shader=..., sampler=0x7fff49e6c190) at /hack/mozilla-central/gfx/skia/src/effects/gradients/SkGradientShader.cpp:751 #12 0x00007f02c92229e0 in GrLinearGradient::GrLinearGradient (this=0x7f029ceca038, ctx=0x7f02b30a65c0, shader=..., sampler=0x7fff49e6c190) at /hack/mozilla-central/gfx/skia/src/effects/gradients/SkLinearGradient.cpp:524 #13 0x00007f02c9222d72 in SkLinearGradient::asNewCustomStage (this=0x7f029b896a40, context=0x7f02b30a65c0, sampler=0x7fff49e6c190) at /hack/mozilla-central/gfx/skia/src/effects/gradients/SkLinearGradient.cpp:584 #14 0x00007f02c92a0e89 in (anonymous namespace)::skPaint2GrPaintShader (dev=0x7f02935b7520, skPaint=..., constantColor=true, textures=0x7fff49e6c280, grPaint=0x7fff49e6c120) at /hack/mozilla-central/gfx/skia/src/gpu/SkGpuDevice.cpp:597 #15 0x00007f02c92a18b2 in SkGpuDevice::drawRect (this=0x7f02935b7520, draw=..., rect=..., paint=...) at /hack/mozilla-central/gfx/skia/src/gpu/SkGpuDevice.cpp:782 #16 0x00007f02c91f9bf5 in SkCanvas::drawRect (this=0x7f0296959140, r=..., paint=...) at /hack/mozilla-central/gfx/skia/src/core/SkCanvas.cpp:1521 #17 0x00007f02c91ae784 in mozilla::gfx::DrawTargetSkia::FillRect (this=0x7f02935abcc0, aRect=..., aPattern=..., aOptions=...) at /hack/mozilla-central/gfx/2d/DrawTargetSkia.cpp:367 #18 0x00007f02c740ba6c in mozilla::dom::CanvasRenderingContext2D::FillRect (this=0x7f02948f6800, x=0, y=0, w=100, h=50) at /hack/mozilla-central/content/canvas/src/CanvasRenderingContext2D.cpp:1576 #19 0x00007f02c8621b7e in mozilla::dom::CanvasRenderingContext2DBinding::fillRect (cx=0x7f02a7e25400, obj=(JSObject * const) 0x7f0297938700 [object CanvasRenderingContext2D], self=0x7f02948f6800, argc=4, vp=0x7f02b6dfe168) at /hack/mozilla-central/obj-firefox-debug-dmd/dom/bindings/CanvasRenderingContext2DBinding.cpp:1706 #20 0x00007f02c8627754 in mozilla::dom::CanvasRenderingContext2DBinding::genericMethod (cx=0x7f02a7e25400, argc=4, vp=0x7f02b6dfe168) at /hack/mozilla-central/obj-firefox-debug-dmd/dom/bindings/CanvasRenderingContext2DBinding.cpp:4153 #21 0x00007f02c9740490 in js::CallJSNative (cx=0x7f02a7e25400, native=0x7f02c862758e <mozilla::dom::CanvasRenderingContext2DBinding::genericMethod(JSContext*, unsigned int, JS::Value*)>, args=...) at /hack/mozilla-central/js/src/jscntxtinlines.h:337 #22 0x00007f02c974a3ee in js::Invoke (cx=0x7f02a7e25400, args=..., construct=js::NO_CONSTRUCT) at /hack/mozilla-central/js/src/jsinterp.cpp:426 #23 0x00007f02c9752116 in js::Interpret (cx=0x7f02a7e25400, entryFrame=0x7f02b6dfe050, interpMode=js::JSINTERP_NORMAL, useNewType=false) at /hack/mozilla-central/js/src/jsinterp.cpp:2393 #24 0x00007f02c9749f9d in js::RunScript (cx=0x7f02a7e25400, fp=0x7f02b6dfe050) at /hack/mozilla-central/js/src/jsinterp.cpp:383 #25 0x00007f02c974a4c4 in js::Invoke (cx=0x7f02a7e25400, args=..., construct=js::NO_CONSTRUCT) at /hack/mozilla-central/js/src/jsinterp.cpp:440 #26 0x00007f02c974a7b7 in js::Invoke (cx=0x7f02a7e25400, thisv=..., fval=..., argc=1, argv=0x7fff49e6e250, rval=0x7fff49e6e1c0) at /hack/mozilla-central/js/src/jsinterp.cpp:473 #27 0x00007f02c9664f51 in JS_CallFunctionValue (cx=0x7f02a7e25400, objArg=(JSObject *) 0x7f02979384c0 [object Proxy], fval=$jsval((JSObject *) 0x7f029797d5c0 [object Function "window.onload"]), argc=1, argv=0x7fff49e6e250, rval=0x7fff49e6e1c0) at /hack/mozilla-central/js/src/jsapi.cpp:5851 #28 0x00007f02c868e99b in mozilla::dom::EventHandlerNonNull::Call (this=0x7f02941ff860, cx=0x7f02a7e25400, aThisObj=(JSObject * const) 0x7f02979384c0 [object Proxy], event=..., aRv=...) at /hack/mozilla-central/obj-firefox-debug-dmd/dom/bindings/EventHandlerBinding.cpp:48 #29 0x00007f02c78d7196 in mozilla::dom::EventHandlerNonNull::Call<nsISupports*> (this=0x7f02941ff860, thisObj=@0x7f02942c33d8: 0x7f02956e4800, event=..., aRv=..., aExceptionHandling=mozilla::dom::CallbackObject::eReportExceptions) at ../../../dist/include/mozilla/dom/EventHandlerBinding.h:58 #30 0x00007f02c78d6644 in nsJSEventListener::HandleEvent (this=0x7f02942c33c0, aEvent=0x7f02b3093160) at /hack/mozilla-central/dom/src/events/nsJSEventListener.cpp:247 #31 0x00007f02c74a1356 in nsEventListenerManager::HandleEventSubType (this=0x7f0294299680, aListenerStruct=0x7f02942996b8, aListener=..., aDOMEvent=0x7f02b3093160, aCurrentTarget=0x7f02956e4800, aPusher=0x7fff49e6e900) at /hack/mozilla-central/content/events/src/nsEventListenerManager.cpp:922 #32 0x00007f02c74a161e in nsEventListenerManager::HandleEventInternal (this=0x7f0294299680, aPresContext=0x7f02965dc000, aEvent=0x7fff49e6ea10, aDOMEvent=0x7fff49e6e8e0, aCurrentTarget=0x7f02956e4800, aEventStatus=0x7fff49e6e8e8, aPusher=0x7fff49e6e900) at /hack/mozilla-central/content/events/src/nsEventListenerManager.cpp:993 #33 0x00007f02c74d4fba in nsEventListenerManager::HandleEvent (this=0x7f0294299680, aPresContext=0x7f02965dc000, aEvent=0x7fff49e6ea10, aDOMEvent=0x7fff49e6e8e0, aCurrentTarget=0x7f02956e4800, aEventStatus=0x7fff49e6e8e8, aPusher=0x7fff49e6e900) at /hack/mozilla-central/content/events/src/nsEventListenerManager.h:327 #34 0x00007f02c74d5583 in nsEventTargetChainItem::HandleEvent (this=0x7f02a7a61100, aVisitor=..., aMayHaveNewListenerManagers=false, aPusher=0x7fff49e6e900) at /hack/mozilla-central/content/events/src/nsEventDispatcher.cpp:202 #35 0x00007f02c74d5a47 in nsEventTargetChainItem::HandleEventTargetChain (this=0x7f02a3da3640, aVisitor=..., aCallback=0x0, aMayHaveNewListenerManagers=false, aPusher=0x7fff49e6e900) at /hack/mozilla-central/content/events/src/nsEventDispatcher.cpp:328 #36 0x00007f02c74d6bf8 in nsEventDispatcher::Dispatch (aTarget=0x7f02a7ca2c18, aPresContext=0x7f02965dc000, aEvent=0x7fff49e6ea10, aDOMEvent=0x0, aEventStatus=0x7fff49e6eab4, aCallback=0x0, aTargets=0x0) at /hack/mozilla-central/content/events/src/nsEventDispatcher.cpp:634 #37 0x00007f02c6f23817 in nsDocumentViewer::LoadComplete (this=0x7f029ed0b860, aStatus=NS_OK) at /hack/mozilla-central/layout/base/nsDocumentViewer.cpp:1036 #38 0x00007f02c7e758c8 in nsDocShell::EndPageLoad (this=0x7f02a7ca2400, aProgress=0x7f02a7ca2428, aChannel=0x7f02965d9858, aStatus=NS_OK) at /hack/mozilla-central/docshell/base/nsDocShell.cpp:6610 #39 0x00007f02c7e74be9 in nsDocShell::OnStateChange (this=0x7f02a7ca2400, aProgress=0x7f02a7ca2428, aRequest=0x7f02965d9858, aStateFlags=131088, aStatus=NS_OK) at /hack/mozilla-central/docshell/base/nsDocShell.cpp:6407 #40 0x00007f02c7ea705d in nsDocLoader::DoFireOnStateChange (this=0x7f02a7ca2400, aProgress=0x7f02a7ca2428, aRequest=0x7f02965d9858, aStateFlags=@0x7fff49e6f124: 131088, aStatus=NS_OK) at /hack/mozilla-central/uriloader/base/nsDocLoader.cpp:1323 #41 0x00007f02c7ea59ce in nsDocLoader::doStopDocumentLoad (this=0x7f02a7ca2400, request=0x7f02965d9858, aStatus=NS_OK) at /hack/mozilla-central/uriloader/base/nsDocLoader.cpp:865 #42 0x00007f02c7ea5527 in nsDocLoader::DocLoaderIsEmpty (this=0x7f02a7ca2400, aFlushLayout=true) at /hack/mozilla-central/uriloader/base/nsDocLoader.cpp:755 #43 0x00007f02c7ea5021 in nsDocLoader::OnStopRequest (this=0x7f02a7ca2400, aRequest=0x7f02b3093cc0, aCtxt=0x0, aStatus=NS_OK) at /hack/mozilla-central/uriloader/base/nsDocLoader.cpp:639 #44 0x00007f02c6b1668b in nsLoadGroup::RemoveRequest (this=0x7f02a7fc1b50, request=0x7f02b3093cc0, ctxt=0x0, aStatus=NS_OK) at /hack/mozilla-central/netwerk/base/src/nsLoadGroup.cpp:684 #45 0x00007f02c6e5d010 in imgRequestProxy::RemoveFromLoadGroup (this=0x7f02b3093cc0, releaseLoadGroup=true) at /hack/mozilla-central/image/src/imgRequestProxy.cpp:260 #46 0x00007f02c6e5e9cd in imgRequestProxy::OnStopRequest (this=0x7f02b3093cc0, lastPart=true) at /hack/mozilla-central/image/src/imgRequestProxy.cpp:829 #47 0x00007f02c6e64091 in imgStatusTracker::SyncNotifyState (proxies=..., hasImage=true, state=63, dirtyRect=..., hadLastPart=true) at /hack/mozilla-central/image/src/imgStatusTracker.cpp:518 #48 0x00007f02c6e648dc in imgStatusTracker::SyncNotify (this=0x7f02a39e8ce0, proxy=0x7f02b3093cc0) at /hack/mozilla-central/image/src/imgStatusTracker.cpp:628 #49 0x00007f02c6e5f1d5 in imgRequestProxy::SyncNotifyListener (this=0x7f02b3093cc0) at /hack/mozilla-central/image/src/imgRequestProxy.cpp:963 #50 0x00007f02c6e50cbc in imgCacheValidator::OnStartRequest (this=0x7f0294299600, aRequest=0x7f02942b6858, ctxt=0x0) at /hack/mozilla-central/image/src/imgLoader.cpp:2180 #51 0x00007f02c6c494a1 in mozilla::net::nsHttpChannel::CallOnStartRequest (this=0x7f02942b6800) at /hack/mozilla-central/netwerk/protocol/http/nsHttpChannel.cpp:970 #52 0x00007f02c6c59eae in mozilla::net::nsHttpChannel::ContinueOnStartRequest3 (this=0x7f02942b6800, result=NS_OK) at /hack/mozilla-central/netwerk/protocol/http/nsHttpChannel.cpp:4965 #53 0x00007f02c6c59e77 in mozilla::net::nsHttpChannel::ContinueOnStartRequest2 (this=0x7f02942b6800, result=NS_OK) at /hack/mozilla-central/netwerk/protocol/http/nsHttpChannel.cpp:4956 #54 0x00007f02c6c59d46 in mozilla::net::nsHttpChannel::OnStartRequest (this=0x7f02942b6800, request=0x7f02941fde00, ctxt=0x0) at /hack/mozilla-central/netwerk/protocol/http/nsHttpChannel.cpp:4929 #55 0x00007f02c6b09296 in nsInputStreamPump::OnStateStart (this=0x7f02941fde00) at /hack/mozilla-central/netwerk/base/src/nsInputStreamPump.cpp:418 #56 0x00007f02c6b09029 in nsInputStreamPump::OnInputStreamReady (this=0x7f02941fde00, stream=0x7f029532ab78) at /hack/mozilla-central/netwerk/base/src/nsInputStreamPump.cpp:369 #57 0x00007f02c899d123 in nsInputStreamReadyEvent::Run (this=0x7f02941f18c0) at /hack/mozilla-central/xpcom/io/nsStreamUtils.cpp:82 #58 0x00007f02c89c1db7 in nsThread::ProcessNextEvent (this=0x7f02cbc5e4f0, mayWait=true, result=0x7fff49e6fd5f) at /hack/mozilla-central/xpcom/threads/nsThread.cpp:627 #59 0x00007f02c894e7f3 in NS_ProcessNextEvent (thread=0x7f02cbc5e4f0, mayWait=true) at /hack/mozilla-central/obj-firefox-debug-dmd/xpcom/build/nsThreadUtils.cpp:238 #60 0x00007f02c83ed7d7 in mozilla::ipc::MessagePump::Run (this=0x7f02cbc5d440, aDelegate=0x7f02cbe99560) at /hack/mozilla-central/ipc/glue/MessagePump.cpp:117 #61 0x00007f02c8a1ed65 in MessageLoop::RunInternal (this=0x7f02cbe99560) at /hack/mozilla-central/ipc/chromium/src/base/message_loop.cc:219 #62 0x00007f02c8a1ecf6 in MessageLoop::RunHandler (this=0x7f02cbe99560) at /hack/mozilla-central/ipc/chromium/src/base/message_loop.cc:212 ---Type <return> to continue, or q <return> to quit---q Quit (gdb) frame 5 #5 0x00007f02c92ac93e in GrTBinHashKey<AtlasEntry, 24ul>::compare (this=0x7f02a16f9908, key=...) at /hack/mozilla-central/gfx/skia/src/gpu/GrBinHashKey.h:74 74 GrAssert(fIsValid && key.fIsValid); (gdb) p this $1 = (const GrTBinHashKey<AtlasEntry, 24ul> * const) 0x7f02a16f9908 (gdb) p *this $2 = {fHash = 1515870810, fData = 'Z' <repeats 24 times>, fIsValid = 90} (gdb) p/x 'Z' $3 = 0x5a (gdb) p/x 90 $4 = 0x5a The gdb prints at the end above ^ show that the |this| pointer points to already free'd memory.
Note: I'm using a debug build; that probably helps a lot with reproducibility by filling free'd memory with 0x5a bytes.
ah_crap_handler, indeed.
Severity: normal → critical
Crash Signature: [@ GrTBinHashKey<AtlasEntry, 24ul>::compare(GrTBinHashKey&)]
Keywords: crash
Reproduced in Valgrind! The first few reloads are fine. Then at about the 5th reload I get a bunch of 1-byte use-after-free's like this: ==17158== Invalid read of size 1 ==17158== at 0x402EE40: bcmp (mc_replace_strmem.c:930) ==17158== by 0x85E3A6A: GrTBinHashKey<AtlasEntry, 24ul>::EQ(AtlasEntry const&, GrTBinHashKey<AtlasEntry, 24ul> const&) (GrBinHashKey.h:80) ==17158== by 0x85E3E97: GrTHashTable<AtlasEntry, GrTBinHashKey<AtlasEntry, 24ul>, 8ul>::searchArray(GrTBinHashKey<AtlasEntry, 24ul> const&) const (GrTHashCache.h:96) ==17158== by 0x85E4158: GrTHashTable<AtlasEntry, GrTBinHashKey<AtlasEntry, 24ul>, 8ul>::insert(GrTBinHashKey<AtlasEntry, 24ul> const&, AtlasEntry*) (GrTHashCache.h:130) ==17158== by 0x85E4426: GrTextureStripAtlas::GetAtlas(GrTextureStripAtlas::Desc const&) (GrTextureStripAtlas.cpp:49) ==17158== by 0x8584CDF: GrGradientEffect::GrGradientEffect(GrContext*, SkGradientShaderBase const&, GrSamplerState*) (SkGradientShader.cpp:751) ==17158== by 0x85879A1: GrLinearGradient::GrLinearGradient(GrContext*, SkLinearGradient const&, GrSamplerState*) (SkLinearGradient.cpp:524) ==17158== by 0x8587A5E: SkLinearGradient::asNewCustomStage(GrContext*, GrSamplerState*) const (SkLinearGradient.cpp:584) ==17158== by 0x85DC1E7: (anonymous namespace)::skPaint2GrPaintShader(SkGpuDevice*, SkPaint const&, bool, SkGpuDevice::SkAutoCachedTexture*, GrPaint*) (SkGpuDevice.cpp:597) ==17158== by 0x85DCF7D: SkGpuDevice::drawRect(SkDraw const&, SkRect const&, SkPaint const&) (SkGpuDevice.cpp:782) ==17158== by 0x856D0B4: SkCanvas::drawRect(SkRect const&, SkPaint const&) (SkCanvas.cpp:1521) ==17158== by 0x8539BAD: mozilla::gfx::DrawTargetSkia::FillRect(mozilla::gfx::Rect const&, mozilla::gfx::Pattern const&, mozilla::gfx::DrawOptions const&) (DrawTargetSkia.cpp:367) ==17158== Address 0x2dd2bfd5 is 165 bytes inside a block of size 240 free'd ==17158== at 0x402C787: realloc (vg_replace_malloc.c:663) ==17158== by 0x858CA53: sk_realloc_throw(void*, unsigned long) (SkMemory_malloc.cpp:27) ==17158== by 0x85E4203: SkTDArray<AtlasEntry>::growBy(unsigned long) (SkTDArray.h:332) ==17158== by 0x85E4295: SkTDArray<AtlasEntry>::append(unsigned long, AtlasEntry const*) (SkTDArray.h:162) ==17158== by 0x85E43D6: GrTextureStripAtlas::GetAtlas(GrTextureStripAtlas::Desc const&) (GrTextureStripAtlas.cpp:46) ==17158== by 0x8584CDF: GrGradientEffect::GrGradientEffect(GrContext*, SkGradientShaderBase const&, GrSamplerState*) (SkGradientShader.cpp:751) ==17158== by 0x85879A1: GrLinearGradient::GrLinearGradient(GrContext*, SkLinearGradient const&, GrSamplerState*) (SkLinearGradient.cpp:524) ==17158== by 0x8587A5E: SkLinearGradient::asNewCustomStage(GrContext*, GrSamplerState*) const (SkLinearGradient.cpp:584) ==17158== by 0x85DC1E7: (anonymous namespace)::skPaint2GrPaintShader(SkGpuDevice*, SkPaint const&, bool, SkGpuDevice::SkAutoCachedTexture*, GrPaint*) (SkGpuDevice.cpp:597) ==17158== by 0x85DCF7D: SkGpuDevice::drawRect(SkDraw const&, SkRect const&, SkPaint const&) (SkGpuDevice.cpp:782) ==17158== by 0x856D0B4: SkCanvas::drawRect(SkRect const&, SkPaint const&) (SkCanvas.cpp:1521) ==17158== by 0x8539BAD: mozilla::gfx::DrawTargetSkia::FillRect(mozilla::gfx::Rect const&, mozilla::gfx::Pattern const&, mozilla::gfx::DrawOptions const&) (DrawTargetSkia.cpp:367) Then the next reload crashes with a failure of the assertion, the evaluation of which crashed in comment 0. /hack/mozilla-central/gfx/skia/src/gpu/GrBinHashKey.h(74) : fIsValid && key.fIsValid failed ==17158== Invalid write of size 4 ==17158== at 0x85E320F: GrTBinHashKey<AtlasEntry, 24ul>::compare(GrTBinHashKey<AtlasEntry, 24ul> const&) const (GrBinHashKey.h:74) ==17158== by 0x85E3E0D: GrTBinHashKey<AtlasEntry, 24ul>::LT(AtlasEntry const&, GrTBinHashKey<AtlasEntry, 24ul> const&) (GrBinHashKey.h:85) ==17158== by 0x85E3E71: GrTHashTable<AtlasEntry, GrTBinHashKey<AtlasEntry, 24ul>, 8ul>::searchArray(GrTBinHashKey<AtlasEntry, 24ul> const&) const (GrTHashCache.h:88) ==17158== by 0x85E3F99: GrTHashTable<AtlasEntry, GrTBinHashKey<AtlasEntry, 24ul>, 8ul>::find(GrTBinHashKey<AtlasEntry, 24ul> const&) const (GrTHashCache.h:117) ==17158== by 0x85E43BF: GrTextureStripAtlas::GetAtlas(GrTextureStripAtlas::Desc const&) (GrTextureStripAtlas.cpp:42) ==17158== by 0x8584CDF: GrGradientEffect::GrGradientEffect(GrContext*, SkGradientShaderBase const&, GrSamplerState*) (SkGradientShader.cpp:751) ==17158== by 0x85879A1: GrLinearGradient::GrLinearGradient(GrContext*, SkLinearGradient const&, GrSamplerState*) (SkLinearGradient.cpp:524) ==17158== by 0x8587A5E: SkLinearGradient::asNewCustomStage(GrContext*, GrSamplerState*) const (SkLinearGradient.cpp:584) ==17158== by 0x85DC1E7: (anonymous namespace)::skPaint2GrPaintShader(SkGpuDevice*, SkPaint const&, bool, SkGpuDevice::SkAutoCachedTexture*, GrPaint*) (SkGpuDevice.cpp:597) ==17158== by 0x85DCF7D: SkGpuDevice::drawRect(SkDraw const&, SkRect const&, SkPaint const&) (SkGpuDevice.cpp:782) ==17158== by 0x856D0B4: SkCanvas::drawRect(SkRect const&, SkPaint const&) (SkCanvas.cpp:1521) ==17158== by 0x8539BAD: mozilla::gfx::DrawTargetSkia::FillRect(mozilla::gfx::Rect const&, mozilla::gfx::Pattern const&, mozilla::gfx::DrawOptions const&) (DrawTargetSkia.cpp:367) ==17158== Address 0xffffffffbeefcafe is not stack'd, malloc'd or (recently) free'd ==17158==
So, this: ==17158== Address 0x2dd2bfd5 is 165 bytes inside a block of size 240 free'd ==17158== at 0x402C787: realloc (vg_replace_malloc.c:663) ==17158== by 0x858CA53: sk_realloc_throw(void*, unsigned long) (SkMemory_malloc.cpp:27) ==17158== by 0x85E4203: SkTDArray<AtlasEntry>::growBy(unsigned long) (SkTDArray.h:332) ==17158== by 0x85E4295: SkTDArray<AtlasEntry>::append(unsigned long, AtlasEntry const*) (SkTDArray.h:162) Suggests a bug in Skia where they grow an array by reallocating it and don't update existing pointers pointing to the old array, so they go dangling.
OK, so here is the faulty code in Skia, in GrTextureStripAtlas.cpp: GrTextureStripAtlas* GrTextureStripAtlas::GetAtlas(const GrTextureStripAtlas::Desc& desc) { static SkTDArray<AtlasEntry> gAtlasEntries; static GrTHashTable<AtlasEntry, AtlasHashKey, 8> gAtlasCache; AtlasHashKey key; key.setKeyData(desc.asKey()); AtlasEntry* entry = gAtlasCache.find(key); if (NULL != entry) { return entry->fAtlas; } else { entry = gAtlasEntries.push(); // <--- line 46 entry->fAtlas = SkNEW_ARGS(GrTextureStripAtlas, (desc)); entry->fKey = key; gAtlasCache.insert(key, entry); // <--- line 49 return entry->fAtlas; } } The Valgrind stacks in comment 3 show that the invalid read occurs at line 49, as the |entry| pointer is no longer valid; it became invalid as line 46 in a realloc(). So what's happening here --- skia's code here is nicely self-contained, kudos to that --- is that Skia wants to manage a bunch of AtlasEntry's in a hash table of raw pointers, |gAtlasCache|; the actual storage of the AtlasEntry's is in a separate array, |gAtlasEntries|. As we push a new entry into the |gAtlasEntries| array at line 46, the array storage of |gAtlasEntries| gets reallocated; that causes all the AtlasEntry* raw pointers in |gAtlasCache| to become bad dangling pointers.
This code looks completely different in trunk Skia, and the anti pattern here of using a separate array and hash-table-of-raw-pointers for managing the Entry's is no longer apparently present: http://code.google.com/p/skia/source/browse/trunk/src/gpu/effects/GrTextureStripAtlas.cpp#54 So this is fairly likely fixed in there... need to try with George's rebasing.
Yay, this is fixed by the rebasing to Skia r8495 from George's git tree. Is there a bug for that, that I can block this one on?
Should have flagged this sec-critical from the beginning --- this is a use-after-free with unclear implications. Brad: I claim that this is by itself reason enough to rebase Skia before turning on Skia/GL anywhere. In addition to being a security bug, this also prevents completing a canvas 2d tests run in Valgrind.
Group: core-security
Keywords: sec-critical
Keywords: csec-uaf
:bjacob, for easier reproduction try to use a ASan build next time, it will provide you a precise stack for alloc, free and re-use.
Assignee: nobody → gwright
It looks like this is disabled everywhere.
ASAN comes out clean for me with the latest Skia when this is enabled. At least on the OS X.
Marking works for me based on comment 7.
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → WORKSFORME
Group: core-security → core-security-release
Group: core-security-release
You need to log in before you can comment on or make changes to this bug.