[gjs/gnome-3-38] function: Early-initialize arguments cache or we won't ever release them



commit e85fb9059d45c43ea621e036986e6488ef3f30e2
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Mon Sep 7 19:42:49 2020 +0200

    function: Early-initialize arguments cache or we won't ever release them
    
    If we throw during the arguments cache creation as we fail during an early
    stage of init_cached_function_data, we don't save the function GICallableInfo
    or the already allocated parameters, but we'd just return loosing
    track of allocated data.
    
    This is not just a potential leak, but also wrong as if a method
    introspection is malformed or not fully supported by gjs, we'd just
    assert crashing badly during function unallocation because no function
    info is set, instead of just throwing as expected.
    
    As per this, let's save the function private informations (such as the
    callable info and the arguments cache) as soon as we allocate them,
    and update the number of initialized arguments in real time, so that
    we can partially de-allocate the arguments cache in case of errors.
    This also implies that during function de-init we must ensure that
    we don't overflow using the marshallers pointer to check if we've ever
    initialized such argument cache and to figure out how many we've allocated
    other than of the total number of the introspected function arguments.

 gi/function.cpp | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)
---
diff --git a/gi/function.cpp b/gi/function.cpp
index 1b065b598..68919a597 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -1066,8 +1066,15 @@ uninit_cached_function_data (Function *function)
         // Careful! function->arguments is offset by one or two elements inside
         // the allocated space, so we have to free index -1 or -2.
         int start_index = g_callable_info_is_method(function->info) ? -2 : -1;
-        int gi_argc = g_callable_info_get_n_args(function->info);
-        for (int ix = start_index; ix < gi_argc; ix++) {
+        int gi_argc = MIN(g_callable_info_get_n_args(function->info),
+                          function->js_in_argc + function->js_out_argc);
+
+        for (int i = 0; i < gi_argc; i++) {
+            int ix = start_index + i;
+
+            if (!function->arguments[ix].marshallers)
+                break;
+
             if (function->arguments[ix].marshallers->free)
                 function->arguments[ix].marshallers->free(
                     &function->arguments[ix]);
@@ -1242,6 +1249,11 @@ init_cached_function_data (JSContext      *context,
     GjsArgumentCache* arguments =
         g_new0(GjsArgumentCache, n_args + offset) + offset;
 
+    function->arguments = arguments;
+    function->info = g_base_info_ref(info);
+    function->js_in_argc = 0;
+    function->js_out_argc = 0;
+
     if (is_method &&
         !gjs_arg_cache_build_instance(context, &arguments[-2], info))
         return false;
@@ -1251,8 +1263,7 @@ init_cached_function_data (JSContext      *context,
                                     &inc_counter))
         return false;
 
-    int out_argc = inc_counter ? 1 : 0;
-    int in_argc = 0;
+    function->js_out_argc = inc_counter ? 1 : 0;
 
     for (i = 0; i < n_args; i++) {
         GIDirection direction;
@@ -1271,13 +1282,13 @@ init_cached_function_data (JSContext      *context,
         if (inc_counter) {
             switch (direction) {
                 case GI_DIRECTION_INOUT:
-                    out_argc++;
+                    function->js_out_argc++;
                     [[fallthrough]];
                 case GI_DIRECTION_IN:
-                    in_argc++;
+                    function->js_in_argc++;
                     break;
                 case GI_DIRECTION_OUT:
-                    out_argc++;
+                    function->js_out_argc++;
                     break;
                 default:
                     g_assert_not_reached();
@@ -1285,14 +1296,6 @@ init_cached_function_data (JSContext      *context,
         }
     }
 
-    function->arguments = arguments;
-
-    function->js_in_argc = in_argc;
-    function->js_out_argc = out_argc;
-    function->info = info;
-
-    g_base_info_ref((GIBaseInfo*) function->info);
-
     return true;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]