Closed
Bug 368760
Opened 14 years ago
Closed 13 years ago
NotifySelectionListeners might lead to self destruction
Categories
(Core :: DOM: Selection, defect, P1)
Core
DOM: Selection
Tracking
()
RESOLVED
FIXED
People
(Reporter: mats, Assigned: smaug)
References
Details
(Whiteboard: [sg:critical?][dbaron-1.9:RsCe])
Attachments
(1 file, 6 obsolete files)
74.95 KB,
patch
|
roc
:
superreview+
|
Details | Diff | Splinter Review |
See the stack from bug 368697: attachment 253357 [details] As roc pointed out it might also lead to destroying 'this'. I guess the obvious solution is to fire off the NotifySelectionListeners call from an event, but is that enough I wonder? Perhaps for the internal calls leading up to NotifySelectionListeners, but what about external callers... e.g. editor code - can the editor be destroyed as well? The whole thing seems rather fragile, it only takes one call to FlushPendingNotifications() and we're back to square one... I'm not sure if adding "kungFuDeathGrip(this)" all over the place is desired either...
Reporter | ||
Comment 1•14 years ago
|
||
Internal paths leading up to NotifySelectionListeners() NotifySelectionListeners Collapse MoveCaret CharacterMove WordMove WordExtendForDelete LineMove IntraLineMove AdjustForMaintainedSelection HandleClick CommonPageMove HandleDrag nsAutoScrollTimer::Notify TakeFocus VisualSequence SelectToEdge SelectLines VisualSelectFrames HandleClick SelectAll HandleTableSelection DeleteFromDocument CollapseToStart CollapseToEnd SelectAllChildren Extend RemoveRange SelectBlockOfCells AddRange CreateAndAddRange SelectCellElement SelectRowOrColumn RemoveAllRanges ClearNormalSelection EndBatchChanges SetMouseDownState
![]() |
||
Comment 2•14 years ago
|
||
So maybe we should actually enforce XPCOM stuff. Like "you must hold a pointer to the callee across the call no matter what". If we can't because we have non-XPCOM classes on the stack, then the first caller into non-XPCOM code should flish pending notifications... and no one under that call should then be modifying the DOM. Or something. I agree that just throwing around kung-fu-death-grips is fragile.
Reporter | ||
Comment 3•14 years ago
|
||
FWIW, I think there is a potential crash on using the "tableLayoutObject" (a table frame) after RemoveRange() have been called in SelectBlockOfCells(). http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/generic/nsSelection.cpp&rev=3.277&root=/cvsroot&mark=3228,3249,3263,3284#3226
Reporter | ||
Comment 4•14 years ago
|
||
Do NotifySelectionListeners() off an event.
Attachment #254524 -
Flags: superreview?(bzbarsky)
Attachment #254524 -
Flags: review?(bzbarsky)
![]() |
||
Comment 5•14 years ago
|
||
I'm sorry, bug there's no way I'm competent to review this code. Someone who has some familiarity with it should look.... perhaps one of the editor peers? Especially Simon?
Reporter | ||
Updated•14 years ago
|
Attachment #254524 -
Flags: review?(bzbarsky) → review?(sfraser_bugs)
Comment 6•14 years ago
|
||
This changes affects the call timing of lots of other things: http://lxr.mozilla.org/mozilla/ident?i=NotifySelectionChanged including onselect events, caret drawing, command updating etc. Please check all of those to make sure that there are no unwanted side effects.
Comment 7•14 years ago
|
||
This is old code so potentially affects the 1.8 branch as well, right?
Flags: wanted1.8.1.x?
Flags: wanted1.8.0.x?
Flags: blocking1.9?
Whiteboard: [sg:critical?]
Flags: blocking1.9? → blocking1.9+
![]() |
||
Comment 8•14 years ago
|
||
Comment on attachment 254524 [details] [diff] [review] Patch rev. 1 Please rerequest sr once this has review...
Attachment #254524 -
Flags: superreview?(bzbarsky)
Comment 9•14 years ago
|
||
Mats, can you please address Comment #6 ?
Mats, what's the story here?
Comment 11•14 years ago
|
||
Seconding Roc's request for followup. :)
Updated•14 years ago
|
Whiteboard: [sg:critical?] → [sg:critical?][dbaron-1.9:RsCe]
This is a scary area with possible regressions and stuff, so we really need it addressed for beta2.
Priority: -- → P1
Comment 13•13 years ago
|
||
Smaug, any chance you'd be able to pick this one up and figure out what to do here?
Assignee | ||
Comment 14•13 years ago
|
||
This patch forces strong ownership of nsFrameSelection in most cases and changes nsTypedSelection<->nsFrameSelection ownership so that if nsFrameSelection has created the nsTypedSelection object, nsFrameSelection is guaranteed to outlive nsTypedSelection. So if nsTypedSelection objects and nsFrameSelection objects are handled using strong pointers, things should be safer. Comments? Mats, what do you think about this?
Attachment #289462 -
Flags: review?(mats.palmgren)
Reporter | ||
Comment 15•13 years ago
|
||
Comment on attachment 289462 [details] [diff] [review] alternative approach I think this is a better approach; it's more robust and less risky. > This patch forces strong ownership of nsFrameSelection in most cases IMO, we should make that an explicit requirement: consumers of nsFrameSelection MUST hold a strong ref. - if we don't require that then we need to add kungFuDeathGrip(this) in most methods listed in comment 1. We also need to something about the current use of |mShell|. AFAICT, it's a non-addref'ed plain pointer: http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/generic/nsFrameSelection.h&rev=1.19&root=/cvsroot&mark=639#639 We need to handle the case were the nsFrameSelection out-lives the shell - which will be more likely now that we extend the life of the nsFrameSelection with strong refs. Making |mShell| a nsWeakPtr is probably the way to go. Also, when dealing with frames, null-checking |mShell| isn't enough. For example: http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/generic/nsSelection.cpp&rev=3.296&root=/cvsroot&mark=3314,3324#3302 the |tableLayoutObject| frame can be destroyed by line 3324. Holding a strong ref on |this| or even |mShell| doesn't help, we must use nsWeakFrame or lookup the frame again. Also watch out for other non-ref-counted things, like views: http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/generic/nsSelection.cpp&rev=3.296&root=/cvsroot&mark=563#521 |captureView| might have been destroyed by HandleDrag(). A few comments on the patch: In nsFrameSelection::MoveCaret and NotifySelectionListeners: we don't need the |kungFuDeathGrip(this)| - mDomSelections[i]->DetachFromPresentation(); - NS_RELEASE(mDomSelections[i]); + delete mDomSelections[i]; // Calls DetachFromPresentation(); This was the last outside caller - we can remove DetachFromPresentation() and move its contents to the destructor. Maybe I'm missing something but I didn't quite get the point of moving nsTextInputSelectionImpl::mFrameSelection to a super-class and then using stack based strong refs... consumers of nsTextInputSelectionImpl (read nsISelectionController) are already required to have a strong ref, so mFrameSelection can't be destroyed... http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/forms/nsTextControlFrame.cpp&rev=3.271&root=/cvsroot&mark=884,886#869 could crash otherwise (if |this| was destroyed). We can remove the mFrameSelection null-checks though. If we don't want that requirement on nsISelectionController consumers, then I do see the point, but then we also need kungFuDeathGrip(this) in a few nsTextInputSelectionImpl methods.
Attachment #289462 -
Flags: review?(mats.palmgren) → review-
Reporter | ||
Updated•13 years ago
|
Assignee: mats.palmgren → Olli.Pettay
Reporter | ||
Updated•13 years ago
|
Attachment #254524 -
Attachment is obsolete: true
Attachment #254524 -
Flags: review?(sfraser_bugs)
Reporter | ||
Comment 16•13 years ago
|
||
Comment on attachment 289462 [details] [diff] [review] alternative approach BTW, this crashes on Linux with an infinite stack of nsTypedSelection::AddRef() calls. Casting |this| to a super-class in NS_IMPL_ADDREF_USING_AGGREGATOR doesn't help, it will still use the vtable for the AddRef() call. We must use an explicit super::AddRef() to avoid that. It's probably clearer to just implement AddRef/Release explicitly here instead of using the macros.
Assignee | ||
Comment 17•13 years ago
|
||
(In reply to comment #15) > (From update of attachment 289462 [details] [diff] [review]) > I think this is a better approach; it's more robust and less risky. > > > This patch forces strong ownership of nsFrameSelection in most cases > > IMO, we should make that an explicit requirement: consumers of > nsFrameSelection MUST hold a strong ref. That is why methods return already_addrefed. - if we don't require that > then we need to add kungFuDeathGrip(this) in most methods listed in > comment 1. Well, keeping nsTypedSelection alive is enough, if the Addref/release trick works. Ofc the users of nsTypedSelection must have strong pointers... > We also need to something about the current use of |mShell|. > AFAICT, it's a non-addref'ed plain pointer: > http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/generic/nsFrameSelection.h&rev=1.19&root=/cvsroot&mark=639#639 > We need to handle the case were the nsFrameSelection out-lives the shell - > which will be more likely now that we extend the life of the > nsFrameSelection with strong refs. Making |mShell| a nsWeakPtr is > probably the way to go. Right. > Also, when dealing with frames, null-checking |mShell| isn't enough. > For example: > http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/generic/nsSelection.cpp&rev=3.296&root=/cvsroot&mark=3314,3324#3302 > the |tableLayoutObject| frame can be destroyed by line 3324. > Holding a strong ref on |this| or even |mShell| doesn't help, we must > use nsWeakFrame or lookup the frame again. Right, will fix. Probably lookup the frame again. > Maybe I'm missing something but I didn't quite get the point of moving > nsTextInputSelectionImpl::mFrameSelection to a super-class and then > using stack based strong refs... consumers of nsTextInputSelectionImpl > (read nsISelectionController) are already required to have a strong ref, > so mFrameSelection can't be destroyed... nsTextInputSelectionImpl is owned by a nsIFrame object which may get deleted...
Assignee | ||
Comment 18•13 years ago
|
||
(In reply to comment #17) > nsTextInputSelectionImpl is owned by a nsIFrame object which may get deleted... Though, this shouldn't be a problem here, except in ::SetValue.
Assignee | ||
Comment 19•13 years ago
|
||
Added DisconnectFromPresShell, null checks for mShell, AddRef/Release implementation (based on the macro implementation) etc.
Attachment #289462 -
Attachment is obsolete: true
Attachment #289537 -
Flags: review?(mats.palmgren)
Assignee | ||
Comment 20•13 years ago
|
||
Attachment #289537 -
Attachment is obsolete: true
Attachment #289540 -
Flags: review?(mats.palmgren)
Attachment #289537 -
Flags: review?(mats.palmgren)
Reporter | ||
Comment 21•13 years ago
|
||
Comment on attachment 289540 [details] [diff] [review] v2 Looks good. r=mats A couple of nits: >Index: layout/generic/nsSelection.cpp While we're here, please remove the STATUS_CHECK_RETURN_MACRO macro and replace it with NS_ENSURE_STATE(mShell) or add '!mShell' to the 'if': http://bonsai.mozilla.org/cvsblame.cgi?file=/mozilla/layout/generic/nsSelection.cpp&rev=3.296&root=/cvsroot&mark=2379#2369 >Index: layout/forms/nsTextControlFrame.cpp: >+ nsCOMPtr<nsISelectionController> kungfuDeatGrip = mSelCon; kungFuDeathGrip is the spelling used in other files...
Attachment #289540 -
Flags: review?(mats.palmgren) → review+
Reporter | ||
Comment 22•13 years ago
|
||
Regarding the nsTypedSelection::AddRef()/Release() implementations: It would be nice if had macros for the default bodies in nsISupportsImpl.h so we could write something like: nsTypedSelection::Release() { if (mFrameSelection) { return mFrameSelection->Release(); } NS_IMPL_RELEASE_WITH_DESTROY_BODY(nsTypedSelection, NS_DELETEXPCOM(this)); } There are a few more places we could reuse that: http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/js/src/xpconnect/src/xpccallcontext.cpp&rev=1.20&root=/cvsroot&mark=364-369#361 http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/js/src/xpconnect/src/XPCDispPrivate.h&rev=1.24&root=/cvsroot&mark=128-137#125 http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/ipc/ipcd/extensions/dconnect/src/ipcDConnectService.cpp&rev=1.14&root=/cvsroot&mark=983-992#977
Assignee | ||
Comment 23•13 years ago
|
||
(In reply to comment #22) > Regarding the nsTypedSelection::AddRef()/Release() implementations: > It would be nice if had macros for the default bodies in nsISupportsImpl.h Could file a new bug for that.
Assignee | ||
Comment 24•13 years ago
|
||
Attachment #289540 -
Attachment is obsolete: true
Attachment #289649 -
Flags: superreview?(roc)
The patch looks fine, but can we document which methods of nsFrameSelection can blow up the world? Because consumers like frames had better not call those methods. In fact it would be nice if there was a way to get a non-addrefed pointer to an object that implemented just the safe methods. Maybe we could make some of the safe methods in nsFrameSelection const and have methods that return non-addrefed but const nsFrameSelection pointers?
Assignee | ||
Comment 26•13 years ago
|
||
Const methods help identifying problematic cases. Not all non-const methods are unsafe, but when starting from const nsFrameSelection*, one needs to think why to use non-const object.
Attachment #289649 -
Attachment is obsolete: true
Attachment #289835 -
Flags: superreview?(roc)
Attachment #289649 -
Flags: superreview?(roc)
Can you document in nsFrameSelection.h which methods are unsafe?
Assignee | ||
Comment 28•13 years ago
|
||
Attachment #289835 -
Attachment is obsolete: true
Attachment #289839 -
Flags: superreview?(roc)
Attachment #289835 -
Flags: superreview?(roc)
Attachment #289839 -
Flags: superreview?(roc) → superreview+
Assignee | ||
Updated•13 years ago
|
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Updated•8 years ago
|
Group: core-security
You need to log in
before you can comment on or make changes to this bug.
Description
•