[pygobject] Fix leak of caller-allocated boxed values



commit 105e6738ee249b64904da26ae45dd273ca4eeba8
Author: Martin Pitt <martinpitt gnome org>
Date:   Thu Feb 28 11:43:47 2013 +0100

    Fix leak of caller-allocated boxed values
    
    Add a new "allocated_slice" argument to _pygi_boxed_new() which specifies
    whether its "boxed" pointer was allocated using a slice (by giving its size) or
    malloc (by specifying 0), as _pygi_boxed_new cannot determine that itself any
    more.
    
    Use this in _pygi_marshal_to_py_interface_struct() for caller-allocated boxed
    values, as _caller_alloc() uses _pygi_boxed_alloc() for those (i. e. slices),
    which would otherwise leak.
    
    Thanks to Mike Gorse <mgorse suse com> for the original patch!
    
    https://bugzilla.gnome.org/show_bug.cgi?id=691501

 gi/gimodule.c           |    2 +-
 gi/pygi-argument.c      |    2 +-
 gi/pygi-boxed.c         |   14 ++++++++++----
 gi/pygi-boxed.h         |    3 ++-
 gi/pygi-marshal-to-py.c |    6 ++++--
 gi/pygi-source.c        |    3 ++-
 6 files changed, 20 insertions(+), 10 deletions(-)
---
diff --git a/gi/gimodule.c b/gi/gimodule.c
index 23b4d9b..108fc77 100644
--- a/gi/gimodule.c
+++ b/gi/gimodule.c
@@ -513,7 +513,7 @@ _wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args)
 
     py_type = _pygi_type_import_by_name ("GLib", "VariantType");
 
-    py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE);
+    py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE, 0);
 
     return py_variant;
 }
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 8dd7842..df2c54d 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -1752,7 +1752,7 @@ _pygi_argument_to_object (GIArgument  *arg,
                         if (py_type == NULL)
                             break;
 
-                        object = _pygi_boxed_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == 
GI_TRANSFER_EVERYTHING);
+                        object = _pygi_boxed_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == 
GI_TRANSFER_EVERYTHING, 0);
 
                         Py_DECREF (py_type);
                     } else if (g_type_is_a (type, G_TYPE_POINTER)) {
diff --git a/gi/pygi-boxed.c b/gi/pygi-boxed.c
index c15c927..cac2b0d 100644
--- a/gi/pygi-boxed.c
+++ b/gi/pygi-boxed.c
@@ -104,7 +104,7 @@ _boxed_new (PyTypeObject *type,
         goto out;
     }
 
-    self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, TRUE);
+    self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, TRUE, size);
     if (self == NULL) {
         g_slice_free1 (size, boxed);
         goto out;
@@ -133,7 +133,8 @@ PYGLIB_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
 PyObject *
 _pygi_boxed_new (PyTypeObject *type,
                  gpointer      boxed,
-                 gboolean      free_on_dealloc)
+                 gboolean      free_on_dealloc,
+                 gsize         allocated_slice)
 {
     PyGIBoxed *self;
 
@@ -154,8 +155,13 @@ _pygi_boxed_new (PyTypeObject *type,
     ( (PyGBoxed *) self)->gtype = pyg_type_from_object ( (PyObject *) type);
     ( (PyGBoxed *) self)->boxed = boxed;
     ( (PyGBoxed *) self)->free_on_dealloc = free_on_dealloc;
-    self->size = 0;
-    self->slice_allocated = FALSE;
+    if (allocated_slice > 0) {
+        self->size = allocated_slice;
+        self->slice_allocated = TRUE;
+    } else {
+        self->size = 0;
+        self->slice_allocated = FALSE;
+    }
 
     return (PyObject *) self;
 }
diff --git a/gi/pygi-boxed.h b/gi/pygi-boxed.h
index a84ec4e..38ac928 100644
--- a/gi/pygi-boxed.h
+++ b/gi/pygi-boxed.h
@@ -30,7 +30,8 @@ extern PyTypeObject PyGIBoxed_Type;
 
 PyObject * _pygi_boxed_new (PyTypeObject *type,
                             gpointer      boxed,
-                            gboolean      free_on_dealloc);
+                            gboolean      free_on_dealloc,
+                            gsize         allocated_slice);
 
 void * _pygi_boxed_alloc (GIBaseInfo *info,
                           gsize *size);
diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c
index 661befc..693d2ea 100644
--- a/gi/pygi-marshal-to-py.c
+++ b/gi/pygi-marshal-to-py.c
@@ -814,8 +814,10 @@ _pygi_marshal_to_py_interface_struct (PyGIInvokeState   *state,
         py_obj = pygi_struct_foreign_convert_from_g_argument (iface_cache->interface_info,
                                                               arg->v_pointer);
     } else if (g_type_is_a (type, G_TYPE_BOXED)) {
-        py_obj = _pygi_boxed_new ( (PyTypeObject *)iface_cache->py_type, arg->v_pointer, 
-                                  arg_cache->transfer == GI_TRANSFER_EVERYTHING);
+        py_obj = _pygi_boxed_new ( (PyTypeObject *)iface_cache->py_type, arg->v_pointer,
+                                  arg_cache->transfer == GI_TRANSFER_EVERYTHING || 
arg_cache->is_caller_allocates,
+                                  arg_cache->is_caller_allocates ?
+                                          g_struct_info_get_size(iface_cache->interface_info) : 0);
     } else if (g_type_is_a (type, G_TYPE_POINTER)) {
         if (iface_cache->py_type == NULL ||
                 !PyType_IsSubtype ( (PyTypeObject *)iface_cache->py_type, &PyGIStruct_Type)) {
diff --git a/gi/pygi-source.c b/gi/pygi-source.c
index b713b73..66bbc3c 100644
--- a/gi/pygi-source.c
+++ b/gi/pygi-source.c
@@ -240,7 +240,8 @@ pyg_source_new (void)
     source = (PyGRealSource*) g_source_new (&pyg_source_funcs, sizeof (PyGRealSource));
 
     py_type = _pygi_type_import_by_name ("GLib", "Source");
-    source->obj = _pygi_boxed_new ( (PyTypeObject *) py_type, source, FALSE);
+    /* g_source_new uses malloc, not slices */
+    source->obj = _pygi_boxed_new ( (PyTypeObject *) py_type, source, FALSE, 0);
 
     return source->obj;
 }


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