[gjs/gnome-3-24] object: Avoid taking address of empty vector



commit 5084c5442d3ffde9eed055789bcb46557030658a
Author: Philip Chimento <philip chimento gmail com>
Date:   Tue Aug 29 23:20:41 2017 -0700

    object: Avoid taking address of empty vector
    
    Given a std::vector<T> vec, &vec[0] is undefined behaviour when the
    vector is empty. C++11 provides a vec.data() method which does the same
    thing safely.
    
    This is an opportunity for a small refactor; the free function didn't
    actually free the vector, so it should be renamed "clear", and it can
    just take in the vector instead of a pointer to the data. We can also
    keep all the memory management of the vector in the same place, in
    object_instance_init().
    
    https://bugzilla.gnome.org/show_bug.cgi?id=786995

 gi/object.cpp |   44 ++++++++++++++++++--------------------------
 1 files changed, 18 insertions(+), 26 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index 6722cfe..15362fa 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -855,19 +855,10 @@ object_instance_resolve(JSContext       *context,
     return true;
 }
 
-static void
-free_g_params(GParameter *params,
-              int         n_params)
-{
-    int i;
-
-    for (i = 0; i < n_params; ++i) {
-        g_value_unset(&params[i].value);
-    }
-}
-
 /* Set properties from args to constructor (argv[0] is supposed to be
  * a hash)
+ * The GParameter elements in the passed-in vector must be unset by the caller,
+ * regardless of the return value of this function.
  */
 static bool
 object_instance_props_to_g_parameters(JSContext                  *context,
@@ -883,7 +874,6 @@ object_instance_props_to_g_parameters(JSContext                  *context,
 
     if (!args[0].isObject()) {
         gjs_throw(context, "argument should be a hash with props to set");
-        free_g_params(&gparams[0], gparams.size());
         return false;
     }
 
@@ -893,7 +883,7 @@ object_instance_props_to_g_parameters(JSContext                  *context,
     JS::RootedValue value(context);
     if (!ids) {
         gjs_throw(context, "Failed to create property iterator for object props hash");
-        goto free_array_and_fail;
+        return false;
     }
 
     for (ix = 0, length = ids.length(); ix < length; ix++) {
@@ -904,12 +894,10 @@ object_instance_props_to_g_parameters(JSContext                  *context,
          * doesn't know that */
         prop_id = ids[ix];
 
-        if (!gjs_object_require_property(context, props, "property list", prop_id, &value)) {
-            goto free_array_and_fail;
-        }
-
-        if (!gjs_get_string_id(context, prop_id, &name))
-            goto free_array_and_fail;
+        if (!gjs_object_require_property(context, props, "property list",
+                                         prop_id, &value) ||
+            !gjs_get_string_id(context, prop_id, &name))
+            return false;
 
         switch (init_g_param_from_property(context, name,
                                            value,
@@ -922,7 +910,7 @@ object_instance_props_to_g_parameters(JSContext                  *context,
             /* fallthrough */
         case SOME_ERROR_OCCURRED:
             g_free(name);
-            goto free_array_and_fail;
+            return false;
         case VALUE_WAS_SET:
         default:
             break;
@@ -934,10 +922,6 @@ object_instance_props_to_g_parameters(JSContext                  *context,
     }
 
     return true;
-
- free_array_and_fail:
-    free_g_params(&gparams[0], gparams.size());
-    return false;
 }
 
 #define DEBUG_DISPOSE 0
@@ -1438,6 +1422,13 @@ disassociate_js_gobject(GObject *gobj)
     priv->js_object_finalized = true;
 }
 
+static void
+clear_g_params(std::vector<GParameter>& params)
+{
+    for (GParameter param : params)
+        g_value_unset(&param.value);
+}
+
 static bool
 object_instance_init (JSContext                  *context,
                       JS::MutableHandleObject     object,
@@ -1456,6 +1447,7 @@ object_instance_init (JSContext                  *context,
 
     if (!object_instance_props_to_g_parameters(context, object, args,
                                                gtype, params)) {
+        clear_g_params(params);
         return false;
     }
 
@@ -1468,10 +1460,10 @@ object_instance_init (JSContext                  *context,
     }
 
 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
-    gobj = (GObject*) g_object_newv(gtype, params.size(), &params[0]);
+    gobj = (GObject*) g_object_newv(gtype, params.size(), params.data());
 G_GNUC_END_IGNORE_DEPRECATIONS
 
-    free_g_params(&params[0], params.size());
+    clear_g_params(params);
 
     ObjectInstance *other_priv = get_object_qdata(gobj);
     if (other_priv && other_priv->keep_alive != object) {


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