From 5895236b6339e4cce9c4fe8227936f9fa39dc2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Thu, 16 May 2024 13:11:39 +0200 Subject: [PATCH] extension: Support unmarshaling more types to GVariant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Håvard Sørbø --- frida/_frida/extension.c | 141 ++++++++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 25 deletions(-) diff --git a/frida/_frida/extension.c b/frida/_frida/extension.c index 5b9a212..fe25f37 100644 --- a/frida/_frida/extension.c +++ b/frida/_frida/extension.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2013-2023 Ole André Vadla Ravnås + * Copyright (C) 2024 Håvard Sørbø * * Licence: wxWindows Library Licence, Version 3.1 */ @@ -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); @@ -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; } }