From fad679ef8cd654646c9234ff8fd39507adad9b8e Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 19 Apr 2020 17:41:55 +0200
Subject: Updated the interface for flat formats.

---
 plugins/pychrysalide/format/flat.c | 109 +++++++++++++++++++++----------------
 plugins/pychrysalide/format/flat.h |   3 +
 src/format/flat-int.h              |   2 +-
 src/format/flat.c                  |  57 +++----------------
 src/format/flat.h                  |   8 +--
 5 files changed, 75 insertions(+), 104 deletions(-)

diff --git a/plugins/pychrysalide/format/flat.c b/plugins/pychrysalide/format/flat.c
index 39ef1f6..2c8e9fd 100644
--- a/plugins/pychrysalide/format/flat.c
+++ b/plugins/pychrysalide/format/flat.c
@@ -41,9 +41,6 @@
 /* Crée un nouvel objet Python de type 'FlatFormat'. */
 static PyObject *py_flat_format_new(PyTypeObject *, PyObject *, PyObject *);
 
-/* Indique le type d'architecture visée par le format. */
-static PyObject *py_flat_format_set_target_machine(PyObject *, PyObject *);
-
 
 
 /******************************************************************************
@@ -64,13 +61,27 @@ static PyObject *py_flat_format_new(PyTypeObject *type, PyObject *args, PyObject
 {
     PyObject *result;                       /* Instance à retourner        */
     GBinContent *content;                   /* Instance GLib du contenu    */
+    const char *machine;                    /* Identifiant d'architecture  */
+    unsigned int endian;                    /* Boutisme de l'architecture  */
     int ret;                                /* Bilan de lecture des args.  */
     GExeFormat *format;                     /* Création GLib à transmettre */
 
-    ret = PyArg_ParseTuple(args, "O&", convert_to_binary_content, &content);
+#define FLAT_FORMAT_DOC                                                     \
+    "FlatFormat is suitable for all executable contents without a proper"   \
+    " file format, such as shellcodes ou eBPF programs.\n"                  \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    FlatFormat(content, machine, endian)"                              \
+    "\n"                                                                    \
+    "Where content is a pychrysalide.analysis.BinContent object, machine"   \
+    " defines the target architecture and endian provides the right"        \
+    " endianness of the data."
+
+    ret = PyArg_ParseTuple(args, "O&sI", convert_to_binary_content, &content, &machine, &endian);
     if (!ret) return NULL;
 
-    format = g_flat_format_new(content);
+    format = g_flat_format_new(content, machine, endian);
 
     if (format == NULL)
     {
@@ -91,42 +102,6 @@ static PyObject *py_flat_format_new(PyTypeObject *type, PyObject *args, PyObject
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : self = description de l'exécutable à consulter.              *
-*                args = arguments accompagnant l'appel.                       *
-*                                                                             *
-*  Description : Indique le type d'architecture visée par le format.          *
-*                                                                             *
-*  Retour      : Rien, donc None en Python.                                   *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static PyObject *py_flat_format_set_target_machine(PyObject *self, PyObject *args)
-{
-    PyObject *result;                       /* Instance à retourner        */
-    GFlatFormat *format;                    /* Version GLib du format      */
-    const char *machine;                    /* Identifiant d'architecture  */
-    int ret;                                /* Bilan de lecture des args.  */
-
-    format = G_FLAT_FORMAT(pygobject_get(self));
-    assert(format != NULL);
-
-    ret = PyArg_ParseTuple(args, "s", &machine);
-    if (!ret) return NULL;
-
-    g_flat_format_set_target_machine(format, machine);
-
-    result = Py_None;
-    Py_INCREF(result);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -140,11 +115,6 @@ static PyObject *py_flat_format_set_target_machine(PyObject *self, PyObject *arg
 PyTypeObject *get_python_flat_format_type(void)
 {
     static PyMethodDef py_flat_format_methods[] = {
-        {
-            "set_machine", py_flat_format_set_target_machine,
-            METH_VARARGS,
-            "set_machine($self, machine, /)\n--\n\nSet the architecture linked to the flat format."
-        },
         { NULL }
     };
 
@@ -161,7 +131,7 @@ PyTypeObject *get_python_flat_format_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
 
-        .tp_doc         = "PyChrysalide flat format",
+        .tp_doc         = FLAT_FORMAT_DOC,
 
         .tp_methods     = py_flat_format_methods,
         .tp_getset      = py_flat_format_getseters,
@@ -211,3 +181,48 @@ bool ensure_python_flat_format_is_registered(void)
     return true;
 
 }
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : arg = argument quelconque à tenter de convertir.             *
+*                dst = destination des valeurs récupérées en cas de succès.   *
+*                                                                             *
+*  Description : Tente de convertir en format à plat.                         *
+*                                                                             *
+*  Retour      : Bilan de l'opération, voire indications supplémentaires.     *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+int convert_to_flat_format(PyObject *arg, void *dst)
+{
+    int result;                             /* Bilan à retourner           */
+
+    result = PyObject_IsInstance(arg, (PyObject *)get_python_flat_format_type());
+
+    switch (result)
+    {
+        case -1:
+            /* L'exception est déjà fixée par Python */
+            result = 0;
+            break;
+
+        case 0:
+            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to flat format");
+            break;
+
+        case 1:
+            *((GFlatFormat **)dst) = G_FLAT_FORMAT(pygobject_get(arg));
+            break;
+
+        default:
+            assert(false);
+            break;
+
+    }
+
+    return result;
+
+}
diff --git a/plugins/pychrysalide/format/flat.h b/plugins/pychrysalide/format/flat.h
index d7447dd..e3fd65a 100644
--- a/plugins/pychrysalide/format/flat.h
+++ b/plugins/pychrysalide/format/flat.h
@@ -37,6 +37,9 @@ PyTypeObject *get_python_flat_format_type(void);
 /* Prend en charge l'objet 'pychrysalide.format.FlatFormat'. */
 bool ensure_python_flat_format_is_registered(void);
 
+/* Tente de convertir en format à plat. */
+int convert_to_flat_format(PyObject *, void *);
+
 
 
 #endif  /* _PLUGINS_PYCHRYSALIDE_FORMAT_FLAT_H */
diff --git a/src/format/flat-int.h b/src/format/flat-int.h
index 9a54e82..d785e5f 100644
--- a/src/format/flat-int.h
+++ b/src/format/flat-int.h
@@ -37,8 +37,8 @@ struct _GFlatFormat
 {
     GExeFormat parent;                      /* A laisser en premier        */
 
-    SourceEndian endian;                    /* Boutisme imposé             */
     char *machine;                          /* Architecture imposée        */
+    SourceEndian endian;                    /* Boutisme imposé             */
 
 };
 
diff --git a/src/format/flat.c b/src/format/flat.c
index a9081d8..75e359e 100644
--- a/src/format/flat.c
+++ b/src/format/flat.c
@@ -126,8 +126,8 @@ static void g_flat_format_class_init(GFlatFormatClass *klass)
 
 static void g_flat_format_init(GFlatFormat *format)
 {
-    format->endian = SRE_LITTLE;
     format->machine = NULL;
+    format->endian = SRE_LITTLE;
 
 }
 
@@ -165,6 +165,9 @@ static void g_flat_format_dispose(GFlatFormat *format)
 
 static void g_flat_format_finalize(GFlatFormat *format)
 {
+    if (format->machine != NULL)
+        free(format->machine);
+
     G_OBJECT_CLASS(g_flat_format_parent_class)->finalize(G_OBJECT(format));
 
 }
@@ -182,7 +185,7 @@ static void g_flat_format_finalize(GFlatFormat *format)
 *                                                                             *
 ******************************************************************************/
 
-GExeFormat *g_flat_format_new(GBinContent *content)
+GExeFormat *g_flat_format_new(GBinContent *content, const char *machine, SourceEndian endian)
 {
     GFlatFormat *result;                     /* Structure à retourner       */
 
@@ -190,6 +193,9 @@ GExeFormat *g_flat_format_new(GBinContent *content)
 
     g_binary_format_set_content(G_BIN_FORMAT(result), content);
 
+    result->machine = strdup(machine);
+    result->endian = endian;
+
     return G_EXE_FORMAT(result);
 
 }
@@ -271,26 +277,6 @@ static bool g_flat_format_analyze(GFlatFormat *format, wgroup_id_t gid, GtkStatu
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
-*                endian = boutisme à associer au format à plat.               *
-*                                                                             *
-*  Description : Spécifie un boutisme à utiliser.                             *
-*                                                                             *
-*  Retour      : Indicateur de boutisme.                                      *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_flat_format_set_endianness(GFlatFormat *format, SourceEndian endian)
-{
-    format->endian = endian;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : format = informations chargées à consulter.                  *
 *                                                                             *
 *  Description : Informe quant au boutisme utilisé.                           *
 *                                                                             *
@@ -309,33 +295,6 @@ static SourceEndian g_flat_format_get_endianness(const GFlatFormat *format)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : format  = informations chargées à consulter.                 *
-*                machine = identifiant de l'architecture visée.               *
-*                                                                             *
-*  Description : Indique le type d'architecture visée par le format.          *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void g_flat_format_set_target_machine(GFlatFormat *format, const char *machine)
-{
-    if (format->machine != NULL)
-        free(format->machine);
-
-    if (machine == NULL)
-        format->machine = NULL;
-
-    else
-        format->machine = strdup(machine);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : format = informations chargées à consulter.                  *
 *                                                                             *
 *  Description : Indique le type d'architecture visée par le format.          *
diff --git a/src/format/flat.h b/src/format/flat.h
index 1a08d25..83c5e3c 100644
--- a/src/format/flat.h
+++ b/src/format/flat.h
@@ -52,13 +52,7 @@ typedef struct _GFlatFormatClass GFlatFormatClass;
 GType g_flat_format_get_type(void);
 
 /* Prend en charge un nouveau format à plat. */
-GExeFormat *g_flat_format_new(GBinContent *);
-
-/* Spécifie un boutisme à utiliser. */
-void g_flat_format_set_endianness(GFlatFormat *, SourceEndian);
-
-/* Indique le type d'architecture visée par le format. */
-void g_flat_format_set_target_machine(GFlatFormat *, const char *);
+GExeFormat *g_flat_format_new(GBinContent *, const char *, SourceEndian);
 
 
 
-- 
cgit v0.11.2-87-g4458