Commit 1c5d497d authored by David Malcolm's avatar David Malcolm Committed by Martin Pitt
Browse files

Fix various endianess errors

Fix code which assumed little endian behaviour when mixing different types of
ints, putting ints into pointers, etc.

https://bugzilla.gnome.org/show_bug.cgi?id=680692
https://bugzilla.redhat.com/show_bug.cgi?id=841596
parent ee6da6f1
......@@ -31,6 +31,56 @@
#include <pyglib-python-compat.h>
#include <pyglib.h>
void
_pygi_hash_pointer_to_arg (GIArgument *arg,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
arg->v_int8 = GPOINTER_TO_INT (arg->v_pointer);
break;
case GI_TYPE_TAG_INT16:
arg->v_int16 = GPOINTER_TO_INT (arg->v_pointer);
break;
case GI_TYPE_TAG_INT32:
arg->v_int32 = GPOINTER_TO_INT (arg->v_pointer);
break;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_INTERFACE:
break;
default:
g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag));
}
}
gpointer
_pygi_arg_to_hash_pointer (const GIArgument *arg,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
return GINT_TO_POINTER (arg->v_int8);
case GI_TYPE_TAG_UINT8:
return GINT_TO_POINTER (arg->v_uint8);
case GI_TYPE_TAG_INT16:
return GINT_TO_POINTER (arg->v_int16);
case GI_TYPE_TAG_UINT16:
return GINT_TO_POINTER (arg->v_uint16);
case GI_TYPE_TAG_INT32:
return GINT_TO_POINTER (arg->v_int32);
case GI_TYPE_TAG_UINT32:
return GINT_TO_POINTER (arg->v_uint32);
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_INTERFACE:
return arg->v_pointer;
default:
g_critical ("Unsupported type %s", g_type_tag_to_string(type_tag));
return arg->v_pointer;
}
}
static void
_pygi_g_type_tag_py_bounds (GITypeTag type_tag,
PyObject **lower,
......@@ -1196,7 +1246,7 @@ array_success:
break;
}
arg.v_long = PYGLIB_PyLong_AsLong (int_);
arg.v_int = PYGLIB_PyLong_AsLong (int_);
Py_DECREF (int_);
......@@ -1369,7 +1419,8 @@ list_item_error:
goto hash_table_item_error;
}
g_hash_table_insert (hash_table, key.v_pointer, value.v_pointer);
g_hash_table_insert (hash_table, key.v_pointer,
_pygi_arg_to_hash_pointer (&value, g_type_info_get_tag (value_type_info)));
continue;
hash_table_item_error:
......@@ -1713,21 +1764,21 @@ _pygi_argument_to_object (GIArgument *arg,
return NULL;
py_args = PyTuple_New (1);
if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (arg->v_long)) != 0) {
if (PyTuple_SetItem (py_args, 0, PyLong_FromLong (arg->v_int)) != 0) {
Py_DECREF (py_args);
Py_DECREF (py_type);
return NULL;
}
object = PyObject_CallFunction (py_type, "l", arg->v_long);
object = PyObject_CallFunction (py_type, "i", arg->v_int);
Py_DECREF (py_args);
Py_DECREF (py_type);
} else if (info_type == GI_INFO_TYPE_ENUM) {
object = pyg_enum_from_gtype (type, arg->v_long);
object = pyg_enum_from_gtype (type, arg->v_int);
} else {
object = pyg_flags_from_gtype (type, arg->v_long);
object = pyg_flags_from_gtype (type, arg->v_int);
}
break;
......@@ -1840,6 +1891,7 @@ _pygi_argument_to_object (GIArgument *arg,
break;
}
_pygi_hash_pointer_to_arg (&value, g_type_info_get_tag (value_type_info));
py_value = _pygi_argument_to_object (&value, value_type_info, item_transfer);
if (py_value == NULL) {
Py_DECREF (py_key);
......
......@@ -30,6 +30,12 @@ G_BEGIN_DECLS
/* Private */
gpointer _pygi_arg_to_hash_pointer (const GIArgument *arg,
GITypeTag type_tag);
void _pygi_hash_pointer_to_arg (GIArgument *arg,
GITypeTag type_tag);
gint _pygi_g_type_interface_check_object (GIBaseInfo *info,
PyObject *object);
......
......@@ -1393,6 +1393,8 @@ _args_cache_generate (GICallableInfo *callable_info,
callable_cache->n_to_py_child_args++;
}
arg_cache->type_tag = g_type_info_get_tag (type_info);
g_base_info_unref ( (GIBaseInfo *)arg_info);
continue;
}
......
......@@ -27,6 +27,57 @@
*/
static GSList* async_free_list;
static void
_pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
GITypeInfo *type_info,
GITransfer transfer)
{
GIArgument arg = _pygi_argument_from_object (object, type_info, transfer);
GITypeTag type_tag = g_type_info_get_tag (type_info);
if (retval == NULL)
return;
switch (type_tag) {
case GI_TYPE_TAG_BOOLEAN:
*((ffi_sarg *) retval) = arg.v_boolean;
break;
case GI_TYPE_TAG_INT8:
*((ffi_sarg *) retval) = arg.v_int8;
break;
case GI_TYPE_TAG_UINT8:
*((ffi_arg *) retval) = arg.v_uint8;
break;
case GI_TYPE_TAG_INT16:
*((ffi_sarg *) retval) = arg.v_int16;
break;
case GI_TYPE_TAG_UINT16:
*((ffi_arg *) retval) = arg.v_uint16;
break;
case GI_TYPE_TAG_INT32:
*((ffi_sarg *) retval) = arg.v_int32;
break;
case GI_TYPE_TAG_UINT32:
*((ffi_arg *) retval) = arg.v_uint32;
break;
case GI_TYPE_TAG_INT64:
*((ffi_sarg *) retval) = arg.v_int64;
break;
case GI_TYPE_TAG_UINT64:
*((ffi_arg *) retval) = arg.v_uint64;
break;
case GI_TYPE_TAG_FLOAT:
*((gfloat *) retval) = arg.v_float;
break;
case GI_TYPE_TAG_DOUBLE:
*((gdouble *) retval) = arg.v_double;
break;
default:
*((GIArgument *) retval) = arg;
break;
}
}
static void
_pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
GITypeInfo *type_info,
......@@ -299,7 +350,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
arg = (GIArgument*) g_args[i].v_pointer;
if (g_type_info_get_tag (arg_type) == GI_TYPE_TAG_ARRAY)
arg->v_pointer = _pygi_argument_to_array (arg, args,
arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args,
arg_type, &free_array);
value = _pygi_argument_to_object (arg, arg_type, transfer);
......@@ -358,10 +409,10 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
GITransfer transfer = g_callable_info_get_caller_owns (callable_info);
if (PyTuple_Check (py_retval)) {
PyObject *item = PyTuple_GET_ITEM (py_retval, 0);
_pygi_closure_assign_pyobj_to_out_argument (resp, item,
_pygi_closure_assign_pyobj_to_retval (resp, item,
return_type_info, transfer);
} else {
_pygi_closure_assign_pyobj_to_out_argument (resp, py_retval,
_pygi_closure_assign_pyobj_to_retval (resp, py_retval,
return_type_info, transfer);
}
i_py_retval++;
......
......@@ -32,6 +32,119 @@
#include "pygi-marshal-cleanup.h"
#include "pygi-marshal-from-py.h"
gboolean
gi_argument_from_py_ssize_t (GIArgument *arg_out,
Py_ssize_t size_in,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_VOID:
case GI_TYPE_TAG_BOOLEAN:
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_UINT8:
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_UINT16:
goto unhandled_type;
/* Ranges assume two's complement */
case GI_TYPE_TAG_INT32:
if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
arg_out->v_int32 = size_in;
return TRUE;
} else {
goto overflow;
}
case GI_TYPE_TAG_UINT32:
if (size_in >= 0 && size_in <= G_MAXUINT32) {
arg_out->v_uint32 = size_in;
return TRUE;
} else {
goto overflow;
}
case GI_TYPE_TAG_INT64:
arg_out->v_int64 = size_in;
return TRUE;
case GI_TYPE_TAG_UINT64:
if (size_in >= 0) {
arg_out->v_uint64 = size_in;
return TRUE;
} else {
goto overflow;
}
case GI_TYPE_TAG_FLOAT:
case GI_TYPE_TAG_DOUBLE:
case GI_TYPE_TAG_GTYPE:
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_ARRAY:
case GI_TYPE_TAG_INTERFACE:
case GI_TYPE_TAG_GLIST:
case GI_TYPE_TAG_GSLIST:
case GI_TYPE_TAG_GHASH:
case GI_TYPE_TAG_ERROR:
case GI_TYPE_TAG_UNICHAR:
default:
goto unhandled_type;
}
overflow:
PyErr_Format (PyExc_OverflowError,
"Unable to marshal C Py_ssize_t %zd to %s",
size_in,
g_type_tag_to_string (type_tag));
return FALSE;
unhandled_type:
PyErr_Format (PyExc_TypeError,
"Unable to marshal C Py_ssize_t %zd to %s",
size_in,
g_type_tag_to_string (type_tag));
return FALSE;
}
gboolean
gi_argument_from_c_long (GIArgument *arg_out,
long c_long_in,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
arg_out->v_int8 = c_long_in;
return TRUE;
case GI_TYPE_TAG_UINT8:
arg_out->v_uint8 = c_long_in;
return TRUE;
case GI_TYPE_TAG_INT16:
arg_out->v_int16 = c_long_in;
return TRUE;
case GI_TYPE_TAG_UINT16:
arg_out->v_uint16 = c_long_in;
return TRUE;
case GI_TYPE_TAG_INT32:
arg_out->v_int32 = c_long_in;
return TRUE;
case GI_TYPE_TAG_UINT32:
arg_out->v_uint32 = c_long_in;
return TRUE;
case GI_TYPE_TAG_INT64:
arg_out->v_int64 = c_long_in;
return TRUE;
case GI_TYPE_TAG_UINT64:
arg_out->v_uint64 = c_long_in;
return TRUE;
default:
PyErr_Format (PyExc_TypeError,
"Unable to marshal C long %ld to %s",
c_long_in,
g_type_tag_to_string (type_tag));
return FALSE;
}
}
/*
* _is_union_member - check to see if the py_arg is actually a member of the
* expected C union
......@@ -736,33 +849,6 @@ _pygi_marshal_from_py_filename (PyGIInvokeState *state,
return TRUE;
}
static gpointer
_pygi_arg_to_hash_pointer (const GIArgument *arg,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
return GINT_TO_POINTER(arg->v_int8);
case GI_TYPE_TAG_UINT8:
return GINT_TO_POINTER(arg->v_uint8);
case GI_TYPE_TAG_INT16:
return GINT_TO_POINTER(arg->v_int16);
case GI_TYPE_TAG_UINT16:
return GINT_TO_POINTER(arg->v_uint16);
case GI_TYPE_TAG_INT32:
return GINT_TO_POINTER(arg->v_int32);
case GI_TYPE_TAG_UINT32:
return GINT_TO_POINTER(arg->v_uint32);
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_INTERFACE:
return arg->v_pointer;
default:
g_critical("Unsupported type %s", g_type_tag_to_string(type_tag));
return arg->v_pointer;
}
}
gboolean
_pygi_marshal_from_py_array (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
......@@ -942,12 +1028,21 @@ array_success:
if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
/* if we are not setup yet just set the in arg */
if (len_arg == NULL)
state->in_args[child_cache->c_arg_index].v_long = length;
else
if (len_arg == NULL) {
if (!gi_argument_from_py_ssize_t (&state->in_args[child_cache->c_arg_index],
length,
child_cache->type_tag)) {
goto err;
}
} else {
*len_arg = length;
}
} else {
state->in_args[child_cache->c_arg_index].v_long = length;
if (!gi_argument_from_py_ssize_t (&state->in_args[child_cache->c_arg_index],
length,
child_cache->type_tag)) {
goto err;
}
}
}
......@@ -1291,20 +1386,32 @@ _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
PyObject *py_arg,
GIArgument *arg)
{
PyObject *int_;
PyObject *py_long;
long c_long;
gint is_instance;
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
GIBaseInfo *interface;
is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
int_ = PYGLIB_PyNumber_Long (py_arg);
if (int_ == NULL) {
py_long = PYGLIB_PyNumber_Long (py_arg);
if (py_long == NULL) {
PyErr_Clear();
goto err;
}
arg->v_long = PYGLIB_PyLong_AsLong (int_);
Py_DECREF (int_);
c_long = PYGLIB_PyLong_AsLong (py_long);
Py_DECREF (py_long);
/* Write c_long into arg */
interface = g_type_info_get_interface (arg_cache->type_info);
assert(g_base_info_get_type (interface) == GI_INFO_TYPE_ENUM);
if (!gi_argument_from_c_long(arg,
c_long,
g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
g_assert_not_reached();
return FALSE;
}
/* If this is not an instance of the Enum type that we want
* we need to check if the value is equivilant to one of the
......@@ -1318,7 +1425,7 @@ _pygi_marshal_from_py_interface_enum (PyGIInvokeState *state,
g_enum_info_get_value (iface_cache->interface_info, i);
glong enum_value = g_value_info_get_value (value_info);
g_base_info_unref ( (GIBaseInfo *)value_info);
if (arg->v_long == enum_value) {
if (c_long == enum_value) {
is_found = TRUE;
break;
}
......@@ -1343,25 +1450,35 @@ _pygi_marshal_from_py_interface_flags (PyGIInvokeState *state,
PyObject *py_arg,
GIArgument *arg)
{
PyObject *int_;
PyObject *py_long;
long c_long;
gint is_instance;
PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
GIBaseInfo *interface;
is_instance = PyObject_IsInstance (py_arg, iface_cache->py_type);
int_ = PYGLIB_PyNumber_Long (py_arg);
if (int_ == NULL) {
py_long = PYGLIB_PyNumber_Long (py_arg);
if (py_long == NULL) {
PyErr_Clear ();
goto err;
}
arg->v_long = PYGLIB_PyLong_AsLong (int_);
Py_DECREF (int_);
c_long = PYGLIB_PyLong_AsLong (py_long);
Py_DECREF (py_long);
/* only 0 or argument of type Flag is allowed */
if (!is_instance && arg->v_long != 0)
if (!is_instance && c_long != 0)
goto err;
/* Write c_long into arg */
interface = g_type_info_get_interface (arg_cache->type_info);
g_assert (g_base_info_get_type (interface) == GI_INFO_TYPE_FLAGS);
if (!gi_argument_from_c_long(arg, c_long,
g_enum_info_get_storage_type ((GIEnumInfo *)interface))) {
return FALSE;
}
return TRUE;
err:
......
......@@ -30,6 +30,9 @@
G_BEGIN_DECLS
gboolean _pygi_marshal_from_py_ssize_t (PyGIArgCache *arg_cache,
Py_ssize_t size,
GIArgument *arg);
gboolean _pygi_marshal_from_py_void (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
......
......@@ -34,6 +34,83 @@
#include "pygi-marshal-cleanup.h"
#include "pygi-marshal-to-py.h"
gboolean
gi_argument_to_c_long (GIArgument *arg_in,
long *c_long_out,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
*c_long_out = arg_in->v_int8;
return TRUE;
case GI_TYPE_TAG_UINT8:
*c_long_out = arg_in->v_uint8;
return TRUE;
case GI_TYPE_TAG_INT16:
*c_long_out = arg_in->v_int16;
return TRUE;
case GI_TYPE_TAG_UINT16:
*c_long_out = arg_in->v_uint16;
return TRUE;
case GI_TYPE_TAG_INT32:
*c_long_out = arg_in->v_int32;
return TRUE;
case GI_TYPE_TAG_UINT32:
*c_long_out = arg_in->v_uint32;
return TRUE;
case GI_TYPE_TAG_INT64:
*c_long_out = arg_in->v_int64;
return TRUE;
case GI_TYPE_TAG_UINT64:
*c_long_out = arg_in->v_uint64;
return TRUE;
default:
PyErr_Format (PyExc_TypeError,
"Unable to marshal %s to C long",
g_type_tag_to_string (type_tag));
return FALSE;
}
}
gboolean
gi_argument_to_gsize (GIArgument *arg_in,
gsize *gsize_out,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
*gsize_out = arg_in->v_int8;
return TRUE;
case GI_TYPE_TAG_UINT8:
*gsize_out = arg_in->v_uint8;
return TRUE;
case GI_TYPE_TAG_INT16:
*gsize_out = arg_in->v_int16;
return TRUE;
case GI_TYPE_TAG_UINT16:
*gsize_out = arg_in->v_uint16;
return TRUE;
case GI_TYPE_TAG_INT32:
*gsize_out = arg_in->v_int32;
return TRUE;
case GI_TYPE_TAG_UINT32:
*gsize_out = arg_in->v_uint32;
return TRUE;
case GI_TYPE_TAG_INT64:
*gsize_out = arg_in->v_int64;
return TRUE;
case GI_TYPE_TAG_UINT64:
*gsize_out = arg_in->v_uint64;
return TRUE;
default:
PyErr_Format (PyExc_TypeError,
"Unable to marshal %s to gsize",
g_type_tag_to_string (type_tag));
return FALSE;
}
}
PyObject *
_pygi_marshal_to_py_void (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
......@@ -284,7 +361,12 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state,
}
} else {
GIArgument *len_arg = state->args[seq_cache->len_arg_index];
len = len_arg->v_long;
if (!gi_argument_to_gsize (len_arg,
&len,
callable_cache->args_cache[seq_cache->len_arg_index]->type_tag)) {
return NULL;
}
}
array_ = g_array_new (FALSE,
......@@ -415,29 +497,6 @@ err:
return NULL;
}
static void
_pygi_hash_pointer_to_arg (GIArgument *arg,
GITypeTag type_tag)
{
switch (type_tag) {
case GI_TYPE_TAG_INT8:
arg->v_int8 = GPOINTER_TO_INT(arg->v_pointer);
break;
case GI_TYPE_TAG_INT16:
arg->v_int16 = GPOINTER_TO_INT(arg->v_pointer);
break;
case GI_TYPE_TAG_INT32:
arg->v_int32 = GPOINTER_TO_INT(arg->v_pointer);
break;
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_INTERFACE:
break;
default:
g_critical("Unsupported type %s", g_type_tag_to_string(type_tag));
}
}
PyObject *
_pygi_marshal_to_py_glist (PyGIInvokeState *state,