RESOLVED FIXED 19183
REGRESSION (r33979): Crash in DebuggerCallFrame::functionName when clicking button in returnEvent-crash.html
https://bugs.webkit.org/show_bug.cgi?id=19183
Summary REGRESSION (r33979): Crash in DebuggerCallFrame::functionName when clicking b...
Adam Roben (:aroben)
Reported 2008-05-22 01:23:54 PDT
I'm seeing a crash in DebuggerCallFrame::functionName when running WebCore/manual-tests/inspector/returnEvent-crash.html Steps to repro: 0. Run a debug Windows build or a debug Mac build with MallocScribble enabled 1. Set Safari to open new windows with empty pages 2. Open a new window 3. Open the Inspector 4. Go to WebCore/manual-tests/inspector/returnEvent-crash.html 5. Attach the Inspector's debugger 6. Set a breakpoint on line 9 of returnEvent-crash.html 7. Click the button that says "click me" in returnEvent-crash.html > WebKit_debug.dll!KJS::DebuggerCallFrame::functionName() Line 49 + 0x3 bytes C++ WebKit_debug.dll!WebCore::JavaScriptCallFrame::functionName() Line 67 + 0xb bytes C++ WebKit_debug.dll!WebCore::JSJavaScriptCallFrame::getValueProperty(KJS::ExecState * exec=0x06a7e820, int token=5) Line 115 + 0x10 bytes C++ WebKit_debug.dll!KJS::staticValueGetter<WebCore::JSJavaScriptCallFrame>(KJS::ExecState * exec=0x06a7e820, KJS::JSObject * __formal=0x07fa7480, KJS::JSObject * __formal=0x07fa7480, const KJS::PropertySlot & slot={...}) Line 110 C++ WebKit_debug.dll!KJS::PropertySlot::getValue(KJS::ExecState * exec=0x06a7e820, KJS::JSObject * originalObject=0x07fa7480, const KJS::Identifier & propertyName={...}) Line 49 + 0x19 bytes C++ WebKit_debug.dll!WebCore::JSQuarantinedObjectWrapper::getOwnPropertySlot(KJS::ExecState * exec=0x0012e804, const KJS::Identifier & identifier={...}, KJS::PropertySlot & slot={...}) Line 113 + 0x1c bytes C++ WebKit_debug.dll!KJS::JSObject::getPropertySlot(KJS::ExecState * exec=0x0012e804, const KJS::Identifier & propertyName={...}, KJS::PropertySlot & slot={...}) Line 553 + 0x1b bytes C++ WebKit_debug.dll!KJS::JSObject::get(KJS::ExecState * exec=0x0012e804, const KJS::Identifier & propertyName={...}) Line 532 + 0x14 bytes C++ WebKit_debug.dll!KJS::Machine::privateExecute(KJS::Machine::ExecutionFlag flag=Normal, KJS::ExecState * exec=0x0012e804, KJS::RegisterFile * registerFile=0x075fffe8, KJS::Register * r=0x07608208, KJS::ScopeChainNode * scopeChain=0x067be9f8, KJS::CodeBlock * codeBlock=0x06d60a60, KJS::JSValue * * exception=0x0012e8a0) Line 1544 + 0x16 bytes C++ WebKit_debug.dll!KJS::Machine::execute(KJS::FunctionBodyNode * functionBodyNode=0x06a12738, KJS::ExecState * exec=0x067bea88, KJS::FunctionImp * function=0x046533c0, KJS::JSObject * thisObj=0x046526e0, const KJS::List & args={...}, KJS::RegisterFileStack * registerFileStack=0x067be830, KJS::ScopeChainNode * scopeChain=0x06a123e8, KJS::JSValue * * exception=0x0012e8a0) Line 709 + 0x22 bytes C++ WebKit_debug.dll!KJS::FunctionImp::callAsFunction(KJS::ExecState * exec=0x067bea88, KJS::JSObject * thisObj=0x046526e0, const KJS::List & args={...}) Line 90 + 0x3c bytes C++ WebKit_debug.dll!KJS::JSObject::call(KJS::ExecState * exec=0x067bea88, KJS::JSObject * thisObj=0x046526e0, const KJS::List & args={...}) Line 99 + 0x1b bytes C++ WebKit_debug.dll!JSObjectCallAsFunction(const OpaqueJSContext * ctx=0x067bea88, OpaqueJSValue * object=0x046533c0, OpaqueJSValue * thisObject=0x046526e0, unsigned int argumentCount=0, const OpaqueJSValue * const * arguments=0x00000000, const OpaqueJSValue * * exception=0x0012e9a4) Line 288 + 0x14 bytes C++ WebKit_debug.dll!WebCore::InspectorController::callFunction(const OpaqueJSContext * context=0x067bea88, OpaqueJSValue * thisObject=0x046526e0, const char * functionName=0x01841e44, unsigned int argumentCount=0, const OpaqueJSValue * const * arguments=0x00000000, const OpaqueJSValue * & exception=0x00000000) Line 143 + 0x1d bytes C++ WebKit_debug.dll!WebCore::InspectorController::didPause() Line 2391 C++ WebKit_debug.dll!WebCore::dispatchFunctionToListeners(const WTF::HashSet<WebCore::JavaScriptDebugListener *,WTF::PtrHash<WebCore::JavaScriptDebugListener *>,WTF::HashTraits<WebCore::JavaScriptDebugListener *> > & listeners={...}, void (void)* callback=0x00f9c7d0) Line 306 + 0x13 bytes C++ WebKit_debug.dll!WebCore::JavaScriptDebugServer::dispatchFunctionToListeners(void (void)* callback=0x00f9c7d0, WebCore::Page * page=0x046d3378) Line 321 + 0xd bytes C++ WebKit_debug.dll!WebCore::JavaScriptDebugServer::pauseIfNeeded(WebCore::Page * page=0x046d3378) Line 406 C++ WebKit_debug.dll!WebCore::JavaScriptDebugServer::atStatement(const KJS::DebuggerCallFrame & debuggerCallFrame={...}, int sourceID=41, int lineNumber=9) Line 435 C++ WebKit_debug.dll!KJS::Machine::debug(KJS::ExecState * exec=0x0012f0b8, const KJS::Instruction * vPC=0x07607098, const KJS::CodeBlock * codeBlock=0x076065a8, KJS::ScopeChainNode * scopeChain=0x06ae3cb0, KJS::Register * * registerBase=0x07605808, KJS::Register * r=0x06aea738) Line 812 + 0x22 bytes C++ WebKit_debug.dll!KJS::Machine::privateExecute(KJS::Machine::ExecutionFlag flag=Normal, KJS::ExecState * exec=0x0012f0b8, KJS::RegisterFile * registerFile=0x076057f8, KJS::Register * r=0x06aea738, KJS::ScopeChainNode * scopeChain=0x06ae3cb0, KJS::CodeBlock * codeBlock=0x076065a8, KJS::JSValue * * exception=0x0012f154) Line 2233 C++ WebKit_debug.dll!KJS::Machine::execute(KJS::FunctionBodyNode * functionBodyNode=0x07605e40, KJS::ExecState * exec=0x06a7e820, KJS::FunctionImp * function=0x05650620, KJS::JSObject * thisObj=0x07fb4160, const KJS::List & args={...}, KJS::RegisterFileStack * registerFileStack=0x06c0e5c0, KJS::ScopeChainNode * scopeChain=0x076058a0, KJS::JSValue * * exception=0x0012f154) Line 709 + 0x22 bytes C++ WebKit_debug.dll!KJS::FunctionImp::callAsFunction(KJS::ExecState * exec=0x06a7e820, KJS::JSObject * thisObj=0x07fb4160, const KJS::List & args={...}) Line 90 + 0x3c bytes C++ WebKit_debug.dll!KJS::JSObject::call(KJS::ExecState * exec=0x06a7e820, KJS::JSObject * thisObj=0x07fb4160, const KJS::List & args={...}) Line 99 + 0x1b bytes C++ WebKit_debug.dll!WebCore::JSAbstractEventListener::handleEvent(WebCore::Event * ele=0x07367150, bool isWindowEvent=false) Line 100 + 0x14 bytes C++ WebKit_debug.dll!WebCore::EventTarget::handleLocalEvents(WebCore::EventTargetNode * referenceNode=0x072fc8c8, WebCore::Event * evt=0x07367150, bool useCapture=false) Line 314 + 0x2e bytes C++ WebKit_debug.dll!WebCore::EventTargetNode::handleLocalEvents(WebCore::Event * evt=0x07367150, bool useCapture=false) Line 106 C++ WebKit_debug.dll!WebCore::EventTarget::dispatchGenericEvent(WebCore::EventTargetNode * referenceNode=0x072fc8c8, WTF::PassRefPtr<WebCore::Event> e={...}, int & __formal=0, bool tempEvent=true) Line 212 + 0x1d bytes C++ WebKit_debug.dll!WebCore::EventTargetNode::dispatchEvent(WTF::PassRefPtr<WebCore::Event> e={...}, int & ec=0, bool tempEvent=true) Line 121 + 0x1e bytes C++ WebKit_debug.dll!WebCore::EventTargetNode::dispatchMouseEvent(const WebCore::AtomicString & eventType={...}, int button=0, int detail=1, int pageX=41, int pageY=93, int screenX=545, int screenY=190, bool ctrlKey=false, bool altKey=false, bool shiftKey=false, bool metaKey=false, bool isSimulated=false, WebCore::Node * relatedTargetArg=0x00000000, WTF::PassRefPtr<WebCore::Event> underlyingEvent={...}) Line 297 C++ WebKit_debug.dll!WebCore::EventTargetNode::dispatchMouseEvent(const WebCore::PlatformMouseEvent & event={...}, const WebCore::AtomicString & eventType={...}, int detail=1, WebCore::Node * relatedTarget=0x00000000) Line 215 C++ WebKit_debug.dll!WebCore::EventHandler::dispatchMouseEvent(const WebCore::AtomicString & eventType={...}, WebCore::Node * targetNode=0x072fc8c8, bool cancelable=true, int clickCount=1, const WebCore::PlatformMouseEvent & mouseEvent={...}, bool setUnder=true) Line 1279 + 0x29 bytes C++ WebKit_debug.dll!WebCore::EventHandler::handleMouseReleaseEvent(const WebCore::PlatformMouseEvent & mouseEvent={...}) Line 1101 + 0x28 bytes C++ WebKit_debug.dll!WebView::handleMouseEvent(unsigned int message=514, unsigned int wParam=0, long lParam=6094889) Line 1244 C++ WebKit_debug.dll!WebViewWndProc(HWND__ * hWnd=0x002b06d0, unsigned int message=514, unsigned int wParam=0, long lParam=6094889) Line 1673 + 0x14 bytes C++
Attachments
Mark Rowe (bdash)
Comment 1 2008-05-22 01:25:15 PDT
Timothy Hatcher
Comment 2 2008-05-24 21:49:17 PDT
I have not been able to reproduce this.
Adam Roben (:aroben)
Comment 3 2008-05-27 07:54:35 PDT
Geoff said he could reproduce with MallocScribble enabled. It's quite easy to reproduce with a Windows debug build.
Adam Roben (:aroben)
Comment 4 2008-05-27 09:22:32 PDT
I can still reproduce this in ToT today. I will try to debug further.
Adam Roben (:aroben)
Comment 5 2008-05-27 09:49:04 PDT
m_codeBlock->numLocals is returning 0xcdcdcdcc, which in a debug Windows build means this is free()'d memory.
Adam Roben (:aroben)
Comment 6 2008-05-27 10:28:32 PDT
(In reply to comment #5) > m_codeBlock->numLocals is returning 0xcdcdcdcc, which in a debug Windows build > means this is free()'d memory. Sorry, 0xcdcdcdcd means uninitialized memory, not free()d memory.
Adam Roben (:aroben)
Comment 7 2008-05-27 10:36:29 PDT
It looks as if the JavaScriptCallFrame in question is the one created when the contents of the <script> tag is parsed. I'm not sure why that call frame is being used here. Instead we should be using the call frames relevant to the script execution.
Adam Roben (:aroben)
Comment 8 2008-05-27 10:46:43 PDT
OK, I think I know what's going on here. The code block when parsing the contents of the <script> element is: [ 0] new_func lr8, f0 [ 3] new_func lr9, f1 [ 6] load tr0, undefined(@k0) [ 9] debug willExecuteStatement, -1, -1 [ 13] debug willExecuteStatement, -1, -1 [ 17] end tr0 Notice that there are two willExecuteStatement calls but no {didEnter,willLeave}CallFrame calls. At the end of this code block, JavaScriptDebugServer::m_currentCallFrame will hold the call frame from the last willExecuteStatement call. Call this call frame "A". The code block when executing the onclick handler of the "click me" button is: [ 0] debug didEnterCallFrame, 16, 17 [ 4] debug willExecuteStatement, 17, 17 [ 8] resolve_func tr0, tr1, test(@id0) [ 12] call tr0, tr1, tr0, 12, 1 [ 18] load tr0, undefined(@k0) [ 21] debug willLeaveCallFrame, 16, 17 [ 25] ret tr0 The first call to didEnterCallFrame will cause a new JavaScriptCallFrame to be created. Call this call frame "B". B's "caller" will be set to A. But by this time the CodeBlock that A holds might already have been deleted. The crash occurs when the Inspector is building up the call stack to display in the debugger. It crawls up from B to A via JavaScriptCallFrame::caller, and then calls DebuggerCallFrame::functionName, which dereferences the deleted CodeBlock.
Geoffrey Garen
Comment 9 2008-05-28 13:48:11 PDT
Committed revision 34182.
Note You need to log in before you can comment on or make changes to this bug.