Bug 218493 - Null Ptr Deref @ WebCore::ReplaceSelectionCommand::doApply
Summary: Null Ptr Deref @ WebCore::ReplaceSelectionCommand::doApply
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: HTML Editing (show other bugs)
Version: WebKit Local Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2020-11-03 02:40 PST by Ian Gilbert
Modified: 2021-01-25 18:24 PST (History)
14 users (show)

See Also:


Attachments
Crashing Input (475.17 KB, text/html)
2020-11-03 02:41 PST, Ian Gilbert
no flags Details
Reduced crashing input (1.65 KB, text/html)
2020-11-05 00:31 PST, Ian Gilbert
no flags Details
More reduced testcase (481 bytes, text/plain)
2020-11-12 12:58 PST, Rob Buis
no flags Details
Patch (3.86 KB, patch)
2021-01-21 03:28 PST, Carlos Garcia Campos
achristensen: review-
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch (4.47 KB, patch)
2021-01-22 01:52 PST, Carlos Garcia Campos
youennf: review+
ews-feeder: commit-queue-
Details | Formatted Diff | Diff
Patch for landing (4.92 KB, patch)
2021-01-22 04:29 PST, Carlos Garcia Campos
ews-feeder: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ian Gilbert 2020-11-03 02:40:34 PST
Description:
Crash found by fuzzing. Reproduces on WebKit revision 265372.

Stack Trace
===========

0   com.apple.WebCore             	0x00000001114dd9cb WebCore::ReplaceSelectionCommand::doApply() + 17483
1   com.apple.WebCore             	0x00000001100cbbc4 WebCore::CompositeEditCommand::apply() + 500
2   com.apple.WebCore             	0x00000001114bc59a WebCore::executeInsertFragment(WebCore::Frame&, WTF::Ref<WebCore::DocumentFragment, WTF::DumbPtrTraits<WebCore::DocumentFragment> >&&) + 74
3   com.apple.WebCore             	0x00000001114bc6d4 WebCore::executeInsertNode(WebCore::Frame&, WTF::Ref<WebCore::Node, WTF::DumbPtrTraits<WebCore::Node> >&&) + 180
4   com.apple.WebCore             	0x00000001114b784b WebCore::executeInsertImage(WebCore::Frame&, WebCore::Event*, WebCore::EditorCommandSource, WTF::String const&) + 75
5   com.apple.WebCore             	0x000000011013123d WebCore::Document::execCommand(WTF::String const&, bool, WTF::String const&) + 77
6   com.apple.WebCore             	0x000000011053897c WebCore::jsDocumentPrototypeFunctionExecCommand(JSC::JSGlobalObject*, JSC::CallFrame*) + 428
7   ???                           	0x000026435ce01178 0 + 42070762852728
8   com.apple.JavaScriptCore      	0x000000010de7a95e llint_entry + 104810
9   com.apple.JavaScriptCore      	0x000000010de60dff vmEntryToJavaScript + 216
10  com.apple.JavaScriptCore      	0x000000010e49f536 JSC::Interpreter::executeCall(JSC::JSGlobalObject*, JSC::JSObject*, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 518
Comment 1 Radar WebKit Bug Importer 2020-11-03 02:40:51 PST
<rdar://problem/70987255>
Comment 2 Ian Gilbert 2020-11-03 02:41:29 PST
Created attachment 413027 [details]
Crashing Input
Comment 3 Ryosuke Niwa 2020-11-03 13:07:23 PST
<rdar://problem/68276643>
Comment 4 Ian Gilbert 2020-11-05 00:31:21 PST
Created attachment 413269 [details]
Reduced crashing input
Comment 5 Rob Buis 2020-11-12 12:58:47 PST
Created attachment 413970 [details]
More reduced testcase
Comment 6 Carlos Garcia Campos 2021-01-21 03:28:45 PST
Created attachment 418028 [details]
Patch

I'm including the test assuming there's no security implication here, since it's just another null check missing. Please confirm.
Comment 7 Alex Christensen 2021-01-21 09:27:38 PST
Comment on attachment 418028 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=418028&action=review

Yep, this test can be included.
WebKitLegacy seems to be asserting in fragmentNeedsColorTransformed.  We should probably fix that too before landing.  The null check seems fine though.

> Source/WebCore/editing/ReplaceSelectionCommand.cpp:1208
> +        if (insertionPos.containerNode() && insertionPos.containerNode()->isTextNode() && insertionPos.offsetInContainerNode() && !insertionPos.atLastEditingPositionForNode()) {

We could use if-with-initializer to avoid calling containerNode twice.
Comment 8 Carlos Garcia Campos 2021-01-22 01:49:48 PST
(In reply to Alex Christensen from comment #7)
> Comment on attachment 418028 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=418028&action=review
> 
> Yep, this test can be included.
> WebKitLegacy seems to be asserting in fragmentNeedsColorTransformed.  We
> should probably fix that too before landing.  The null check seems fine
> though.

Yes, it's here:

RefPtr<Element> editableRoot = insertionPos.rootEditableElement();
ASSERT(editableRoot);
if (!editableRoot)
    return false;

I think the assert is wrong and the early return correct, so we can just remove the assert.

> > Source/WebCore/editing/ReplaceSelectionCommand.cpp:1208
> > +        if (insertionPos.containerNode() && insertionPos.containerNode()->isTextNode() && insertionPos.offsetInContainerNode() && !insertionPos.atLastEditingPositionForNode()) {
> 
> We could use if-with-initializer to avoid calling containerNode twice.

Sure.
Comment 9 Carlos Garcia Campos 2021-01-22 01:52:25 PST
Created attachment 418119 [details]
Patch
Comment 10 Carlos Garcia Campos 2021-01-22 03:26:48 PST
Now it's hitting another assert, but I can't reproduce it this time. I'll investigate.
Comment 11 youenn fablet 2021-01-22 03:29:25 PST
Comment on attachment 418119 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=418119&action=review

> Source/WebCore/editing/ReplaceSelectionCommand.cpp:1209
> +                splitTextNode(*insertionPos.containerText(), insertionPos.offsetInContainerNode());

Do we have a guarantee that insertionPos.containerText() cannot be null? Is it ensured from containerNode->isTextNode()?
Looking at Position::containerText(), it seems to depend on anchorType being PositionIsOffsetInAnchor.
Comment 12 Carlos Garcia Campos 2021-01-22 04:13:37 PST
I was running the wrong test, I can indeed reproduce the new assert too.
Comment 13 Carlos Garcia Campos 2021-01-22 04:27:16 PST
(In reply to youenn fablet from comment #11)
> Comment on attachment 418119 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=418119&action=review
> 
> > Source/WebCore/editing/ReplaceSelectionCommand.cpp:1209
> > +                splitTextNode(*insertionPos.containerText(), insertionPos.offsetInContainerNode());
> 
> Do we have a guarantee that insertionPos.containerText() cannot be null? Is
> it ensured from containerNode->isTextNode()?
> Looking at Position::containerText(), it seems to depend on anchorType being
> PositionIsOffsetInAnchor.

Not an expert in editing code, but I think it's the whole condition:

containerNode->isTextNode() && insertionPos.offsetInContainerNode() && !insertionPos.atLastEditingPositionForNode()
Comment 14 Carlos Garcia Campos 2021-01-22 04:29:10 PST
Created attachment 418137 [details]
Patch for landing
Comment 15 EWS 2021-01-25 00:26:44 PST
commit-queue failed to commit attachment 418137 [details] to WebKit repository.
Comment 16 Carlos Garcia Campos 2021-01-25 00:33:22 PST
Committed r271787: <https://trac.webkit.org/changeset/271787>