Closed Bug 232095 Opened 21 years ago Closed 21 years ago

[FIX]JS syntax error in XBL binding used twice crashes Mozilla


(Core :: XBL, defect, P1)






(Reporter: WeirdAl, Assigned: bzbarsky)




(Keywords: crash, testcase)


(3 files)

Crash testcase coming up.  Stack appears to be corrupted...  Just in case it's not:

#0  0x405a46f6 in nanosleep () from /lib/
#1  0x0000001c in ?? ()
#2  0x080721be in ah_crap_handler(int) (signum=11) at nsSigHandlers.cpp:135
#3  0x419338a9 in nsProfileLock::FatalSignalHandler(int) (signo=11)
    at nsProfileLock.cpp:209
#4  0x4012bc2d in __pthread_sighandler () from /lib/
#5  0x4051fd58 in __libc_sigaction () from /lib/
#6  0x41473a6a in nsXBLProtoImplMethod::InstallMember(nsIScriptContext*,
nsIContent*, void*, void*, nsCString const&) (this=0x87cf930, aContext=0x869efb0,
    aBoundElement=0x87a67e8, aScriptObject=0x83e0cf0,
    aTargetClassObject=0x83e0d00, aClassStr=@0x87cf5b0)
    at nsXBLProtoImplMethod.cpp:183
#7  0x414749b6 in nsXBLProtoImpl::InstallImplementation(nsXBLPrototypeBinding*,
nsIContent*) (this=0x87cf5b0, aBinding=0x876c578, aBoundElement=0x87a67e8)
    at nsXBLProtoImpl.cpp:84
#8  0x41465976 in nsXBLPrototypeBinding::InstallImplementation(nsIContent*) (
    this=0x876c578, aBoundElement=0x87a67e8) at nsXBLPrototypeBinding.cpp:440
#9  0x414614b2 in nsXBLBinding::InstallImplementation() (this=0x87cf858)
    at nsXBLBinding.cpp:814
#10 0x4147f22a in nsXBLService::LoadBindings(nsIContent*, nsIURI*, int,
nsIXBLBinding**, int*) (this=0x82042e8, aContent=0x87a67e8, aURL=0x87ae308,
    aAugmentFlag=0, aBinding=0xbfffe680, aResolveStyle=0xbfffe678)
    at nsXBLService.cpp:632
#11 0x411172d7 in nsCSSFrameConstructor::ConstructFrameInternal(nsIPresShell*,
n---Type <return> to continue, or q <return> to quit---
sIPresContext*, nsFrameConstructorState&, nsIContent*, nsIFrame*, nsIAtom*, int,
nsStyleContext*, nsFrameItems&, int) (this=0x83daba0, aPresShell=0x86eade8,
    aPresContext=0x87562f8, aState=@0xbfffe820, aContent=0x87a67e8,
    aParentFrame=0x8782e44, aTag=0x87d3210, aNameSpaceID=9,
    aStyleContext=0x8783688, aFrameItems=@0xbfffe800, aXBLBaseTag=0)
    at nsCSSFrameConstructor.cpp:7025
#12 0x41117183 in nsCSSFrameConstructor::ConstructFrame(nsIPresShell*,
nsIPresContext*, nsFrameConstructorState&, nsIContent*, nsIFrame*, nsFrameItems&) (
    this=0x83daba0, aPresShell=0x86eade8, aPresContext=0x87562f8,
    aState=@0xbfffe820, aContent=0x87a67e8, aParentFrame=0x8782e44,
    aFrameItems=@0xbfffe800) at nsCSSFrameConstructor.cpp:6981
#13 0x4111c074 in nsCSSFrameConstructor::ContentInserted(nsIPresContext*,
nsIContent*, nsIFrame*, nsIContent*, int, nsILayoutHistoryState*, int) (
    this=0x83daba0, aPresContext=0x87562f8, aContainer=0x87ac8d0,
    aContainerFrame=0x0, aChild=0x87a67e8, aIndexInContainer=3,
    aFrameState=0x0, aInContentReplaced=0) at nsCSSFrameConstructor.cpp:8899
#14 0x4109f866 in PresShell::ContentInserted(nsIDocument*, nsIContent*,
nsIContent*, int) (this=0x86eade8, aDocument=0x87d1360, aContainer=0x87ac8d0,
    aChild=0x87a67e8, aIndexInContainer=3) at nsPresShell.cpp:5266
#15 0x41482b2a in nsXBLBindingRequest::DocumentLoaded(nsIDocument*) (
    this=0x8204348, aBindingDoc=0x87dc968) at nsXBLService.cpp:178
#16 0x4147dd9f in nsXBLStreamListener::Load(nsIDOMEvent*) (this=0x87d0f20,
    aEvent=0x87bedb0) at nsXBLService.cpp:429
#17 0x412d7597 in DispatchToInterface (aEvent=0x87bedb0, aListener=0x87d0f24,
---Type <return> to continue, or q <return> to quit---
    aMethod={__pfn = 0x11, __delta = 0}, aIID=@0x415b7c3c,
    aHasInterface=0xbfffeb28) at nsEventListenerManager.cpp:128
#18 0x412db353 in nsEventListenerManager::HandleEvent(nsIPresContext*, nsEvent*,
nsIDOMEvent**, nsIDOMEventTarget*, unsigned, nsEventStatus*) (this=0x87d0f78,
    aPresContext=0x0, aEvent=0xbfffec50, aDOMEvent=0xbfffebc4,
    aCurrentTarget=0x87dca00, aFlags=7, aEventStatus=0xbfffec8c)
    at nsEventListenerManager.cpp:1504
#19 0x41220840 in nsDocument::HandleDOMEvent(nsIPresContext*, nsEvent*,
nsIDOMEvent**, unsigned, nsEventStatus*) (this=0x87dc968, aPresContext=0x0,
    aEvent=0xbfffec50, aDOMEvent=0xbfffebc4, aFlags=7, aEventStatus=0xbfffec8c)
    at nsDocument.cpp:3632
#20 0x4145820f in nsXMLDocument::EndLoad() (this=0x87dc968)
    at nsXMLDocument.cpp:667
#21 0x4144d29e in nsXMLContentSink::DidBuildModel() (this=0x87e9d38)
    at nsXMLContentSink.cpp:290
#22 0x419d2124 in nsExpatDriver::DidBuildModel(unsigned, int, nsIParser*,
nsIContentSink*) (this=0x87c9478, anErrorCode=0, aNotifySink=1, aParser=0x87d0dd0,
    aSink=0x87e9d88) at nsExpatDriver.cpp:1042
#23 0x419f0212 in nsParser::DidBuildModel(unsigned) (this=0x87d0dd0,
    anErrorCode=0) at nsParser.cpp:1245
#24 0x419f12e3 in nsParser::ResumeParse(int, int, int) (this=0x87d0dd0,
    allowIteration=1, aIsFinalChunk=1, aCanInterrupt=1) at nsParser.cpp:1806
#25 0x419f304b in nsParser::OnStopRequest(nsIRequest*, nsISupports*, unsigned)
    (this=0x87d0dd0, request=0x87086b8, aContext=0x0, status=0)
---Type <return> to continue, or q <return> to quit---
    at nsParser.cpp:2472
#26 0x4147d750 in nsXBLStreamListener::OnStopRequest(nsIRequest*, nsISupports*,
unsigned) (this=0x87d0f20, request=0x87086b8, aCtxt=0x0, aStatus=0)
    at nsXBLService.cpp:322
#27 0x40c16ae1 in nsFileChannel::OnStopRequest(nsIRequest*, nsISupports*,
unsigned) (this=0x87086b8, req=0x87d10e0, ctx=0x0, status=0) at
#28 0x40b81318 in nsInputStreamPump::OnStateStop() (this=0x87d10e0)
    at nsInputStreamPump.cpp:498
#29 0x40b80cdb in nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream*) (
    this=0x87d10e0, stream=0x87d1234) at nsInputStreamPump.cpp:339
#30 0x407f49d1 in nsInputStreamReadyEvent::EventHandler(PLEvent*) (
    plevent=0x8758ce4) at nsStreamUtils.cpp:118
#31 0x4081a2f4 in PL_HandleEvent (self=0x8758ce4) at plevent.c:671
#32 0x4081a195 in PL_ProcessPendingEvents (self=0x813e118) at plevent.c:606
#33 0x4081d4ca in nsEventQueueImpl::ProcessPendingEvents() (this=0x813df08)
    at nsEventQueue.cpp:391
#34 0x41888d74 in event_processor_callback (data=0x813df08, source=4,
    condition=GDK_INPUT_READ) at nsAppShell.cpp:186
#35 0x418886dd in our_gdk_io_invoke (source=0x8262f90, condition=G_IO_IN,
    data=0x8286080) at nsAppShell.cpp:71
#36 0x4030d7d6 in g_io_channel_unix_get_fd () from /usr/lib/
#37 0x403103ee in g_idle_remove_by_data () from /usr/lib/
#38 0x40310199 in g_idle_remove_by_data () from /usr/lib/
#39 0x4030f174 in g_main_run () from /usr/lib/

On frame 6:
#6  0x41473a6a in nsXBLProtoImplMethod::InstallMember(nsIScriptContext*,
nsIContent*, void*, void*, nsCString const&) (this=0x87cf930, aContext=0x869efb0,
    aBoundElement=0x87a67e8, aScriptObject=0x83e0cf0,
    aTargetClassObject=0x83e0d00, aClassStr=@0x87cf5b0)
    at nsXBLProtoImplMethod.cpp:183
183         JSObject * method = ::JS_CloneFunctionObject(cx, mJSMethodObject,
(gdb) print mJSMethodObject
No symbol "mJSMethodObject" in current context.

Per line 181 of nsXBLProtoImplMethod.cpp, you would think this isn't even called...

Also reference bug 231396, which has a JS syntax error unreported by XBL (but
does not crash).  Crash testcase coming up.
Attached file crash testcase
It took me a very long time to figure out the minimal testcase for this bug. 
Please note bug 231396, which might've made it easier.	:-)

In this crash testcase, there's a valid method which follows an invalid one
(this is actually required for the testcase to crash in current builds), and
two elements tied to the same binding (again, required).  Other permutations
(such as swapping the methods around) do not crash Mozilla.
Note, this is from a patched debug build, so some line numbers may be wrong.
The problem here is a follows:

1)  nsXBLProtoImpl::InstallImplementation calls InitTargetObjects.
2)  The first time we attach the binding, InitTargetObjects sees no mClassObject
    and calls CompilePrototypeMembers.
3)  CompilePrototypeMembers creates mClassObject, starts compiling members,
    fails on the first one, and bails out.  This makes InitTargetObjects bail
    out too, and makes InstallImplementation bail out as well, which means we
    never try to install the members on the object.
4)  The second time through, mClassObject is set (by step 3).  So
    InitTargetObjects doesn't bother calling CompilePrototypeMembers and we end
    up in the InstallMember loop.
5)  Calling InstallMember on an uncompiled (because we bailed before we got to
    it in step 3) nsXBLProtoImplMethod crashes (because we think we know what's
    in the union, but we're wrong).

The core problem is that the binding has a single "compiled" flag -- the binding
is compiled if mClassObject is set.  So even if steps 4 and 5 above were
avoided, at binding teardown the Destroy() method would be called with the
aCompiled flag set to "true" anyway, and that would cause similarly bogus access
to the union.  So just messing with mClassObject is not enough -- we need to
ensure that all proto members are in the "compiled" (this can include
"destroyed") state after the compilation phase.

The two posssible solutions I see:

1)  Ignore failure returns in the CompileMember loop and make sure to call
    CompileMember on all the members.  The CompileMember functions do
    appropriate cleanup when compilation fails, so this would do the trick.
2)  On failure return in the loop, go through and destroy all members (with
    aCompiled set to true for the already-compiled ones and to false for the
    yet-to-be-compiled ones).

The former would mean that all methods but the one that failed would be defined;
the latter would mean that none of the methods would be defined.  I'm not sure
which is better here...
Attached patch Possible fixSplinter Review
This destroys all the members and properties on the binding if a compilation
error happens.	Per conversation with WeirdAl this is better than having
sorta-working franken-bindings.

I'd love it if we could prevent binding attachment completely in such cases...
Assignee: hyatt → bz-vacation
Attachment #139958 - Flags: superreview?(bryner)
Attachment #139958 - Flags: review?(bryner)
OS: Linux → All
Priority: -- → P1
Hardware: PC → All
Summary: JS syntax error in XBL binding used twice crashes Mozilla → [FIX]JS syntax error in XBL binding used twice crashes Mozilla
Target Milestone: --- → mozilla1.7alpha
Attachment #139958 - Flags: superreview?(bryner)
Attachment #139958 - Flags: superreview+
Attachment #139958 - Flags: review?(bryner)
Attachment #139958 - Flags: review+
>+    curr->Destroy(compiled);
>+    if (curr == aBrokenMember) {
>+      compiled = PR_FALSE;
>+    }

I switched the Destroy() call and the if places to correspond to the comment I
put in the header...  Checked in.
Closed: 21 years ago
Resolution: --- → FIXED
Flags: in-testsuite+
You need to log in before you can comment on or make changes to this bug.