[pygobject] Fix unmarshalling of gssize



commit 266d37719bb54e6f04d23ff21bcceb9514e20ff2
Author: David Malcolm <dmalcolm redhat com>
Date:   Mon Aug 20 11:27:52 2012 +0200

    Fix unmarshalling of gssize
    
    Do not assume that the v_int union member always corresponds to a gssize. This
    is not true on big-endian 64 bit machines like ppc64, so add a new
    gi_argument_to_gssize() and use it properly.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=680693
    https://bugzilla.redhat.com/show_bug.cgi?id=842880

 gi/pygi-argument.c       |   53 +++++++++++++++++++++++++++++++++++++++++++--
 gi/pygi-argument.h       |    1 +
 gi/pygi-closure.c        |    2 +-
 gi/pygi-info.c           |    4 +-
 gi/pygi-signal-closure.c |    2 +-
 5 files changed, 55 insertions(+), 7 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index db97a86..b7cab1a 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -31,6 +31,44 @@
 #include <pyglib-python-compat.h>
 #include <pyglib.h>
 
+static gboolean
+gi_argument_to_gssize (GIArgument *arg_in,
+                       GITypeTag  type_tag,
+                       gssize *gssize_out)
+{
+    switch (type_tag) {
+      case GI_TYPE_TAG_INT8:
+          *gssize_out = arg_in->v_int8;
+          return TRUE;
+      case GI_TYPE_TAG_UINT8:
+          *gssize_out = arg_in->v_uint8;
+          return TRUE;
+      case GI_TYPE_TAG_INT16:
+          *gssize_out = arg_in->v_int16;
+          return TRUE;
+      case GI_TYPE_TAG_UINT16:
+          *gssize_out = arg_in->v_uint16;
+          return TRUE;
+      case GI_TYPE_TAG_INT32:
+          *gssize_out = arg_in->v_int32;
+          return TRUE;
+      case GI_TYPE_TAG_UINT32:
+          *gssize_out = arg_in->v_uint32;
+          return TRUE;
+      case GI_TYPE_TAG_INT64:
+          *gssize_out = arg_in->v_int64;
+          return TRUE;
+      case GI_TYPE_TAG_UINT64:
+          *gssize_out = arg_in->v_uint64;
+          return TRUE;
+      default:
+          PyErr_Format (PyExc_TypeError,
+                        "Unable to marshal %s to gssize",
+                        g_type_tag_to_string(type_tag));
+          return FALSE;
+    }
+}
+
 void
 _pygi_hash_pointer_to_arg (GIArgument *arg,
                            GITypeTag  type_tag)
@@ -708,6 +746,7 @@ check_number_release:
  * @arg: The argument to convert
  * @args: Arguments to method invocation, possibly contaning the array length.
  *        Set to NULL if this is not for a method call
+ * @callable_info: Info on the callable, if this a method call; otherwise NULL
  * @type_info: The type info for @arg
  * @out_free_array: A return location for a gboolean that indicates whether
  *                  or not the wrapped GArray should be freed
@@ -725,6 +764,7 @@ check_number_release:
 GArray *
 _pygi_argument_to_array (GIArgument  *arg,
                          GIArgument  *args[],
+                         GICallableInfo *callable_info,                  
                          GITypeInfo  *type_info,
                          gboolean    *out_free_array)
 {
@@ -762,12 +802,19 @@ _pygi_argument_to_array (GIArgument  *arg,
                         return g_array;
                     }
                     gint length_arg_pos;
+                    GIArgInfo *length_arg_info;
+                    GITypeInfo *length_type_info;
 
                     length_arg_pos = g_type_info_get_array_length (type_info);
                     g_assert (length_arg_pos >= 0);
-
-                    /* FIXME: Take into account the type of the length argument */
-                    length = args[length_arg_pos]->v_int;
+                    g_assert (callable_info);
+                    length_arg_info = g_callable_info_get_arg (callable_info, length_arg_pos);
+                    length_type_info = g_arg_info_get_type (length_arg_info);
+                    if (!gi_argument_to_gssize (args[length_arg_pos],
+                                                g_type_info_get_tag (length_type_info),
+                                                &length)) {
+                        return NULL;
+                    }
                 }
             }
 
diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h
index 32f263b..a1420ee 100644
--- a/gi/pygi-argument.h
+++ b/gi/pygi-argument.h
@@ -50,6 +50,7 @@ gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
 
 GArray* _pygi_argument_to_array (GIArgument  *arg,
                                  GIArgument  *args[],
+                                 GICallableInfo *callable_info,
                                  GITypeInfo  *type_info,
                                  gboolean    *out_free_array);
 
diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c
index bec0bc4..f6f5c51 100644
--- a/gi/pygi-closure.c
+++ b/gi/pygi-closure.c
@@ -351,7 +351,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
                 
                 if (g_type_info_get_tag (arg_type) == GI_TYPE_TAG_ARRAY)
                     arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, 
-                                                              arg_type, &free_array);
+                                                              callable_info, arg_type, &free_array);
 
                 value = _pygi_argument_to_object (arg, arg_type, transfer);
                 
diff --git a/gi/pygi-info.c b/gi/pygi-info.c
index 9f92cd3..3ca5c8f 100644
--- a/gi/pygi-info.c
+++ b/gi/pygi-info.c
@@ -1157,7 +1157,7 @@ _wrap_g_constant_info_get_value (PyGIBaseInfo *self)
     type_info = g_constant_info_get_type ( (GIConstantInfo *) self->info);
 
     if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) {
-        value.v_pointer = _pygi_argument_to_array (&value, NULL,
+        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
                                                    type_info, &free_array);
     }
 
@@ -1290,7 +1290,7 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self,
     }
 
     if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) {
-        value.v_pointer = _pygi_argument_to_array (&value, NULL,
+        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
                                                    field_type_info, &free_array);
     }
 
diff --git a/gi/pygi-signal-closure.c b/gi/pygi-signal-closure.c
index 4e9dcb5..83f9a41 100644
--- a/gi/pygi-signal-closure.c
+++ b/gi/pygi-signal-closure.c
@@ -154,7 +154,7 @@ pygi_signal_closure_marshal(GClosure *closure,
             arg = _pygi_argument_from_g_value(&param_values[i], &type_info);
             
             if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ARRAY) {
-                arg.v_pointer = _pygi_argument_to_array (&arg, NULL,
+                arg.v_pointer = _pygi_argument_to_array (&arg, NULL, NULL,
                                                          &type_info, &free_array);
             }
             



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