Title: [275031] trunk
Revision
275031
Author
[email protected]
Date
2021-03-25 07:34:25 -0700 (Thu, 25 Mar 2021)

Log Message

[GTK][WPE] JSC crashes if a function expects a parameter but doesn't receive any
https://bugs.webkit.org/show_bug.cgi?id=223646

Reviewed by Adrian Perez de Castro.

Source/_javascript_Core:

Handle the case of receiving fewer argumens than expected in function calls and constructors. We pass undefined
for the expected arguments that are missing. We were not correctly handling the case of converting undefined and
null values to JSCValue, so this patch fixes that case too.

* API/glib/JSCCallbackFunction.cpp:
(JSC::JSCCallbackFunction::call):
(JSC::JSCCallbackFunction::construct):
* API/glib/JSCContext.cpp:
(jscContextJSValueToWrappedObject):
(jscContextJSValueToGValue):

Tools:

Add test cases.

* TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
(valueToString):
(testJSCFunction):
(testJSCClass):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.cpp (275030 => 275031)


--- trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.cpp	2021-03-25 14:07:29 UTC (rev 275030)
+++ trunk/Source/_javascript_Core/API/glib/JSCCallbackFunction.cpp	2021-03-25 14:34:25 UTC (rev 275031)
@@ -113,7 +113,7 @@
     // GClosure always expect to have at least the instance parameter.
     bool addInstance = instance || (m_parameters && m_parameters->isEmpty());
 
-    auto parameterCount = m_parameters ? std::min(m_parameters->size(), argumentCount) : 1;
+    auto parameterCount = m_parameters ? m_parameters->size() : 1;
     if (addInstance)
         parameterCount++;
     auto* values = static_cast<GValue*>(g_alloca(sizeof(GValue) * parameterCount));
@@ -126,8 +126,11 @@
         firstParameter = 1;
     }
     if (m_parameters) {
-        for (size_t i = firstParameter; i < parameterCount && !*exception; ++i)
-            jscContextJSValueToGValue(context.get(), arguments[i - firstParameter], m_parameters.value()[i - firstParameter], &values[i], exception);
+        for (size_t i = firstParameter; i < parameterCount && !*exception; ++i) {
+            auto argumentIndex = i - firstParameter;
+            jscContextJSValueToGValue(context.get(), argumentIndex < argumentCount ? arguments[argumentIndex] : JSValueMakeUndefined(jsContext),
+                m_parameters.value()[argumentIndex], &values[i], exception);
+        }
     } else {
         auto* parameters = g_ptr_array_new_full(argumentCount, g_object_unref);
         for (size_t i = 0; i < argumentCount; ++i)
@@ -182,13 +185,13 @@
         g_closure_invoke(m_closure.get(), &returnValue, 1, &dummyValue, nullptr);
         g_value_unset(&dummyValue);
     } else {
-        auto parameterCount = m_parameters ? std::min(m_parameters->size(), argumentCount) : 1;
+        auto parameterCount = m_parameters ? m_parameters->size() : 1;
         auto* values = static_cast<GValue*>(g_alloca(sizeof(GValue) * parameterCount));
         memset(values, 0, sizeof(GValue) * parameterCount);
 
         if (m_parameters) {
             for (size_t i = 0; i < parameterCount && !*exception; ++i)
-                jscContextJSValueToGValue(context.get(), arguments[i], m_parameters.value()[i], &values[i], exception);
+                jscContextJSValueToGValue(context.get(), i < argumentCount ? arguments[i] : JSValueMakeUndefined(jsContext), m_parameters.value()[i], &values[i], exception);
         } else {
             auto* parameters = g_ptr_array_new_full(argumentCount, g_object_unref);
             for (size_t i = 0; i < argumentCount; ++i)

Modified: trunk/Source/_javascript_Core/API/glib/JSCContext.cpp (275030 => 275031)


--- trunk/Source/_javascript_Core/API/glib/JSCContext.cpp	2021-03-25 14:07:29 UTC (rev 275030)
+++ trunk/Source/_javascript_Core/API/glib/JSCContext.cpp	2021-03-25 14:34:25 UTC (rev 275031)
@@ -462,6 +462,12 @@
     return JSValueMakeUndefined(priv->jsContext.get());
 }
 
+static inline gpointer jscContextJSValueToWrappedObject(JSCContext* context, JSValueRef jsValue)
+{
+    auto jsObject = JSValueToObject(context->priv->jsContext.get(), jsValue, nullptr);
+    return jsObject ? jscContextWrappedObject(context, jsObject) : nullptr;
+}
+
 void jscContextJSValueToGValue(JSCContext* context, JSValueRef jsValue, GType type, GValue* value, JSValueRef* exception)
 {
     JSCContextPrivate* priv = context->priv;
@@ -472,7 +478,7 @@
     auto fundamentalType = g_type_fundamental(G_VALUE_TYPE(value));
     switch (fundamentalType) {
     case G_TYPE_INT:
-        g_value_set_int(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
+        g_value_set_int(value, JSC::toInt32(JSValueToNumber(priv->jsContext.get(), jsValue, exception)));
         break;
     case G_TYPE_FLOAT:
         g_value_set_float(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
@@ -496,56 +502,50 @@
             g_value_set_string(value, nullptr);
         break;
     case G_TYPE_CHAR:
-        g_value_set_schar(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
+        g_value_set_schar(value, JSC::toInt32(JSValueToNumber(priv->jsContext.get(), jsValue, exception)));
         break;
     case G_TYPE_UCHAR:
-        g_value_set_uchar(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
+        g_value_set_uchar(value, JSC::toUInt32(JSValueToNumber(priv->jsContext.get(), jsValue, exception)));
         break;
     case G_TYPE_UINT:
-        g_value_set_uint(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
+        g_value_set_uint(value, JSC::toUInt32(JSValueToNumber(priv->jsContext.get(), jsValue, exception)));
         break;
     case G_TYPE_POINTER:
     case G_TYPE_OBJECT:
     case G_TYPE_BOXED: {
-        gpointer wrappedObject = nullptr;
+        gpointer wrappedObject = jscContextJSValueToWrappedObject(context, jsValue);
 
-        if (!JSValueIsNull(priv->jsContext.get(), jsValue)) {
-            auto jsObject = JSValueToObject(priv->jsContext.get(), jsValue, exception);
-            if (*exception)
+        if (!wrappedObject) {
+            if (g_type_is_a(G_VALUE_TYPE(value), JSC_TYPE_VALUE)) {
+                auto jscValue = jscContextGetOrCreateValue(context, jsValue);
+                g_value_set_object(value, jscValue.get());
                 return;
+            }
 
-            wrappedObject = jscContextWrappedObject(context, jsObject);
-            if (!wrappedObject) {
-                if (g_type_is_a(G_VALUE_TYPE(value), JSC_TYPE_VALUE)) {
-                    auto jscValue = jscContextGetOrCreateValue(context, jsValue);
-                    g_value_set_object(value, jscValue.get());
-                    return;
-                }
+            if (g_type_is_a(G_VALUE_TYPE(value), JSC_TYPE_EXCEPTION)) {
+                auto exception = jscExceptionCreate(context, jsValue);
+                g_value_set_object(value, exception.get());
+                return;
+            }
 
-                if (g_type_is_a(G_VALUE_TYPE(value), JSC_TYPE_EXCEPTION)) {
-                    auto exception = jscExceptionCreate(context, jsValue);
-                    g_value_set_object(value, exception.get());
-                    return;
-                }
+            if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_PTR_ARRAY)) {
+                auto gArray = jscContextJSArrayToGArray(context, jsValue, exception);
+                if (!*exception)
+                    g_value_take_boxed(value, gArray.leakRef());
+                return;
+            }
 
-                if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_PTR_ARRAY)) {
-                    auto gArray = jscContextJSArrayToGArray(context, jsValue, exception);
-                    if (!*exception)
-                        g_value_take_boxed(value, gArray.leakRef());
-                    return;
-                }
-
-                if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_STRV)) {
-                    auto strv = jscContextJSArrayToGStrv(context, jsValue, exception);
-                    if (!*exception)
-                        g_value_take_boxed(value, strv.release());
-                    return;
-                }
-
-                *exception = toRef(JSC::createTypeError(globalObject, "invalid pointer type"_s));
+            if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_STRV)) {
+                auto strv = jscContextJSArrayToGStrv(context, jsValue, exception);
+                if (!*exception)
+                    g_value_take_boxed(value, strv.release());
                 return;
             }
+
+            *exception = toRef(JSC::createTypeError(globalObject, "invalid pointer type"_s));
+            return;
         }
+
         if (fundamentalType == G_TYPE_POINTER)
             g_value_set_pointer(value, wrappedObject);
         else if (fundamentalType == G_TYPE_BOXED)
@@ -569,10 +569,10 @@
         g_value_set_uint64(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
         break;
     case G_TYPE_ENUM:
-        g_value_set_enum(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
+        g_value_set_enum(value, JSC::toInt32(JSValueToNumber(priv->jsContext.get(), jsValue, exception)));
         break;
     case G_TYPE_FLAGS:
-        g_value_set_flags(value, JSValueToNumber(priv->jsContext.get(), jsValue, exception));
+        g_value_set_flags(value, JSC::toInt32(JSValueToNumber(priv->jsContext.get(), jsValue, exception)));
         break;
     case G_TYPE_PARAM:
     case G_TYPE_INTERFACE:

Modified: trunk/Source/_javascript_Core/ChangeLog (275030 => 275031)


--- trunk/Source/_javascript_Core/ChangeLog	2021-03-25 14:07:29 UTC (rev 275030)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-03-25 14:34:25 UTC (rev 275031)
@@ -1,3 +1,21 @@
+2021-03-25  Carlos Garcia Campos  <[email protected]>
+
+        [GTK][WPE] JSC crashes if a function expects a parameter but doesn't receive any
+        https://bugs.webkit.org/show_bug.cgi?id=223646
+
+        Reviewed by Adrian Perez de Castro.
+
+        Handle the case of receiving fewer argumens than expected in function calls and constructors. We pass undefined
+        for the expected arguments that are missing. We were not correctly handling the case of converting undefined and
+        null values to JSCValue, so this patch fixes that case too.
+
+        * API/glib/JSCCallbackFunction.cpp:
+        (JSC::JSCCallbackFunction::call):
+        (JSC::JSCCallbackFunction::construct):
+        * API/glib/JSCContext.cpp:
+        (jscContextJSValueToWrappedObject):
+        (jscContextJSValueToGValue):
+
 2021-03-24  Michael Saboff  <[email protected]>
 
         [YARR] Interpreter incorrectly matches non-BMP characters with multiple . w/dotAll flag

Modified: trunk/Tools/ChangeLog (275030 => 275031)


--- trunk/Tools/ChangeLog	2021-03-25 14:07:29 UTC (rev 275030)
+++ trunk/Tools/ChangeLog	2021-03-25 14:34:25 UTC (rev 275031)
@@ -1,3 +1,17 @@
+2021-03-25  Carlos Garcia Campos  <[email protected]>
+
+        [GTK][WPE] JSC crashes if a function expects a parameter but doesn't receive any
+        https://bugs.webkit.org/show_bug.cgi?id=223646
+
+        Reviewed by Adrian Perez de Castro.
+
+        Add test cases.
+
+        * TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp:
+        (valueToString):
+        (testJSCFunction):
+        (testJSCClass):
+
 2021-03-25  Aakash Jain  <[email protected]>
 
         [ews] Add unit-test to ensure that config.json doesn't have tab characters

Modified: trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp (275030 => 275031)


--- trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2021-03-25 14:07:29 UTC (rev 275030)
+++ trunk/Tools/TestWebKitAPI/Tests/_javascript_Core/glib/TestJSC.cpp	2021-03-25 14:34:25 UTC (rev 275031)
@@ -854,6 +854,11 @@
     return G_IS_FILE(file);
 }
 
+static char* valueToString(JSCValue* value)
+{
+    return jsc_value_to_string(value);
+}
+
 static void testJSCFunction()
 {
     {
@@ -1123,6 +1128,47 @@
         g_assert_true(jsc_value_is_boolean(value.get()));
         g_assert_true(jsc_value_to_boolean(value.get()));
     }
+
+    {
+        LeakChecker checker;
+        GRefPtr<JSCContext> context = adoptGRef(jsc_context_new());
+        checker.watch(context.get());
+        ExceptionHandler exceptionHandler(context.get());
+
+        GRefPtr<JSCValue> function = adoptGRef(jsc_value_new_function(context.get(), "valueToString", G_CALLBACK(valueToString), nullptr, nullptr, G_TYPE_STRING, 1, JSC_TYPE_VALUE));
+        checker.watch(function.get());
+        jsc_context_set_value(context.get(), "valueToString", function.get());
+
+        GRefPtr<JSCValue> value = adoptGRef(jsc_context_evaluate(context.get(), "valueToString(4)", -1));
+        checker.watch(value.get());
+        GUniquePtr<char> valueString(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "4");
+
+        value = adoptGRef(jsc_context_evaluate(context.get(), "valueToString('Hello World')", -1));
+        checker.watch(value.get());
+        valueString.reset(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "Hello World");
+
+        value = adoptGRef(jsc_context_evaluate(context.get(), "valueToString(undefined)", -1));
+        checker.watch(value.get());
+        valueString.reset(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "undefined");
+
+        value = adoptGRef(jsc_context_evaluate(context.get(), "valueToString(null)", -1));
+        checker.watch(value.get());
+        valueString.reset(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "null");
+
+        value = adoptGRef(jsc_context_evaluate(context.get(), "valueToString()", -1));
+        checker.watch(value.get());
+        valueString.reset(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "undefined");
+
+        value = adoptGRef(jsc_context_evaluate(context.get(), "valueToString(1,2,3)", -1));
+        checker.watch(value.get());
+        valueString.reset(jsc_value_to_string(value.get()));
+        g_assert_cmpstr(valueString.get(), ==, "1");
+    }
 }
 
 static void testJSCObject()
@@ -1813,6 +1859,14 @@
         g_assert_true(jsc_value_is_number(value.get()));
         g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 52);
 
+        foo2 = adoptGRef(jsc_context_evaluate(context.get(), "f2 = new Foo.CreateWithFoo();", -1));
+        checker.watch(foo2.get());
+        g_assert_true(jsc_value_is_object(foo2.get()));
+        value = adoptGRef(jsc_context_evaluate(context.get(), "f2.foo", -1));
+        checker.watch(value.get());
+        g_assert_true(jsc_value_is_number(value.get()));
+        g_assert_cmpint(jsc_value_to_int32(value.get()), ==, 0);
+
         GRefPtr<JSCValue> constructorV = adoptGRef(jsc_class_add_constructor_variadic(jscClass, "CreateWithFoo", G_CALLBACK(fooCreateWithFooV), nullptr, nullptr, G_TYPE_POINTER));
         checker.watch(constructorV.get());
         g_assert_true(jsc_value_is_constructor(constructorV.get()));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to