Invalid write decoding crafted PNG crashes tab

RESOLVED FIXED in Firefox 67

Status

()

defect
P3
critical
RESOLVED FIXED
5 months ago
4 months ago

People

(Reporter: geeknik, Assigned: tnikkel)

Tracking

({csectype-nullptr, nightly-community, regression})

Trunk
mozilla67
x86_64
Linux
Points:
---
Bug Flags:
in-testsuite +

Firefox Tracking Flags

(firefox-esr60 wontfix, firefox66 wontfix, firefox67 fixed)

Details

Attachments

(2 attachments)

Posted file invalid_write.zip

This was discovered while fuzzing Nightly. The HTML is just 50 embeds of a 64x64 thumbnails of file:///tmp/webp/fuzz-1311.webp which is actually an 8-bit/color RGB, interlaced PNG. Loading the PNG alone doesn't crash the tab. Loading the html file does.

Leading up to the crash we see this:

Assertion failure: !mIsSome, at /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/Maybe.h:525
#01: ???[/home/geeknik/firefox/libxul.so +0x50d1a48]
#02: ???[/home/geeknik/firefox/libxul.so +0xbce7fbf]
#03: ???[/home/geeknik/firefox/libxul.so +0xbce550c]
#04: ???[/home/geeknik/firefox/libxul.so +0x50d892d]
#05: ???[/home/geeknik/firefox/libxul.so +0x511199d]
#06: ???[/home/geeknik/firefox/libxul.so +0x50d49d3]
#07: ???[/home/geeknik/firefox/libxul.so +0x4f82ea2]
#08: ???[/home/geeknik/firefox/libxul.so +0x4f948f2]
#09: ???[/home/geeknik/firefox/libxul.so +0x4fbda42]
#10: ???[/home/geeknik/firefox/libxul.so +0x211d1eb]
#11: ???[/home/geeknik/firefox/libxul.so +0x21232b2]
#12: ???[/home/geeknik/firefox/libxul.so +0x30be429]
#13: ???[/home/geeknik/firefox/libxul.so +0x3006940]
#14: ???[/home/geeknik/firefox/libxul.so +0x2117311]
#15: ???[/home/geeknik/firefox/libnspr4.so +0x81167]
#16: ???[/lib64/libpthread.so.0 +0x858e]
#17: clone[/lib64/libc.so.6 +0xfd6a3]
#18: ??? (???:???)
AddressSanitizer:DEADLYSIGNAL

Then we get the ASan dump:

=================================================================
==23953==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7f22135a4e6f bp 0x7f21f974cd70 sp 0x7f21f974cc80 T16)
==23953==The signal is caused by a WRITE memory access.
==23953==Hint: address points to the zero page.
#0 0x7f22135a4e6e in emplace<mozilla::image::Orientation &> /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/Maybe.h:525:3
#1 0x7f22135a4e6e in SetSize /builds/worker/workspace/build/src/image/ImageMetadata.h:59
#2 0x7f22135a4e6e in mozilla::image::Decoder::PostSize(int, int, mozilla::image::Orientation) /builds/worker/workspace/build/src/image/Decoder.cpp:418
#3 0x7f22136dba47 in mozilla::image::nsPNGDecoder::info_callback(png_struct_def*, png_info_def*) /builds/worker/workspace/build/src/image/decoders/nsPNGDecoder.cpp:545:12
#4 0x7f221a2f1fbe in MOZ_PNG_push_have_info /builds/worker/workspace/build/src/media/libpng/pngpread.c:1195:7
#5 0x7f221a2f1fbe in MOZ_PNG_push_read_chunk /builds/worker/workspace/build/src/media/libpng/pngpread.c:352
#6 0x7f221a2ef50b in MOZ_PNG_proc_some_data /builds/worker/workspace/build/src/media/libpng/pngpread.c:109:10
#7 0x7f221a2ef50b in MOZ_PNG_process_data /builds/worker/workspace/build/src/media/libpng/pngpread.c:46
#8 0x7f22136e292c in mozilla::image::nsPNGDecoder::ReadPNGData(char const*, unsigned long) /builds/worker/workspace/build/src/image/decoders/nsPNGDecoder.cpp:388:3
#9 0x7f221371b99c in operator() /builds/worker/workspace/build/src/image/decoders/nsPNGDecoder.cpp:359:34
#10 0x7f221371b99c in mozilla::Maybe<mozilla::Variant<mozilla::image::TerminalState, mozilla::image::Yield> > mozilla::image::StreamingLexer<mozilla::image::nsPNGDecoder::State, 16ul>::ContinueUnbufferedRead<mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8>(char const*, unsigned long, unsigned long, mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*)::$_8) /builds/worker/workspace/build/src/image/StreamingLexer.h:554
#11 0x7f22136de9d2 in UnbufferedRead<(lambda at /builds/worker/workspace/build/src/image/decoders/nsPNGDecoder.cpp:356:21)> /builds/worker/workspace/build/src/image/StreamingLexer.h:500:12
#12 0x7f22136de9d2 in Lex<(lambda at /builds/worker/workspace/build/src/image/decoders/nsPNGDecoder.cpp:356:21)> /builds/worker/workspace/build/src/image/StreamingLexer.h:468
#13 0x7f22136de9d2 in mozilla::image::nsPNGDecoder::DoDecode(mozilla::image::SourceBufferIterator&, mozilla::image::IResumable*) /builds/worker/workspace/build/src/image/decoders/nsPNGDecoder.cpp:355
#14 0x7f221358cea1 in mozilla::image::Decoder::Decode(mozilla::image::IResumable*) /builds/worker/workspace/build/src/image/Decoder.cpp:125:19
#15 0x7f221359e8f1 in mozilla::image::DecodedSurfaceProvider::Run() /builds/worker/workspace/build/src/image/DecodedSurfaceProvider.cpp:122:34
#16 0x7f22135c7a41 in mozilla::image::DecodePoolWorker::Run() /builds/worker/workspace/build/src/image/DecodePool.cpp:265:23
#17 0x7f22107271ea in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1162:14
#18 0x7f221072d2b1 in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:474:10
#19 0x7f22116c8428 in mozilla::ipc::MessagePumpForNonMainThreads::Run(base::MessagePump::Delegate*) /builds/worker/workspace/build/src/ipc/glue/MessagePump.cpp:303:20
#20 0x7f221161093f in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:315:10
#21 0x7f221161093f in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:308
#22 0x7f221161093f in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:290
#23 0x7f2210721310 in nsThread::ThreadFunc(void*) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:449:11
#24 0x7f2225ad4166 in _pt_root /builds/worker/workspace/build/src/nsprpub/pr/src/pthreads/ptthread.c:201:5
#25 0x7f2228cdb58d in start_thread (/lib64/libpthread.so.0+0x858d)
#26 0x7f22288c16a2 in __GI___clone (/lib64/libc.so.6+0xfd6a2)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV /builds/worker/workspace/build/src/obj-firefox/dist/include/mozilla/Maybe.h:525:3 in emplace<mozilla::image::Orientation &>
Thread T16 (ImgDecoder #1) created by T0 (file:// Content) here:
#0 0x55730c5a927d in __interceptor_pthread_create /builds/worker/workspace/moz-toolchain/src/llvm/projects/compiler-rt/lib/asan/asan_interceptors.cc:210:3
#1 0x7f2225ad0e95 in _PR_CreateThread /builds/worker/workspace/build/src/nsprpub/pr/src/pthreads/ptthread.c:433:14
#2 0x7f2225ad0a7e in PR_CreateThread /builds/worker/workspace/build/src/nsprpub/pr/src/pthreads/ptthread.c:518:12
#3 0x7f22107236f6 in nsThread::Init(nsTSubstring<char> const&) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:655:8
#4 0x7f221072c4a0 in nsThreadManager::NewNamedThread(nsTSubstring<char> const&, unsigned int, nsIThread**) /builds/worker/workspace/build/src/xpcom/threads/nsThreadManager.cpp:414:12
#5 0x7f221072ff69 in NS_NewNamedThread(nsTSubstring<char> const&, nsIThread**, nsIRunnable*, unsigned int) /builds/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:127:57
#6 0x7f221359a30a in mozilla::image::DecodePoolImpl::CreateThread() /builds/worker/workspace/build/src/image/DecodePool.cpp:297:17
#7 0x7f221359b5a7 in mozilla::image::DecodePoolImpl::DecodePoolImpl(unsigned char, unsigned char, mozilla::BaseTimeDuration<mozilla::TimeDurationValueCalculator>) /builds/worker/workspace/build/src/image/DecodePool.cpp:65:20
#8 0x7f221359af9b in mozilla::image::DecodePool::DecodePool() /builds/worker/workspace/build/src/image/DecodePool.cpp:373:15
#9 0x7f221359a7c0 in Singleton /builds/worker/workspace/build/src/image/DecodePool.cpp:321:22
#10 0x7f221359a7c0 in mozilla::image::DecodePool::Initialize() /builds/worker/workspace/build/src/image/DecodePool.cpp:315
#11 0x7f221369217e in mozilla::image::EnsureModuleInitialized() /builds/worker/workspace/build/src/image/build/nsImageModule.cpp:149:3
#12 0x7f22106dafc9 in nsComponentManagerImpl::KnownModule::Load() /builds/worker/workspace/build/src/xpcom/components/nsComponentManager.cpp:919:21
#13 0x7f22106e4c32 in nsFactoryEntry::GetFactory() /builds/worker/workspace/build/src/xpcom/components/nsComponentManager.cpp:1868:19
#14 0x7f22106deda9 in CreateInstance /builds/worker/workspace/build/src/xpcom/components/nsComponentManager.cpp:1900:34
#15 0x7f22106deda9 in CreateInstance /builds/worker/workspace/build/src/xpcom/components/nsComponentManager.cpp:217
#16 0x7f22106deda9 in nsComponentManagerImpl::GetServiceLocked((anonymous namespace)::MutexLock&, (anonymous namespace)::EntryWrapper&, nsID const&, void**) /builds/worker/workspace/build/src/xpcom/components/nsComponentManager.cpp:1396
#17 0x7f22106d42cc in nsComponentManagerImpl::GetServiceByContractID(char const*, nsID const&, void**) /builds/worker/workspace/build/src/xpcom/components/nsComponentManager.cpp:1583:10
#18 0x7f22106e74ec in CallGetService /builds/worker/workspace/build/src/xpcom/components/nsComponentManagerUtils.cpp:61:43
#19 0x7f22106e74ec in nsGetServiceByContractID::operator()(nsID const&, void**) const /builds/worker/workspace/build/src/xpcom/components/nsComponentManagerUtils.cpp:243
#20 0x7f2210571ad0 in nsCOMPtr_base::assign_from_gs_contractid(nsGetServiceByContractID, nsID const&) /builds/worker/workspace/build/src/xpcom/base/nsCOMPtr.cpp:82:7
#21 0x7f22132845a2 in nsCOMPtr /builds/worker/workspace/build/src/obj-firefox/dist/include/nsCOMPtr.h:607:5
#22 0x7f22132845a2 in gfxPlatform::Init() /builds/worker/workspace/build/src/gfx/thebes/gfxPlatform.cpp:1033
#23 0x7f22132867e9 in gfxPlatform::InitChild(mozilla::gfx::ContentDeviceData const&) /builds/worker/workspace/build/src/gfx/thebes/gfxPlatform.cpp:511:3
#24 0x7f2217e31b83 in InitGraphicsDeviceData /builds/worker/workspace/build/src/dom/ipc/ContentChild.cpp:1160:3
#25 0x7f2217e31b83 in mozilla::dom::ContentChild::RecvSetXPCOMProcessAttributes(mozilla::dom::XPCOMInitData const&, mozilla::dom::ipc::StructuredCloneData const&, nsTArray<LookAndFeelInt>&&, nsTArray<mozilla::dom::SystemFontListEntry>&&) /builds/worker/workspace/build/src/dom/ipc/ContentChild.cpp:599
#26 0x7f22118923a9 in mozilla::dom::PContentChild::OnMessageReceived(IPC::Message const&) /builds/worker/workspace/build/src/obj-firefox/ipc/ipdl/PContentChild.cpp:7847:56
#27 0x7f22116bf90e in mozilla::ipc::MessageChannel::DispatchAsyncMessage(IPC::Message const&) /builds/worker/workspace/build/src/ipc/glue/MessageChannel.cpp:2150:21
#28 0x7f22116bcbc3 in mozilla::ipc::MessageChannel::DispatchMessage(IPC::Message&&) /builds/worker/workspace/build/src/ipc/glue/MessageChannel.cpp:2077:9
#29 0x7f22116be41c in mozilla::ipc::MessageChannel::RunMessage(mozilla::ipc::MessageChannel::MessageTask&) /builds/worker/workspace/build/src/ipc/glue/MessageChannel.cpp:1936:3
#30 0x7f22116bea07 in mozilla::ipc::MessageChannel::MessageTask::Run() /builds/worker/workspace/build/src/ipc/glue/MessageChannel.cpp:1967:13
#31 0x7f22107271ea in nsThread::ProcessNextEvent(bool, bool*) /builds/worker/workspace/build/src/xpcom/threads/nsThread.cpp:1162:14
#32 0x7f221072d2b1 in NS_ProcessNextEvent(nsIThread*, bool) /builds/worker/workspace/build/src/xpcom/threads/nsThreadUtils.cpp:474:10
#33 0x7f22116c7420 in mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate*) /builds/worker/workspace/build/src/ipc/glue/MessagePump.cpp:88:21
#34 0x7f221161093f in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:315:10
#35 0x7f221161093f in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:308
#36 0x7f221161093f in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:290
#37 0x7f2218788d6a in nsBaseAppShell::Run() /builds/worker/workspace/build/src/widget/nsBaseAppShell.cpp:137:27
#38 0x7f221ca6bd0f in XRE_RunAppShell() /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:908:20
#39 0x7f221161093f in RunInternal /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:315:10
#40 0x7f221161093f in RunHandler /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:308
#41 0x7f221161093f in MessageLoop::Run() /builds/worker/workspace/build/src/ipc/chromium/src/base/message_loop.cc:290
#42 0x7f221ca6b66d in XRE_InitChildProcess(int, char**, XREChildData const*) /builds/worker/workspace/build/src/toolkit/xre/nsEmbedFunctions.cpp:746:34
#43 0x55730c5f33e4 in content_process_main /builds/worker/workspace/build/src/browser/app/../../ipc/contentproc/plugin-container.cpp:49:28
#44 0x55730c5f33e4 in main /builds/worker/workspace/build/src/browser/app/nsBrowserApp.cpp:265
#45 0x7f22287e8412 in __libc_start_main (/lib64/libc.so.6+0x24412)

==23953==ABORTING

This is reproducible on a Fedora 29 x64 machine using a GTX 970 and v415.27 Nvidia drivers. WebRender is enabled. The Firefox configuration for this run is prefs-webrender.js from the MozillaSecurity repo on GitHub, the only change being gfx.webrender.all set to true.

Flags: needinfo?(tnikkel)
Flags: needinfo?(aosmond)

I don't seem to hit any crash or assertion in a debug build. And I don't get a crash in an official nightly.

Just reproduced it again in ASan Nightly built from https://hg.mozilla.org/mozilla-central/rev/aa525133e148825b006d76a9d2ad33b5b56c5957 (Build ID 20190209214755). I tried to get rr to run but it core dumps and doesn't do anything useful.

The testcase file references a local path that doesn't exist on my computer, fixing that to just reference the image without a path fixes that and I can reproduce now.

Component: Graphics: Layers → ImageLib
Assignee: nobody → tnikkel
Priority: -- → P3

Timothy, this is a regression in 67. Will it have a fix by the 67 soft freeze (Mar 11)?

(In reply to Neha Kochar [:neha] from comment #5)

Timothy, this is a regression in 67. Will it have a fix by the 67 soft
freeze (Mar 11)?

I don't think it is a regression in 67, I haven't verified but the code involved hasn't changed since at least 64, and I would guess the bug exists long prior to that. I assume you arrived at that because the status-firefox67 affected flag is set? Is that flag only supposed to be used for regressions in that release? I thought it tracked any issue present in that version whether it was a regression or not.

libpng uses the first IDAT chunk it encounters as a signal that it has read all header chunks and to send the info callback.

The testcase png has an IDAT chunk, then a z chunk (not a known chunk type), and then another IDAT chunk.

libpng tracks if we are in an "after idat" state, and throws a benign error if it encounters another IDAT chunk in "after idat" mode, but it just continues normally, processing the idat chunk as if it were the first and therefore sends the info callback again. This seems silly.

Flags: needinfo?(tnikkel)
Flags: needinfo?(aosmond)
Pushed by tnikkel@gmail.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/355c9ff9b895
Guard against libpng calling the info callback more than once. r=aosmond
Status: NEW → RESOLVED
Closed: 4 months ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla67
Flags: in-testsuite+
You need to log in before you can comment on or make changes to this bug.