Bug 226799

Summary: Nullptr crash in null ptr deref in ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline
Product: WebKit Reporter: Ryosuke Niwa <rniwa>
Component: HTML EditingAssignee: Frédéric Wang (:fredw) <fred.wang>
Status: RESOLVED FIXED    
Severity: Normal CC: bfulgham, cgarcia, darin, ews-feeder, fred.wang, gpoo, product-security, rbuis, svillar, webkit-bug-importer, wenson_hsieh
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   
Attachments:
Description Flags
Test
none
Patch none

Description Ryosuke Niwa 2021-06-08 17:15:32 PDT
Created attachment 430918 [details]
Test

e.g.

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.WebCore             	0x0000000161224430 WTF::OptionSet<WebCore::Node::NodeFlag>::isEmpty() const + 1 (OptionSet.h:164) [inlined]
1   com.apple.WebCore             	0x0000000161224430 WTF::OptionSet<WebCore::Node::NodeFlag>::operator bool() + 1 (OptionSet.h:169) [inlined]
2   com.apple.WebCore             	0x0000000161224430 WTF::OptionSet<WebCore::Node::NodeFlag>::containsAny(WTF::OptionSet<WebCore::Node::NodeFlag>) const + 1 (OptionSet.h:178) [inlined]
3   com.apple.WebCore             	0x0000000161224430 WTF::OptionSet<WebCore::Node::NodeFlag>::contains(WebCore::Node::NodeFlag) const + 1 (OptionSet.h:173) [inlined]
4   com.apple.WebCore             	0x0000000161224430 WebCore::Node::hasNodeFlag(WebCore::Node::NodeFlag) const + 1 (Node.h:585) [inlined]
5   com.apple.WebCore             	0x0000000161224430 WebCore::Node::isTextNode() const + 1 (Node.h:191) [inlined]
6   com.apple.WebCore             	0x0000000161224430 WebCore::firstPositionInNode(WebCore::Node*) + 1 (Position.h:322) [inlined]
7   com.apple.WebCore             	0x0000000161224430 WebCore::ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(WebCore::ReplaceSelectionCommand::InsertedNodes&) + 992 (ReplaceSelectionCommand.cpp:667)
8   com.apple.WebCore             	0x000000016122927c WebCore::ReplaceSelectionCommand::doApply() + 10860 (ReplaceSelectionCommand.cpp:1362)
9   com.apple.WebCore             	0x00000001611a93b7 WebCore::CompositeEditCommand::apply() + 167 (CompositeEditCommand.cpp:397)
10  com.apple.WebCore             	0x00000001611de4ec WebCore::Editor::replaceSelectionWithFragment(WebCore::DocumentFragment&, WebCore::Editor::SelectReplacement, WebCore::Editor::SmartReplace, WebCore::Editor::MatchStyle, WebCore::EditAction, WebCore::MailBlockquoteHandling) + 892 (Editor.cpp:698)
11  com.apple.WebCore             	0x00000001611de088 WebCore::Editor::handleTextEvent(WebCore::TextEvent&) + 72 (Editor.cpp:347)
12  com.apple.WebCore             	0x00000001616b70df WebCore::EventHandler::defaultTextInputEventHandler(WebCore::TextEvent&) + 31 (EventHandler.cpp:4182)
13  com.apple.WebCore             	0x0000000161115013 WebCore::callDefaultEventHandlersInBubblingOrder(WebCore::Event&, WebCore::EventPath const&) + 39 (EventDispatcher.cpp:63) [inlined]
14  com.apple.WebCore             	0x0000000161115013 WebCore::EventDispatcher::dispatchEvent(WebCore::Node&, WebCore::Event&) + 1763 (EventDispatcher.cpp:204)
15  com.apple.WebCore             	0x00000001611e0ae5 WebCore::Editor::pasteAsFragment(WTF::Ref<WebCore::DocumentFragment, WTF::RawPtrTraits<WebCore::DocumentFragment> >&&, bool, bool, WebCore::MailBlockquoteHandling) + 245 (Editor.cpp:629)
16  com.apple.WebCore             	0x00000001604ee133 WebCore::Editor::pasteWithPasteboard(WebCore::Pasteboard*, WTF::OptionSet<WebCore::Editor::PasteOption>) + 259 (EditorMac.mm:97)
17  com.apple.WebCore             	0x00000001611e7e39 WebCore::Editor::paste(WebCore::Pasteboard&, WebCore::Editor::FromMenuOrKeyBinding) + 377 (Editor.cpp:1479)
18  com.apple.WebCore             	0x00000001611e7c7f WebCore::Editor::paste(WebCore::Editor::FromMenuOrKeyBinding) + 95 (Editor.cpp:1465)
19  com.apple.WebCore             	0x000000016120a063 WebCore::executePaste(WebCore::Frame&, WebCore::Event*, WebCore::EditorCommandSource, WTF::String const&) + 51 (EditorCommand.cpp:904)
20  com.apple.WebCore             	0x00000001610d7cac WebCore::Document::execCommand(WTF::String const&, bool, WTF::String const&) + 76 (Document.cpp:5759)
21  com.apple.WebCore             	0x0000000160357a16 WebCore::jsDocumentPrototypeFunction_execCommandBody(JSC::JSGlobalObject*, JSC::CallFrame*, WebCore::JSDocument*) + 218 (JSDocument.cpp:5859) [inlined]
22  com.apple.WebCore             	0x0000000160357a16 long long WebCore::IDLOperation<WebCore::JSDocument>::call<&(WebCore::jsDocumentPrototypeFunction_execCommandBody(JSC::JSGlobalObject*, JSC::CallFrame*, WebCore::JSDocument*)), (WebCore::CastedThisErrorBehavior)0>(JSC::JSGlobalObject&, JSC::CallFrame&, char const*) + 392 (JSDOMOperation.h:63) [inlined]
23  com.apple.WebCore             	0x0000000160357a16 WebCore::jsDocumentPrototypeFunction_execCommand(JSC::JSGlobalObject*, JSC::CallFrame*) + 422 (JSDocument.cpp:5864)
24  ???                           	0x00003634ef4011d8 0 + 59600980152792
25  com.apple.JavaScriptCore      	0x0000000165ba65f7 llint_entry + 110528 (LowLevelInterpreter.asm:1097)
26  com.apple.JavaScriptCore      	0x0000000165b8b436 vmEntryToJavaScript + 216 (LowLevelInterpreter64.asm:316)

<rdar://78689218>
Comment 1 Ryosuke Niwa 2021-06-08 17:15:44 PDT
Reproduced with non-ASAN release build of WebKitTestRunner at r278627.
Comment 2 Frédéric Wang (:fredw) 2021-06-16 08:39:45 PDT
(In reply to Ryosuke Niwa from comment #1)
> Reproduced with non-ASAN release build of WebKitTestRunner at r278627.

FWIW ASAN build gives:

==75==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000028 (pc 0x7f9b19cf6b86 bp 0x7ffe7ea01800 sp 0x7ffe7ea01750 T0)
==75==The signal is caused by a READ memory access.
==75==Hint: address points to the zero page.
    #0 0x7f9b19cf6b86 in WTF::OptionSet<WebCore::Node::NodeFlag>::containsAny(WTF::OptionSet<WebCore::Node::NodeFlag>) const (/app/webkit/WebKitBuild/Debug/lib/libwebkit2gtk-4.1.so.0+0x8baeb86)
    #1 0x7f9b19cf456a in WTF::OptionSet<WebCore::Node::NodeFlag>::contains(WebCore::Node::NodeFlag) const (/app/webkit/WebKitBuild/Debug/lib/libwebkit2gtk-4.1.so.0+0x8bac56a)
    #2 0x7f9b19cf2979 in WebCore::Node::hasNodeFlag(WebCore::Node::NodeFlag) const (/app/webkit/WebKitBuild/Debug/lib/libwebkit2gtk-4.1.so.0+0x8baa979)
    #3 0x7f9b19df2eb2 in WebCore::Node::isTextNode() const (/app/webkit/WebKitBuild/Debug/lib/libwebkit2gtk-4.1.so.0+0x8caaeb2)
    #4 0x7f9b1ad554af in WebCore::firstPositionInNode(WebCore::Node*) (/app/webkit/WebKitBuild/Debug/lib/libwebkit2gtk-4.1.so.0+0x9c0d4af)
    #5 0x7f9b1f565394 in WebCore::ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(WebCore::ReplaceSelectionCommand::InsertedNodes&) (/app/webkit/WebKitBuild/Debug/lib/libwebkit2gtk-4.1.so.0+0xe41d394)

will take a look at this bug.
Comment 3 Darin Adler 2021-06-16 08:59:54 PDT
Looks like the local variable named context, the element’s parent, is nullptr.
Comment 4 Frédéric Wang (:fredw) 2021-06-16 23:18:25 PDT
(In reply to Darin Adler from comment #3)
> Looks like the local variable named context, the element’s parent, is
> nullptr.

Right, so it looks like when Paste is called,  callDefaultEventHandlersInBubblingOrder will also execute the Indent command queued in the microtask which is the one removing the h1 element from the tree. Checking whether the node is orphan seems enought to prevent the crash in the testcase.

Thread 1 received signal SIGSEGV, Segmentation fault.
(rr) reverse-f
(rr) 
(rr) 
(rr) 
(rr) 
(rr)
    at ../../Source/WebCore/editing/ReplaceSelectionCommand.cpp:667
667	            RefPtr<Node> blockquoteNode = isMailPasteAsQuotationNode(context.get()) ? context.get() : enclosingNodeOfType(firstPositionInNode(context.get()), isMailBlockquote, CanCrossEditingBoundary);
(rr) p context.get()
$1 = (WebCore::ContainerNode *) 0x0
(rr) bt
#0  0x00007fdeea729390 in WebCore::ReplaceSelectionCommand::removeRedundantStylesAndKeepStyleSpanInline(WebCore::ReplaceSelectionCommand::InsertedNodes&)
    (this=0x615000261680, insertedNodes=...)
    at ../../Source/WebCore/editing/ReplaceSelectionCommand.cpp:667
#1  0x00007fdeea732a0d in WebCore::ReplaceSelectionCommand::doApply()
    (this=0x615000261680)
    at ../../Source/WebCore/editing/ReplaceSelectionCommand.cpp:1362
#2  0x00007fdeee955195 in WebCore::CompositeEditCommand::apply()
    (this=0x615000261680)
    at ../../Source/WebCore/editing/CompositeEditCommand.cpp:397
#3  0x00007fdeea660251 in WebCore::Editor::replaceSelectionWithFragment(WebCore::DocumentFragment&, WebCore::Editor::SelectReplacement, WebCore::Editor::SmartReplace, WebCore::Editor::MatchStyle, WebCore::EditAction, WebCore::MailBlockquoteHandling)
    (this=0x614000077a40, fragment=..., selectReplacement=WebCore::Editor::SelectReplacement::No, smartReplace=WebCore::Editor::SmartReplace::No, matchStyle=WebCore::Editor::MatchStyle::No, editingAction=WebCore::EditAction::Paste, mailBlockquoteHandling=WebCore::MailBlockquoteHandling::RespectBlockquote)
    at ../../Source/WebCore/editing/Editor.cpp:698
#4  0x00007fdeea65c0a6 in WebCore::Editor::handleTextEvent(WebCore::TextEvent&)
    (this=0x614000077a40, event=...)
    at ../../Source/WebCore/editing/Editor.cpp:347
#5  0x00007fdeeb8ef946 in WebCore::EventHandler::defaultTextInputEventHandler(We
bCore::TextEvent&) (this=0x616000384c80, event=...)
    at ../../Source/WebCore/page/EventHandler.cpp:4182
#6  0x00007fdeea4062ae in WebCore::Node::defaultEventHandler(WebCore::Event&)
    (this=0x61200007e7c0, event=warning: RTTI symbol not found for class 'WebCore::TextEvent'
...) at ../../Source/WebCore/dom/Node.cpp:2451
#7  0x00007fdeeaa33e7b in WebCore::HTMLInputElement::defaultEventHandler(WebCore::Event&) (this=0x61200007e7c0, event=warning: RTTI symbol not found for class 'WebCore::TextEvent'
...)
    at ../../Source/WebCore/html/HTMLInputElement.cpp:1258
#8  0x00007fdeea2ed704 in WebCore::callDefaultEventHandlersInBubblingOrder(WebCore::Event&, WebCore::EventPath const&) (event=warning: RTTI symbol not found for class 'WebCore::TextEvent'
..., path=...)
    at ../../Source/WebCore/dom/EventDispatcher.cpp:63
#9  0x00007fdeea2ee863 in WebCore::EventDispatcher::dispatchEvent(WebCore::Node&, WebCore::Event&) (node=..., event=warning: RTTI symbol not found for class 'WebCore::TextEvent'
...)
    at ../../Source/WebCore/dom/EventDispatcher.cpp:204
#10 0x00007fdeea4056f3 in WebCore::Node::dispatchEvent(WebCore::Event&)
    (this=0x61200007e7c0, event=warning: RTTI symbol not found for class 'WebCore::TextEvent'
...) at ../../Source/WebCore/dom/Node.cpp:2381
#11 0x00007fdeea65eda9 in WebCore::Editor::pasteAsFragment(WTF::Ref<WebCore::DocumentFragment, WTF::RawPtrTraits<WebCore::DocumentFragment> >&&, bool, bool, WebCore::MailBlockquoteHandling)
    (this=0x614000077a40, pastingFragment=..., smartReplace=false, matchStyle=false, respectsMailBlockquote=WebCore::MailBlockquoteHandling::RespectBlockquote)
    at ../../Source/WebCore/editing/Editor.cpp:629
...
(rr) p showTree(element)
warning: RTTI symbol not found for class 'WebCore::HTMLHeadingElement'
*H1	0x60c0002b39c0 (renderer (nil))  STYLE=caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0.4); -webkit-text-stroke-width: 0px; text-decoration: none;
$2 = void
(rr) watch -l element->m_parentNode
(rr) rc
(rr) delete
(rr) reverse-f
(rr) bt
#0  0x00007fdeea0b3a05 in WebCore::ContainerNode::removeBetween(WebCore::Node*, WebCore::Node*, WebCore::Node&)
    (this=0x60c0002a6a00, previousChild=0x60c0002b8f40, nextChild=0x60c0002a8380, oldChild=warning: RTTI symbol not found for class 'WebCore::HTMLHeadingElement'
...) at ../../Source/WebCore/dom/ContainerNode.cpp:655
#1  0x00007fdeea0c19a2 in WebCore::ContainerNode::removeNodeWithScriptAssertion(WebCore::Node&, WebCore::ContainerNode::ChildChange::Source)
    (this=0x60c0002a6a00, childToRemove=warning: RTTI symbol not found for class 'WebCore::HTMLHeadingElement'
..., source=WebCore::ContainerNode::ChildChange::Source::API)
    at ../../Source/WebCore/dom/ContainerNode.cpp:181
#2  0x00007fdeea0b3355 in WebCore::ContainerNode::removeChild(WebCore::Node&)
    (this=0x60c0002a6a00, oldChild=warning: RTTI symbol not found for class 'WebCore::HTMLHeadingElement'
...)
    at ../../Source/WebCore/dom/ContainerNode.cpp:614
#3  0x00007fdeea3f85a0 in WebCore::Node::remove() (this=0x60c0002b39c0)
    at ../../Source/WebCore/dom/Node.cpp:642
...
#17 0x00007fdeea695d53 in WebCore::executeIndent(WebCore::Frame&, WebCore::Event*, WebCore::EditorCommandSource, WTF::String const&) (frame=...) at ../../Source/WebCore/editing/EditorCommand.cpp:445
...
(rr) reverse-f
(rr) reverse-f
(rr) reverse-f
(rr) p showTree(parent)
*BODY	0x60c0002a6a00 (renderer 0x61200007dbc0) 
	H1	0x60c0002a8080 (renderer 0x61200007fe40) 
		DIV	0x60c0002a82c0 (renderer 0x61200006c4c0) 
	BLOCKQUOTE	0x60c0002b8f40 (renderer 0x612000097e40)  STYLE=margin: 0 0 0 40px; border: none; padding: 0px;
		H1	0x60c0002b9780 (renderer 0x612000098d40)  STYLE=caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0.4); -webkit-text-stroke-width: 0px; text-decoration: none;
			INPUT	0x612000098140 (renderer 0x612000098ec0) 
				#document-fragment	0x6120000982c0 (renderer (nil))  (needs style recalc) (child needs style recalc)
					DIV	0x60c0002b9900 (renderer 0x612000099040) 
	H1	0x60c0002b39c0 (renderer 0x612000094fc0)  STYLE=caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0.4); -webkit-text-stroke-width: 0px; text-decoration: none;
	H2	0x60c0002a8380 (renderer 0x61200006c7c0) 
	H3	0x60c0002a8440 (renderer 0x612000096c40) 
		IFRAME	0x61400007d840 (renderer 0x612000096dc0) 
$3 = void
Comment 5 Frédéric Wang (:fredw) 2021-06-17 02:01:28 PDT
Created attachment 431636 [details]
Patch

More debugging:

0x00007f6f7b667a08 in WebCore::ReplaceSelectionCommand::doApply (
    this=0x615000261180)
    at ../../Source/WebCore/editing/ReplaceSelectionCommand.cpp:1364
1364	    removeRedundantStylesAndKeepStyleSpanInline(insertedNodes);
(rr) p showTree(insertedNodes.firstNodeInserted())
warning: RTTI symbol not found for class 'WebCore::HTMLHeadingElement'
*H1	0x60c0002b3780 (renderer (nil))  STYLE=caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0.4); -webkit-text-stroke-width: 0px; text-decoration: none;
$1 = void
(rr) rn
(rr)
(rr)
(rr)
(rr)
1355	    makeInsertedContentRoundTrippableWithHTMLTreeBuilder(insertedNodes);
(rr) rn
1352	    if (insertedNodes.isEmpty())
(rr) p showTree(insertedNodes.firstNodeInserted())
warning: RTTI symbol not found for class 'WebCore::HTMLHeadingElement'
BODY	0x60c0002a6880 (renderer 0x61200007dbc0) 
	H1	0x60c0002a7f00 (renderer 0x61200007fe40) 
*		H1	0x60c0002b3780 (renderer 0x6120000a3b40)  STYLE=caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-family: -webkit-standard; font-style: normal; font-variant-caps: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-tap-highlight-color: rgba(0, 0, 0, 0.4); -webkit-text-stroke-width: 0px; text-decoration: none;
			INPUT	0x6120000a2640 (renderer 0x6120000a3cc0) 
				#document-fragment	0x6120000a27c0 (renderer (nil))  (needs style recalc) (child needs style recalc)
					DIV	0x60c0002b3900 (renderer 0x6120000a3e40) 
		DIV	0x60c0002a8140 (renderer 0x61200006c4c0) 
	H2	0x60c0002a8200 (renderer 0x61200006c7c0) 
		H3	0x60c0002a82c0 (renderer 0x61200006c940) 
			IFRAME	0x61400007d840 (renderer 0x6120000a1740) 
$3 = void
Comment 6 EWS 2021-06-22 02:06:20 PDT
Committed r279110 (239027@main): <https://commits.webkit.org/239027@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 431636 [details].