[pygobject] Fix stack smasher when marshaling enums as a vfunc return value
- From: Simon Feltman <sfeltman src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Fix stack smasher when marshaling enums as a vfunc return value
- Date: Mon, 18 Mar 2013 08:32:09 +0000 (UTC)
commit a0844a896603c5c91bed24cf94106765f0ced74e
Author: Simon Feltman <sfeltman src gnome org>
Date: Sun Mar 17 23:22:38 2013 -0700
Fix stack smasher when marshaling enums as a vfunc return value
Add special case for marshaling GI_TYPE_TAG_INTERFACE with enum or
flag types. Default interfaces to marshal as a pointer.
Add explicit cases for GType and Unichar out/return marshaling.
Fix leaking of GIBaseInfo when marshaling interface as out arg.
https://bugzilla.gnome.org/show_bug.cgi?id=637832
gi/pygi-closure.c | 69 ++++++++++++++++++++++++++++++++++++++++++++--------
tests/test_gi.py | 19 ++++++++++++++
2 files changed, 77 insertions(+), 11 deletions(-)
---
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index f49f8e2..e70fd86 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -72,9 +72,37 @@ _pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
case GI_TYPE_TAG_DOUBLE:
*((gdouble *) retval) = arg.v_double;
break;
- default:
- *((GIArgument *) retval) = arg;
+ case GI_TYPE_TAG_GTYPE:
+ *((ffi_arg *) retval) = arg.v_ulong;
break;
+ case GI_TYPE_TAG_UNICHAR:
+ *((ffi_arg *) retval) = arg.v_uint32;
+ break;
+ case GI_TYPE_TAG_INTERFACE:
+ {
+ GIBaseInfo* interface_info;
+ GIInfoType interface_type;
+
+ interface_info = g_type_info_get_interface(type_info);
+ interface_type = g_base_info_get_type(interface_info);
+
+ switch (interface_type) {
+ case GI_INFO_TYPE_ENUM:
+ *(ffi_sarg *) retval = arg.v_int;
+ break;
+ case GI_INFO_TYPE_FLAGS:
+ *(ffi_arg *) retval = arg.v_uint;
+ break;
+ default:
+ *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
+ break;
+ }
+
+ g_base_info_unref (interface_info);
+ }
+ default:
+ *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
+ break;
}
}
@@ -123,6 +151,12 @@ _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
case GI_TYPE_TAG_DOUBLE:
*((gdouble *) out_arg) = arg.v_double;
break;
+ case GI_TYPE_TAG_GTYPE:
+ *((gulong *) out_arg) = arg.v_ulong;
+ break;
+ case GI_TYPE_TAG_UNICHAR:
+ *((guint32 *) out_arg) = arg.v_uint32;
+ break;
case GI_TYPE_TAG_INTERFACE:
{
GIBaseInfo *interface;
@@ -131,21 +165,34 @@ _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
interface = g_type_info_get_interface (type_info);
interface_type = g_base_info_get_type (interface);
- if (!g_type_info_is_pointer (type_info) &&
- interface_type == GI_INFO_TYPE_STRUCT) {
- if (object == Py_None) {
- arg.v_pointer = NULL;
- } else {
- gsize item_size = _pygi_g_type_info_size (type_info);
- memcpy (out_arg, arg.v_pointer, item_size);
+ switch (interface_type) {
+ case GI_INFO_TYPE_ENUM:
+ *(gint *) out_arg = arg.v_int;
+ break;
+ case GI_INFO_TYPE_FLAGS:
+ *(guint *) out_arg = arg.v_uint;
+ break;
+ case GI_INFO_TYPE_STRUCT:
+ if (!g_type_info_is_pointer (type_info)) {
+ if (object != Py_None) {
+ gsize item_size = _pygi_g_type_info_size (type_info);
+ memcpy (out_arg, arg.v_pointer, item_size);
+ }
+ break;
}
+
+ /* Fall through if pointer */
+ default:
+ *((gpointer *) out_arg) = arg.v_pointer;
break;
}
+
+ g_base_info_unref (interface);
+ break;
}
- /* Fall through */
default:
- *((GIArgument *) out_arg) = arg;
+ *((gpointer *) out_arg) = arg.v_pointer;
break;
}
}
diff --git a/tests/test_gi.py b/tests/test_gi.py
index e51d7cf..2671588 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1497,6 +1497,25 @@ class TestEnum(unittest.TestCase):
GIMarshallingTests.NoTypeFlags.__gtype__)
+ unittest skipUnless(hasattr(GIMarshallingTests.Object, 'vfunc_return_enum'),
+ 'GIMarshallingTests too old')
+class TestEnumVFuncResults(unittest.TestCase):
+ class EnumTester(GIMarshallingTests.Object):
+ def do_vfunc_return_enum(self):
+ return GIMarshallingTests.Enum.VALUE2
+
+ def do_vfunc_out_enum(self):
+ return GIMarshallingTests.Enum.VALUE3
+
+ def test_vfunc_return_enum(self):
+ tester = self.EnumTester()
+ self.assertEqual(tester.vfunc_return_enum(), GIMarshallingTests.Enum.VALUE2)
+
+ def test_vfunc_out_enum(self):
+ tester = self.EnumTester()
+ self.assertEqual(tester.vfunc_out_enum(), GIMarshallingTests.Enum.VALUE3)
+
+
class TestGEnum(unittest.TestCase):
def test_genum(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]