summaryrefslogtreecommitdiff
path: root/gi/pygi-marshal-cleanup.c
diff options
context:
space:
mode:
authorMikkel Kamstrup Erlandsen <mikkel.kamstrup@canonical.com>2011-10-04 12:28:26 +0200
committerMartin Pitt <martin.pitt@ubuntu.com>2011-10-25 08:46:05 +0200
commitc7aa0e79dfb4c1092c51ae1464b8414083b4f3fc (patch)
tree4617138680e0fa52abfb207da62a25973adbb20c /gi/pygi-marshal-cleanup.c
parentc2ec4d8eb46ae2e6ee4372b2a4f9d5df0e5d82f3 (diff)
downloadpygobject-c7aa0e79dfb4c1092c51ae1464b8414083b4f3fc.tar.gz
fix marshaling of arrays of GVariants
Add unit tests for marshaling of arrays of variants with all transfer modes. Requires latest gobject-introspection. Plug potential leaks of GArray data members Fix calling of wrong cleanup_from_py for arrays Simplify and fix logic for cleaning up arrays both in from_py() and to_py() code paths. https://bugzilla.gnome.org/show_bug.cgi?id=638915 Signed-off-by: Martin Pitt <martin.pitt@ubuntu.com>
Diffstat (limited to 'gi/pygi-marshal-cleanup.c')
-rw-r--r--gi/pygi-marshal-cleanup.c81
1 files changed, 52 insertions, 29 deletions
diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c
index 8ed9bdb2..f80ebfa2 100644
--- a/gi/pygi-marshal-cleanup.c
+++ b/gi/pygi-marshal-cleanup.c
@@ -273,6 +273,37 @@ _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
data);
}
+static GArray*
+_wrap_c_array (PyGIInvokeState *state,
+ PyGISequenceCache *sequence_cache,
+ gpointer data)
+{
+ GArray *array_;
+ gsize len;
+
+ if (sequence_cache->fixed_size >= 0) {
+ len = sequence_cache->fixed_size;
+ } else if (sequence_cache->is_zero_terminated) {
+ len = g_strv_length ((gchar **)data);
+ } else {
+ GIArgument *len_arg = state->args[sequence_cache->len_arg_index];
+ len = len_arg->v_long;
+ }
+
+ array_ = g_array_new (FALSE,
+ FALSE,
+ sequence_cache->item_size);
+
+ if (array_ == NULL)
+ return NULL;
+
+ g_free (array_->data);
+ array_->data = data;
+ array_->len = len;
+
+ return array_;
+}
+
void
_pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
@@ -286,26 +317,11 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
/* If this isn't a garray create one to help process variable sized
array elements */
if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- gsize len;
- if (sequence_cache->fixed_size >= 0) {
- len = sequence_cache->fixed_size;
- } else if (sequence_cache->is_zero_terminated) {
- len = g_strv_length ((gchar **)data);
- } else {
- GIArgument *len_arg = state->args[sequence_cache->len_arg_index];
- len = len_arg->v_long;
- }
-
- array_ = g_array_new (FALSE,
- FALSE,
- sequence_cache->item_size);
-
+ array_ = _wrap_c_array (state, sequence_cache, data);
+
if (array_ == NULL)
return;
-
- array_->data = data;
- array_->len = len;
-
+
} else {
array_ = (GArray *) data;
}
@@ -324,12 +340,12 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
}
}
- if (state->failed ||
- arg_cache->transfer == GI_TRANSFER_NOTHING ||
- arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+ /* Only free the array when we didn't transfer ownership */
+ if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
+ g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
+ } else if (state->failed ||
+ arg_cache->transfer == GI_TRANSFER_NOTHING) {
g_array_free (array_, TRUE);
- } else if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- g_array_free (array_, FALSE);
}
}
}
@@ -343,12 +359,20 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
- arg_cache->transfer == GI_TRANSFER_CONTAINER) {
- GArray *array_ = (GArray *) data;
+ arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+ GArray *array_;
+ PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
+ /* If this isn't a garray create one to help process variable sized
+ array elements */
if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
- g_free (data);
- return;
+ array_ = _wrap_c_array (state, sequence_cache, data);
+
+ if (array_ == NULL)
+ return;
+
+ } else {
+ array_ = (GArray *) data;
}
if (sequence_cache->item_cache->to_py_cleanup != NULL) {
@@ -363,8 +387,7 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
}
}
- if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
- g_array_free (array_, TRUE);
+ g_array_free (array_, TRUE);
}
}