Bug 226798 - Nullptr crash in Page::libWebRTCProvider via RTCPeerConnection::generateCertificate
Summary: Nullptr crash in Page::libWebRTCProvider via RTCPeerConnection::generateCerti...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebRTC (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Rob Buis
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2021-06-08 17:11 PDT by Ryosuke Niwa
Modified: 2021-06-09 21:53 PDT (History)
18 users (show)

See Also:


Attachments
Test (363 bytes, text/html)
2021-06-08 17:11 PDT, Ryosuke Niwa
no flags Details
Patch (3.83 KB, patch)
2021-06-09 01:29 PDT, Rob Buis
no flags Details | Formatted Diff | Diff
Patch (4.43 KB, patch)
2021-06-09 02:53 PDT, Rob Buis
no flags Details | Formatted Diff | Diff
Patch (4.40 KB, patch)
2021-06-09 05:18 PDT, Rob Buis
no flags Details | Formatted Diff | Diff
Patch (4.40 KB, patch)
2021-06-09 19:58 PDT, Rob Buis
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ryosuke Niwa 2021-06-08 17:11:39 PDT
Created attachment 430917 [details]
Test

e.g.

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   com.apple.WebCore             	0x000000010b51ef1e std::__1::unique_ptr<WebCore::LibWebRTCProvider, std::__1::default_delete<WebCore::LibWebRTCProvider> >::operator*() const + 0 (memory:2310) [inlined]
1   com.apple.WebCore             	0x000000010b51ef1e WTF::UniqueRef<WebCore::LibWebRTCProvider>::get() + 0 (UniqueRef.h:70) [inlined]
2   com.apple.WebCore             	0x000000010b51ef1e WebCore::Page::libWebRTCProvider() + 0 (Page.h:313) [inlined]
3   com.apple.WebCore             	0x000000010b51ef1e WebCore::PeerConnectionBackend::generateCertificate(WebCore::Document&, WebCore::PeerConnectionBackend::CertificateInformation const&, WebCore::DOMPromiseDeferred<WebCore::IDLInterface<WebCore::RTCCertificate> >&&) + 46 (PeerConnectionBackend.cpp:609)
4   com.apple.WebCore             	0x000000010b5482a4 WebCore::RTCPeerConnection::generateCertificate(JSC::JSGlobalObject&, WTF::Variant<JSC::Strong<JSC::JSObject, (JSC::ShouldStrongDestructorGrabLock)0>, WTF::String>&&, WebCore::DOMPromiseDeferred<WebCore::IDLInterface<WebCore::RTCCertificate> >&&) + 964 (RTCPeerConnection.cpp:772)
5   com.apple.WebCore             	0x000000010afa34fd WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)::'lambda'()::operator()() const + 20 (JSRTCPeerConnection.cpp:1079) [inlined]
6   com.apple.WebCore             	0x000000010afa34fd JSC::JSValue WebCore::toJS<WebCore::IDLPromise<WebCore::IDLInterface<WebCore::RTCCertificate> >, WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)::'lambda'()>(JSC::JSGlobalObject&, WebCore::JSDOMGlobalObject&, JSC::ThrowScope&, WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)::'lambda'()&&) + 20 (JSDOMConvertBase.h:195) [inlined]
7   com.apple.WebCore             	0x000000010afa34fd WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&) + 71 (JSRTCPeerConnection.cpp:1079) [inlined]
8   com.apple.WebCore             	0x000000010afa34fd long long WebCore::IDLOperationReturningPromise<WebCore::JSRTCPeerConnection>::callStatic<&(WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)), (WebCore::CastedThisErrorBehavior)2>(JSC::JSGlobalObject&, JSC::CallFrame&, char const*)::'lambda'(JSC::JSGlobalObject&, JSC::CallFrame&, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)::operator()(JSC::JSGlobalObject&, JSC::CallFrame&, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&) const + 71 (JSDOMOperationReturningPromise.h:79) [inlined]
9   com.apple.WebCore             	0x000000010afa34fd JSC::JSValue WebCore::callPromiseFunction<long long WebCore::IDLOperationReturningPromise<WebCore::JSRTCPeerConnection>::callStatic<&(WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)), (WebCore::CastedThisErrorBehavior)2>(JSC::JSGlobalObject&, JSC::CallFrame&, char const*)::'lambda'(JSC::JSGlobalObject&, JSC::CallFrame&, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)>(JSC::JSGlobalObject&, JSC::CallFrame&, &(WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&))) + 251 (JSDOMPromiseDeferred.h:337) [inlined]
10  com.apple.WebCore             	0x000000010afa34fd long long WebCore::IDLOperationReturningPromise<WebCore::JSRTCPeerConnection>::callStatic<&(WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificateBody(JSC::JSGlobalObject*, JSC::CallFrame*, WTF::Ref<WebCore::DeferredPromise, WTF::RawPtrTraits<WebCore::DeferredPromise> >&&)), (WebCore::CastedThisErrorBehavior)2>(JSC::JSGlobalObject&, JSC::CallFrame&, char const*) + 251 (JSDOMOperationReturningPromise.h:77) [inlined]
11  com.apple.WebCore             	0x000000010afa34fd WebCore::jsRTCPeerConnectionConstructorFunction_generateCertificate(JSC::JSGlobalObject*, JSC::CallFrame*) + 285 (JSRTCPeerConnection.cpp:1084)

<rdar://78765971>
Comment 1 Ryosuke Niwa 2021-06-08 17:12:45 PDT
Reproduced with non-ASAN release build of WebKitTestRunner at r278627.
Comment 2 Rob Buis 2021-06-09 01:29:20 PDT
Created attachment 430946 [details]
Patch
Comment 3 youenn fablet 2021-06-09 01:51:59 PDT
Comment on attachment 430946 [details]
Patch

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

> Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp:612
> +        promise.reject(InvalidStateError);

I would go with something like:
auto* page = document.page();
if (!page) {
    promise.reject(InvalidStateError);
    return;
}
LibWebRTCCertificateGenerator::generateCertificate(...);

> LayoutTests/ChangeLog:8
> +        Add test for this.

Comment not really needed

> LayoutTests/webrtc/RTCPeerConnection-generateCertificate-crash.html:7
> +        await RTCPeerConnection.generateCertificate({

We can probably have a simpler test using an iframe that we detached before calling generateCertificate, something like:

promise_test(async (t) => {
  const iframe = await with_iframe('/'); //requires http.
  const pc = iframe.contentWindow.RTCPeerConnection;
  iframe.remove();
  return promise_rejects(... pc.generateCertificate...)
});
Comment 4 Rob Buis 2021-06-09 02:53:20 PDT
Created attachment 430949 [details]
Patch
Comment 5 Rob Buis 2021-06-09 02:54:14 PDT
Comment on attachment 430946 [details]
Patch

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

>> Source/WebCore/Modules/mediastream/PeerConnectionBackend.cpp:612
>> +        promise.reject(InvalidStateError);
> 
> I would go with something like:
> auto* page = document.page();
> if (!page) {
>     promise.reject(InvalidStateError);
>     return;
> }
> LibWebRTCCertificateGenerator::generateCertificate(...);

Sure, done.

>> LayoutTests/ChangeLog:8
>> +        Add test for this.
> 
> Comment not really needed

Removed.

>> LayoutTests/webrtc/RTCPeerConnection-generateCertificate-crash.html:7
>> +        await RTCPeerConnection.generateCertificate({
> 
> We can probably have a simpler test using an iframe that we detached before calling generateCertificate, something like:
> 
> promise_test(async (t) => {
>   const iframe = await with_iframe('/'); //requires http.
>   const pc = iframe.contentWindow.RTCPeerConnection;
>   iframe.remove();
>   return promise_rejects(... pc.generateCertificate...)
> });

Nice! Done.
Comment 6 youenn fablet 2021-06-09 02:55:54 PDT
Comment on attachment 430949 [details]
Patch

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

> LayoutTests/http/wpt/webrtc/RTCPeerConnection-generateCertificate-crash.html:31
> +  return promise_rejects(pc.generateCertificate({ name: 'ECDSA', namedCurve: 'P-256'}));

promise_rejects_js is directly available in testharness.js
Comment 7 Rob Buis 2021-06-09 03:14:24 PDT
Comment on attachment 430949 [details]
Patch

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

>> LayoutTests/http/wpt/webrtc/RTCPeerConnection-generateCertificate-crash.html:31
>> +  return promise_rejects(pc.generateCertificate({ name: 'ECDSA', namedCurve: 'P-256'}));
> 
> promise_rejects_js is directly available in testharness.js

Sadly that does not work as InvalidStateError is not exposed to JS (like TypeError etc.).
Comment 8 EWS 2021-06-09 05:00:25 PDT
ChangeLog entry in LayoutTests/ChangeLog contains OOPS!.
Comment 9 Rob Buis 2021-06-09 05:18:55 PDT
Created attachment 430954 [details]
Patch
Comment 10 EWS 2021-06-09 10:58:53 PDT
Found 1 new test failure: imported/w3c/web-platform-tests/navigation-timing/nav2_test_attributes_values.html
Comment 11 Rob Buis 2021-06-09 19:58:02 PDT
Created attachment 431045 [details]
Patch
Comment 12 EWS 2021-06-09 21:53:03 PDT
Committed r278692 (238666@main): <https://commits.webkit.org/238666@main>

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