Skip to content

Commit

Permalink
extension: Support unmarshaling more types to GVariant
Browse files Browse the repository at this point in the history
Co-authored-by: Håvard Sørbø <[email protected]>
  • Loading branch information
oleavr and hsorbo committed May 16, 2024
1 parent e7231b1 commit 5895236
Showing 1 changed file with 116 additions and 25 deletions.
141 changes: 116 additions & 25 deletions frida/_frida/extension.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2013-2023 Ole André Vadla Ravnås <[email protected]>
* Copyright (C) 2024 Håvard Sørbø <[email protected]>
*
* Licence: wxWindows Library Licence, Version 3.1
*/
Expand Down Expand Up @@ -356,6 +357,8 @@ static PyObject * PyGObject_marshal_bytes (GBytes * bytes);
static PyObject * PyGObject_marshal_bytes_non_nullable (GBytes * bytes);
static PyObject * PyGObject_marshal_variant (GVariant * variant);
static gboolean PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant);
static gboolean PyGObject_unmarshal_variant_from_mapping (PyObject * mapping, GVariant ** variant);
static gboolean PyGObject_unmarshal_variant_from_sequence (PyObject * sequence, GVariant ** variant);
static PyObject * PyGObject_marshal_parameters_dict (GHashTable * dict);
static PyObject * PyGObject_marshal_socket_address (GSocketAddress * address);
static gboolean PyGObject_unmarshal_certificate (const gchar * str, GTlsCertificate ** certificate);
Expand Down Expand Up @@ -1697,53 +1700,141 @@ PyGObject_unmarshal_variant (PyObject * value, GVariant ** variant)
PyGObject_unmarshal_string (value, &str);

*variant = g_variant_new_take_string (str);

return TRUE;
}
else if (PyBool_Check (value))
{
*variant = g_variant_new_boolean (value == Py_True);
}
#if PY_MAJOR_VERSION < 3
else if (PyUnicode_Check (value))

if (PyLong_Check (value))
{
PyObject * value_utf8;
PY_LONG_LONG l;

value_utf8 = PyUnicode_AsUTF8String (value);
if (value_utf8 == NULL)
goto propagate_error;
l = PyLong_AsLongLong (value);
if (l == -1 && PyErr_Occurred ())
return FALSE;

*variant = g_variant_new_string (PyBytes_AsString (value_utf8));
*variant = g_variant_new_int64 (l);

Py_DECREF (value_utf8);
return TRUE;
}
else if (PyInt_Check (value))

if (PyBool_Check (value))
{
*variant = g_variant_new_int64 (PyInt_AS_LONG (value));
*variant = g_variant_new_boolean (value == Py_True);

return TRUE;
}
#endif
else if (PyLong_Check (value))

if (PyBytes_Check (value))
{
PY_LONG_LONG l;
char * buffer;
Py_ssize_t length;
gpointer copy;

l = PyLong_AsLongLong (value);
if (l == -1 && PyErr_Occurred ())
goto propagate_error;
PyBytes_AsStringAndSize (value, &buffer, &length);

*variant = g_variant_new_int64 (l);
copy = g_memdup2 (buffer, length);
*variant = g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING, copy, length, TRUE, g_free, copy);

return TRUE;
}
else

if (PySequence_Check (value))
return PyGObject_unmarshal_variant_from_sequence (value, variant);

if (PyMapping_Check (value))
return PyGObject_unmarshal_variant_from_mapping (value, variant);

PyErr_SetString (PyExc_TypeError, "unsupported type");
return FALSE;
}

static gboolean
PyGObject_unmarshal_variant_from_mapping (PyObject * mapping, GVariant ** variant)
{
GVariantBuilder builder;
PyObject * items = NULL;
Py_ssize_t n, i;

g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);

items = PyMapping_Items (mapping);
if (items == NULL)
goto propagate_error;

n = PyList_Size (items);

for (i = 0; i != n; i++)
{
goto unsupported_type;
PyObject * pair, * key, * val, * key_bytes;
GVariant * raw_value;

pair = PyList_GetItem (items, i);
key = PyTuple_GetItem (pair, 0);
val = PyTuple_GetItem (pair, 1);

if (!PyGObject_unmarshal_variant (val, &raw_value))
goto propagate_error;

key_bytes = PyUnicode_AsUTF8String (key);

g_variant_builder_add (&builder, "{sv}", PyBytes_AsString (key_bytes), raw_value);

Py_DECREF (key_bytes);
}

Py_DecRef (items);

*variant = g_variant_builder_end (&builder);

return TRUE;

unsupported_type:
propagate_error:
{
PyErr_SetString (PyExc_TypeError, "unsupported type");
Py_XDECREF (items);
g_variant_builder_clear (&builder);

return FALSE;
}
}

static gboolean
PyGObject_unmarshal_variant_from_sequence (PyObject * sequence, GVariant ** variant)
{
GVariantBuilder builder;
Py_ssize_t n, i;
PyObject * val = NULL;

g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));

n = PySequence_Length (sequence);
if (n == -1)
goto propagate_error;

for (i = 0; i != n; i++)
{
GVariant * raw_value;

val = PySequence_GetItem (sequence, i);
if (val == NULL)
goto propagate_error;

if (!PyGObject_unmarshal_variant (val, &raw_value))
goto propagate_error;

g_variant_builder_add (&builder, "v", raw_value);

Py_DECREF (val);
}

*variant = g_variant_builder_end (&builder);

return TRUE;

propagate_error:
{
Py_XDECREF (val);
g_variant_builder_clear (&builder);

return FALSE;
}
}
Expand Down

0 comments on commit 5895236

Please sign in to comment.