Bug 68220

Summary: REGRESSION: Reproducible crash below SlotVisitor::harvestWeakReferences using Domino's online ordering
Product: WebKit Reporter: Mark Rowe (bdash) <mrowe>
Component: JavaScriptCoreAssignee: Nobody <webkit-unassigned>
Status: RESOLVED FIXED    
Severity: Normal CC: fpizlo, ggaren, oliver, webkit-bug-importer
Priority: P1 Keywords: InRadar, Regression
Version: 528+ (Nightly build)   
Hardware: Mac (Intel)   
OS: OS X 10.7   
URL: http://express.dominos.com/order/olo.jsp
Attachments:
Description Flags
the patch oliver: review+

Description Mark Rowe (bdash) 2011-09-15 22:18:22 PDT
When using Domino's online ordering system it's relatively easy to hit the following crash:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x00007fff91b0d4aa in JSC::SlotVisitor::harvestWeakReferences (this=0x1029e7c28) at JavaScriptCore/heap/MarkStack.cpp:146
146	        current->visitWeakReferences(*this);
(gdb) bt
#0  0x00007fff91b0d4aa in JSC::SlotVisitor::harvestWeakReferences (this=0x1029e7c28) at JavaScriptCore/heap/MarkStack.cpp:146
#1  0x00007fff9199d0cc in JSC::Heap::markRoots (this=0x1029e78b0) at JavaScriptCore/heap/Heap.cpp:589
Previous frame inner to this frame (gdb could not unwind past this frame)

I can hit it relatively reliably in a production build of tip of tree by doing:
1) Visit <http://express.dominos.com/order/olo.jsp> and enter my address.
2) Click on Sides & Desserts.
3) Click on Build Your Order below New Boneless Chicken.
4) Picking any size, then click Next.
5) Wait for a few moments.

If you don't crash at this point, try editing the various text fields that are offered to you for a few moments.
Comment 1 Radar WebKit Bug Importer 2011-09-15 22:19:36 PDT
<rdar://problem/10135429>
Comment 2 Mark Rowe (bdash) 2011-09-15 23:41:26 PDT
In a debug build I hit an assertion failure when following the same steps:


Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000bbadbeef
0x000000010429797c in WTF::Vector<JSC::ValueProfile, 8ul>::at (this=0x7f80e834d138, i=0) at Vector.h:537
537	            ASSERT(i < size());
(gdb) bt 10
#0  0x000000010429797c in WTF::Vector<JSC::ValueProfile, 8ul>::at (this=0x7f80e834d138, i=0) at Vector.h:537
#1  0x00000001042978bd in WTF::Vector<JSC::ValueProfile, 8ul>::operator[] (this=0x7f80e834d138, i=0) at Vector.h:546
#2  0x000000010429785c in WTF::SegmentedVector<JSC::ValueProfile, 8ul>::at (this=0x7f80e834d130, index=0) at SegmentedVector.h:124
#3  0x000000010429780d in WTF::SegmentedVector<JSC::ValueProfile, 8ul>::operator[] (this=0x7f80e834d130, index=0) at SegmentedVector.h:130
#4  0x000000010428e673 in JSC::CodeBlock::valueProfile (this=0x7f80e834d000, index=0) at CodeBlock.h:455
#5  0x000000010428b928 in JSC::CodeBlock::visitWeakReferences (this=0x7f80e834d000) at JavaScriptCore/bytecode/CodeBlock.cpp:1608
#6  0x00000001044d4f91 in JSC::SlotVisitor::harvestWeakReferences (this=0x7f80e4060ce0) at JavaScriptCore/heap/MarkStack.cpp:146
#7  0x00000001044dbddc in JSC::Heap::harvestWeakReferences (this=0x7f80e40608d8) at JavaScriptCore/heap/Heap.cpp:518
#8  0x00000001044dc38b in JSC::Heap::markRoots (this=0x7f80e40608d8) at JavaScriptCore/heap/Heap.cpp:589
#9  0x00000001044db7d9 in JSC::Heap::collect (this=0x7f80e40608d8, sweepToggle=JSC::Heap::DoSweep) at JavaScriptCore/heap/Heap.cpp:674

A little poking around shows:
(gdb) up
#2  0x000000010429785c in WTF::SegmentedVector<JSC::ValueProfile, 8ul>::at (this=0x7f80e834d130, index=0) at SegmentedVector.h:124
124	                return m_inlineSegment[index];
(gdb) list
119	        bool isEmpty() const { return !size(); }
120	
121	        T& at(size_t index)
122	        {
123	            if (index < SegmentSize)
124	                return m_inlineSegment[index];
125	            return segmentFor(index)->at(subscriptFor(index));
126	        }
127	
128	        T& operator[](size_t index)
(gdb) print index
$7 = 0
(gdb) print m_inlineSegment.m_size
$8 = 0
(gdb) print m_segments.m_size
$9 = 0
(gdb) print m_size
$10 = 1

Something is shady about that SegmentedVector!
Comment 3 Filip Pizlo 2011-09-15 23:44:45 PDT

(In reply to comment #2)
> In a debug build I hit an assertion failure when following the same steps:

Fascinating.  Thanks for poking around.  This helps a lot!
Comment 4 Mark Rowe (bdash) 2011-09-16 00:22:17 PDT
Using MallocStackLogging=YES on WebProcess shows that the memory pointed to by “current” at the time of the crash formerly pointed to a FunctionCodeBlock but is now deallocated.  That explains the assertion I hit: in that case the deallocated memory was valid enough that it could be interpreted as a CodeBlock. Most of the time it can’t be though.
Comment 5 Mark Rowe (bdash) 2011-09-16 00:23:37 PDT
I’m not sure how useful it is, but the stack trace for the allocation / deallocations of the FunctionCodeBlock are as follows:


ALLOC 0x7ffe92f50e00-0x7ffe92f5159f [size=1952]: thread_7fff788c2960 |start | main | WebKitMain | _ZL10WebKitMainRKN6WebKit11CommandLineE | WebKit::WebProcessMain(WebKit::CommandLine const&) | RunLoop::run() | -[NSApplication run] | -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] | _DPSNextEvent | BlockUntilNextEventMatchingListInMode | ReceiveNextEventCommon | RunCurrentEventLoopInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoSources0 | __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ | RunLoop::performWork(void*) | RunLoop::performWork() | MemberFunctionWorkItem0<CoreIPC::Connection>::execute() | CoreIPC::Connection::dispatchMessages() | CoreIPC::Connection::dispatchMessage(CoreIPC::Connection::Message<CoreIPC::ArgumentDecoder>&) | WebKit::WebProcess::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*) | WebKit::WebPage::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*) | WebKit::WebPage::didReceiveWebPageMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*) | void CoreIPC::handleMessage<Messages::WebPage::MouseEvent, WebKit::WebPage, void (WebKit::WebPage::*)(WebKit::WebMouseEvent const&)>(CoreIPC::ArgumentDecoder*, WebKit::WebPage*, void (WebKit::WebPage::*)(WebKit::WebMouseEvent const&)) | void CoreIPC::callMemberFunction<WebKit::WebPage, void (WebKit::WebPage::*)(WebKit::WebMouseEvent const&), WebKit::WebMouseEvent>(CoreIPC::Arguments1<WebKit::WebMouseEvent> const&, WebKit::WebPage*, void (WebKit::WebPage::*)(WebKit::WebMouseEvent const&)) | WebKit::WebPage::mouseEvent(WebKit::WebMouseEvent const&) | _ZN6WebKitL16handleMouseEventERKNS_13WebMouseEventEPN7WebCore4PageE | WebCore::EventHandler::handleMouseReleaseEvent(WebCore::PlatformMouseEvent const&) | WebCore::EventHandler::dispatchMouseEvent(WTF::AtomicString const&, WebCore::Node*, bool, int, WebCore::PlatformMouseEvent const&, bool) | WebCore::Node::dispatchMouseEvent(WebCore::PlatformMouseEvent const&, WTF::AtomicString const&, int, WebCore::Node*) | WebCore::EventDispatcher::dispatchEvent(WebCore::Node*, WTF::PassRefPtr<WebCore::EventDispatchMediator>) | WebCore::MouseEventDispatchMediator::dispatchEvent(WebCore::EventDispatcher*) const | WebCore::EventDispatcher::dispatchEvent(WTF::PassRefPtr<WebCore::Event>) | WebCore::Node::handleLocalEvents(WebCore::Event*) | WebCore::EventTarget::fireEventListeners(WebCore::Event*) | WebCore::EventTarget::fireEventListeners(WebCore::Event*, WebCore::EventTargetData*, WTF::Vector<WebCore::RegisteredEventListener, 1ul>&) | WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) | WebCore::JSMainThreadExecState::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) | JSC::call(JSC::ExecState*, JSC::JSValue, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) | JSC::Interpreter::executeCall(JSC::ExecState*, JSC::JSObject*, JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) | JSC::FunctionExecutable::compileForCall(JSC::ExecState*, JSC::ScopeChainNode*, JSC::ExecState*) | JSC::FunctionExecutable::compileForCallInternal(JSC::ExecState*, JSC::ScopeChainNode*, JSC::ExecState*, JSC::JITCode::JITType) | JSC::CodeBlock::operator new(unsigned long) | WTF::fastMalloc(unsigned long) | malloc | malloc_zone_malloc 
----
FREE  0x7ffe92f50e00-0x7ffe92f5159f [size=1952]: thread_7fff788c2960 |start | main | WebKitMain | _ZL10WebKitMainRKN6WebKit11CommandLineE | WebKit::WebProcessMain(WebKit::CommandLine const&) | RunLoop::run() | -[NSApplication run] | -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] | _DPSNextEvent | BlockUntilNextEventMatchingListInMode | ReceiveNextEventCommon | RunCurrentEventLoopInMode | CFRunLoopRunSpecific | __CFRunLoopRun | __CFRunLoopDoTimer | __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ | JSC::DefaultGCActivityCallbackPlatformData::trigger(__CFRunLoopTimer*, void*) | JSC::Heap::collectAllGarbage() | JSC::JSGlobalData::recompileAllJSFunctions() | (anonymous namespace)::Recompiler::ReturnType JSC::Heap::forEachCell<(anonymous namespace)::Recompiler>() | (anonymous namespace)::Recompiler::ReturnType JSC::Heap::forEachCell<(anonymous namespace)::Recompiler>((anonymous namespace)::Recompiler&) | void JSC::MarkedBlock::forEachCell<(anonymous namespace)::Recompiler>((anonymous namespace)::Recompiler&) | (anonymous namespace)::Recompiler::operator()(JSC::JSCell*) | JSC::FunctionExecutable::discardCode() | JSC::FunctionExecutable::clearCode() | WTF::OwnPtr<JSC::FunctionCodeBlock>::clear() | void WTF::deleteOwnedPtr<JSC::FunctionCodeBlock>(JSC::FunctionCodeBlock*) | JSC::FunctionCodeBlock::~FunctionCodeBlock() | JSC::CodeBlock::operator delete(void*) | WTF::fastFree(void*) | free
Comment 6 Filip Pizlo 2011-09-16 01:20:56 PDT
Created attachment 107621 [details]
the patch
Comment 7 Filip Pizlo 2011-09-16 11:42:50 PDT
Landed in r95308.