Title: [228331] trunk
Revision
228331
Author
aes...@apple.com
Date
2018-02-09 11:07:28 -0800 (Fri, 09 Feb 2018)

Log Message

[Payment Request] Crash in PaymentRequest::canMakePayment() when Apple Pay payment method data is missing required fields
https://bugs.webkit.org/show_bug.cgi?id=182631

Reviewed by Mark Lam.

Source/WebCore:

PaymentRequest::canMakePayment() needs to parse each payment method's serialized data to
determine if it is a supported payment method. If parsing fails by raising an exception, we
intend to skip over that payment method and try the next one. If all payment method data
fail to parse, we resolve the returned promise with false. At no point do we intend to
propagate the parsing exception up to the calling script, however.

Even though we intend to swallow any exceptions from parsing, we failed to clear the
_javascript_ VM's exception state. The next time WebCore tries to execute _javascript_, a
release assertion is raised due to seeing an unexpected exception in the VM.

Fix this by using a CatchScope in PaymentRequest::canMakePayment(), and calling
CatchScope::clearException() in the places we intend to swallow exceptions.

Added a test case to http/tests/paymentrequest/payment-request-canmakepayment-method.https.html.

* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::canMakePayment):

LayoutTests:

* http/tests/paymentrequest/payment-request-canmakepayment-method.https-expected.txt:
* http/tests/paymentrequest/payment-request-canmakepayment-method.https.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (228330 => 228331)


--- trunk/LayoutTests/ChangeLog	2018-02-09 18:59:54 UTC (rev 228330)
+++ trunk/LayoutTests/ChangeLog	2018-02-09 19:07:28 UTC (rev 228331)
@@ -1,3 +1,13 @@
+2018-02-09  Andy Estes  <aes...@apple.com>
+
+        [Payment Request] Crash in PaymentRequest::canMakePayment() when Apple Pay payment method data is missing required fields
+        https://bugs.webkit.org/show_bug.cgi?id=182631
+
+        Reviewed by Mark Lam.
+
+        * http/tests/paymentrequest/payment-request-canmakepayment-method.https-expected.txt:
+        * http/tests/paymentrequest/payment-request-canmakepayment-method.https.html:
+
 2018-02-09  Ryan Haddad  <ryanhad...@apple.com>
 
         Update TestExpectations for fast/forms/textarea/textarea-state-restore.html

Modified: trunk/LayoutTests/http/tests/paymentrequest/payment-request-canmakepayment-method.https-expected.txt (228330 => 228331)


--- trunk/LayoutTests/http/tests/paymentrequest/payment-request-canmakepayment-method.https-expected.txt	2018-02-09 18:59:54 UTC (rev 228330)
+++ trunk/LayoutTests/http/tests/paymentrequest/payment-request-canmakepayment-method.https-expected.txt	2018-02-09 19:07:28 UTC (rev 228331)
@@ -3,6 +3,7 @@
 PASS If request.[[state]] is "interactive", then return a promise rejected with an "InvalidStateError" DOMException. 
 PASS If request.[[state]] is "closed", then return a promise rejected with an "InvalidStateError" DOMException. 
 PASS If payment method identifier and serialized parts are supported, resolve promise with true. 
+PASS If a payment method identifier is supported but its serialized parts are not, resolve promise with false. 
 PASS If payment method identifier is unknown, resolve promise with false. 
 PASS Optionally, at the user agent's discretion, return a promise rejected with a "NotAllowedError" DOMException. 
 

Modified: trunk/LayoutTests/http/tests/paymentrequest/payment-request-canmakepayment-method.https.html (228330 => 228331)


--- trunk/LayoutTests/http/tests/paymentrequest/payment-request-canmakepayment-method.https.html	2018-02-09 18:59:54 UTC (rev 228330)
+++ trunk/LayoutTests/http/tests/paymentrequest/payment-request-canmakepayment-method.https.html	2018-02-09 19:07:28 UTC (rev 228331)
@@ -10,7 +10,7 @@
 <script src=""
 <script src=""
 <script>
-    const applePay = Object.freeze({
+const applePay = Object.freeze({
     supportedMethods: "https://apple.com/apple-pay",
     data: {
         version: 2,
@@ -20,6 +20,11 @@
         countryCode: "US",
     }
 });
+const invalidApplePay = Object.freeze({
+    supportedMethods: "https://apple.com/apple-pay",
+    data: {
+    }
+});
 const defaultMethods = Object.freeze([applePay]);
 const defaultDetails = Object.freeze({
   total: {
@@ -98,6 +103,11 @@
 }, `If payment method identifier and serialized parts are supported, resolve promise with true.`);
 
 promise_test(async t => {
+  const request = new PaymentRequest([invalidApplePay], defaultDetails);
+  assert_false(await request.canMakePayment(), "Apple Pay with invalid data should not be supported");
+}, `If a payment method identifier is supported but its serialized parts are not, resolve promise with false.`);
+
+promise_test(async t => {
   const unsupportedMethods = [
     "this-is-not-supported",
     "https://not.supported",

Modified: trunk/Source/WebCore/ChangeLog (228330 => 228331)


--- trunk/Source/WebCore/ChangeLog	2018-02-09 18:59:54 UTC (rev 228330)
+++ trunk/Source/WebCore/ChangeLog	2018-02-09 19:07:28 UTC (rev 228331)
@@ -1,3 +1,28 @@
+2018-02-09  Andy Estes  <aes...@apple.com>
+
+        [Payment Request] Crash in PaymentRequest::canMakePayment() when Apple Pay payment method data is missing required fields
+        https://bugs.webkit.org/show_bug.cgi?id=182631
+
+        Reviewed by Mark Lam.
+
+        PaymentRequest::canMakePayment() needs to parse each payment method's serialized data to
+        determine if it is a supported payment method. If parsing fails by raising an exception, we
+        intend to skip over that payment method and try the next one. If all payment method data
+        fail to parse, we resolve the returned promise with false. At no point do we intend to
+        propagate the parsing exception up to the calling script, however.
+
+        Even though we intend to swallow any exceptions from parsing, we failed to clear the
+        _javascript_ VM's exception state. The next time WebCore tries to execute _javascript_, a
+        release assertion is raised due to seeing an unexpected exception in the VM.
+
+        Fix this by using a CatchScope in PaymentRequest::canMakePayment(), and calling
+        CatchScope::clearException() in the places we intend to swallow exceptions.
+
+        Added a test case to http/tests/paymentrequest/payment-request-canmakepayment-method.https.html.
+
+        * Modules/paymentrequest/PaymentRequest.cpp:
+        (WebCore::PaymentRequest::canMakePayment):
+
 2018-02-09  Zalan Bujtas  <za...@apple.com>
 
         [RenderTreeBuilder] Move multicolumn descendant/sibling removal logic to RenderTreeBuilder

Modified: trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp (228330 => 228331)


--- trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp	2018-02-09 18:59:54 UTC (rev 228330)
+++ trunk/Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp	2018-02-09 19:07:28 UTC (rev 228331)
@@ -489,10 +489,14 @@
         return;
     }
 
+    auto scope = DECLARE_CATCH_SCOPE(document.execState()->vm());
     for (auto& paymentMethod : m_serializedMethodData) {
         auto data = "" paymentMethod.serializedData);
-        if (data.hasException())
+        ASSERT(!!scope.exception() == data.hasException());
+        if (data.hasException()) {
+            scope.clearException();
             continue;
+        }
 
         auto handler = PaymentHandler::create(document, *this, paymentMethod.identifier);
         if (!handler)
@@ -499,8 +503,11 @@
             continue;
 
         auto exception = handler->convertData(data.releaseReturnValue());
-        if (exception.hasException())
+        ASSERT(!!scope.exception() == exception.hasException());
+        if (exception.hasException()) {
+            scope.clearException();
             continue;
+        }
 
         handler->canMakePayment([promise = WTFMove(promise)](bool canMakePayment) mutable {
             promise.resolve(canMakePayment);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to