From 43f249445c9c69b9eabeea8be08b6b55a474f1fc Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 9 Jan 2020 00:42:44 +0100
Subject: Fixed the link between native and Python locations.

---
 plugins/pychrysalide/analysis/block.c             |   6 +-
 plugins/pychrysalide/analysis/content.c           |  45 +++-
 plugins/pychrysalide/analysis/db/items/bookmark.c |  18 +-
 plugins/pychrysalide/analysis/db/items/comment.c  |  14 +-
 plugins/pychrysalide/arch/processor.c             |  20 +-
 plugins/pychrysalide/arch/vmpa.c                  | 313 +++++++++++-----------
 plugins/pychrysalide/arch/vmpa.h                  |   3 +
 plugins/pychrysalide/debug/debugger.c             |  36 ++-
 plugins/pychrysalide/format/format.c              |   6 +-
 plugins/pychrysalide/glibext/binarycursor.c       |   6 +-
 plugins/pychrysalide/glibext/binportion.c         |  12 +-
 11 files changed, 280 insertions(+), 199 deletions(-)

diff --git a/plugins/pychrysalide/analysis/block.c b/plugins/pychrysalide/analysis/block.c
index e282d14..7e6b109 100644
--- a/plugins/pychrysalide/analysis/block.c
+++ b/plugins/pychrysalide/analysis/block.c
@@ -399,7 +399,7 @@ int convert_to_code_block(PyObject *arg, void *dst)
 static PyObject *py_block_list_find_by_addr(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Conclusion à retourner      */
-    vmpa2t addr;                            /* Emplacement ciblé           */
+    vmpa2t *addr;                           /* Emplacement ciblé           */
     int ret;                                /* Bilan de lecture des args.  */
     GBlockList *list;                       /* Liste de blocs manipulée    */
     GCodeBlock *found;                      /* Eventuel bloc trouvé        */
@@ -409,7 +409,7 @@ static PyObject *py_block_list_find_by_addr(PyObject *self, PyObject *args)
 
     list = G_BLOCK_LIST(pygobject_get(self));
 
-    found = g_block_list_find_by_addr(list, &addr);
+    found = g_block_list_find_by_addr(list, addr);
 
     if (found != NULL)
     {
@@ -422,6 +422,8 @@ static PyObject *py_block_list_find_by_addr(PyObject *self, PyObject *args)
         Py_INCREF(result);
     }
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
diff --git a/plugins/pychrysalide/analysis/content.c b/plugins/pychrysalide/analysis/content.c
index 93292fb..8934c88 100644
--- a/plugins/pychrysalide/analysis/content.c
+++ b/plugins/pychrysalide/analysis/content.c
@@ -155,7 +155,7 @@ static PyObject *py_binary_content_describe(PyObject *self, PyObject *args)
 static PyObject *py_binary_content_read_raw(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     unsigned long long length;              /* Quantité de données à lire  */
     int ret;                                /* Bilan de lecture des args.  */
     GBinContent *content;                   /* Version GLib du format      */
@@ -173,15 +173,20 @@ static PyObject *py_binary_content_read_raw(PyObject *self, PyObject *args)
 
     content = G_BIN_CONTENT(pygobject_get(self));
 
-    val = g_binary_content_get_raw_access(content, &addr, length);
+    val = g_binary_content_get_raw_access(content, addr, length);
     if (val == NULL)
     {
+        clean_vmpa_arg(addr);
+
         PyErr_SetString(PyExc_Exception, _("Invalid read access."));
         return NULL;
+
     }
 
     result = PyBytes_FromStringAndSize((char *)val, length);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -203,7 +208,7 @@ static PyObject *py_binary_content_read_raw(PyObject *self, PyObject *args)
 static PyObject *py_binary_content_read_u8(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     int ret;                                /* Bilan de lecture des args.  */
     GBinContent *content;                   /* Version GLib du format      */
     uint8_t val;                            /* Valeur lue à faire suivre   */
@@ -221,15 +226,20 @@ static PyObject *py_binary_content_read_u8(PyObject *self, PyObject *args)
 
     content = G_BIN_CONTENT(pygobject_get(self));
 
-    status = g_binary_content_read_u8(content, &addr, &val);
+    status = g_binary_content_read_u8(content, addr, &val);
     if (!status)
     {
+        clean_vmpa_arg(addr);
+
         PyErr_SetString(PyExc_Exception, _("Invalid read access."));
         return NULL;
+
     }
 
     result = PyLong_FromUnsignedLong(val);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -251,7 +261,7 @@ static PyObject *py_binary_content_read_u8(PyObject *self, PyObject *args)
 static PyObject *py_binary_content_read_u16(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     unsigned long endianness;               /* Boutisme de la lecture      */
     int ret;                                /* Bilan de lecture des args.  */
     GBinContent *content;                   /* Version GLib du format      */
@@ -273,15 +283,20 @@ static PyObject *py_binary_content_read_u16(PyObject *self, PyObject *args)
 
     content = G_BIN_CONTENT(pygobject_get(self));
 
-    status = g_binary_content_read_u16(content, &addr, endianness, &val);
+    status = g_binary_content_read_u16(content, addr, endianness, &val);
     if (!status)
     {
+        clean_vmpa_arg(addr);
+
         PyErr_SetString(PyExc_Exception, _("Invalid read access."));
         return NULL;
+
     }
 
     result = PyLong_FromUnsignedLong(val);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -303,7 +318,7 @@ static PyObject *py_binary_content_read_u16(PyObject *self, PyObject *args)
 static PyObject *py_binary_content_read_u32(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     unsigned long endianness;               /* Boutisme de la lecture      */
     int ret;                                /* Bilan de lecture des args.  */
     GBinContent *content;                   /* Version GLib du format      */
@@ -325,15 +340,20 @@ static PyObject *py_binary_content_read_u32(PyObject *self, PyObject *args)
 
     content = G_BIN_CONTENT(pygobject_get(self));
 
-    status = g_binary_content_read_u32(content, &addr, endianness, &val);
+    status = g_binary_content_read_u32(content, addr, endianness, &val);
     if (!status)
     {
+        clean_vmpa_arg(addr);
+
         PyErr_SetString(PyExc_Exception, _("Invalid read access."));
         return NULL;
+
     }
 
     result = PyLong_FromUnsignedLong(val);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -354,7 +374,7 @@ static PyObject *py_binary_content_read_u32(PyObject *self, PyObject *args)
 static PyObject *py_binary_content_read_u64(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     unsigned long endianness;               /* Boutisme de la lecture      */
     int ret;                                /* Bilan de lecture des args.  */
     GBinContent *content;                   /* Version GLib du format      */
@@ -376,15 +396,20 @@ static PyObject *py_binary_content_read_u64(PyObject *self, PyObject *args)
 
     content = G_BIN_CONTENT(pygobject_get(self));
 
-    status = g_binary_content_read_u64(content, &addr, endianness, &val);
+    status = g_binary_content_read_u64(content, addr, endianness, &val);
     if (!status)
     {
+        clean_vmpa_arg(addr);
+
         PyErr_SetString(PyExc_Exception, _("Invalid read access."));
         return NULL;
+
     }
 
     result = PyLong_FromUnsignedLongLong(val);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
diff --git a/plugins/pychrysalide/analysis/db/items/bookmark.c b/plugins/pychrysalide/analysis/db/items/bookmark.c
index 468f38c..547d8f1 100644
--- a/plugins/pychrysalide/analysis/db/items/bookmark.c
+++ b/plugins/pychrysalide/analysis/db/items/bookmark.c
@@ -148,7 +148,7 @@ static PyObject *py_db_bookmark_new(PyTypeObject *type, PyObject *args, PyObject
 static int py_db_bookmark_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
     int result;                             /* Bilan à renvoyer            */
-    vmpa2t addr;                            /* Emplacement ciblé           */
+    vmpa2t *addr;                           /* Emplacement ciblé           */
     const char *comment;                    /* Commentaire éventuel associé*/
     int ret;                                /* Bilan de lecture des args.  */
     PyObject *new_args;                     /* Nouveaux arguments épurés   */
@@ -190,14 +190,24 @@ static int py_db_bookmark_init(PyObject *self, PyObject *args, PyObject *kwds)
     Py_DECREF(new_kwds);
     Py_DECREF(new_args);
 
-    if (ret == -1) goto exit;
+    if (ret == -1)
+    {
+        clean_vmpa_arg(addr);
+        goto exit;
+    }
 
     /* Eléments de base */
 
     bookmark = G_DB_BOOKMARK(pygobject_get(self));
 
-    status = g_db_bookmark_fill(bookmark, &addr, comment);
-    if (!status) goto exit;
+    status = g_db_bookmark_fill(bookmark, addr, comment);
+    if (!status)
+    {
+        clean_vmpa_arg(addr);
+        goto exit;
+    }
+
+    clean_vmpa_arg(addr);
 
     result = 0;
 
diff --git a/plugins/pychrysalide/analysis/db/items/comment.c b/plugins/pychrysalide/analysis/db/items/comment.c
index 6d05403..6a9f990 100644
--- a/plugins/pychrysalide/analysis/db/items/comment.c
+++ b/plugins/pychrysalide/analysis/db/items/comment.c
@@ -71,7 +71,7 @@ static PyObject *py_db_comment_new(PyTypeObject *type, PyObject *args, PyObject
     int repeatable;                         /* Note une répétition demandée*/
     const char *text;                       /* Eventuel premier commentaire*/
     int before;                             /* Indication sur l'emplacement*/
-    vmpa2t addr;                            /* Emplacement ciblé           */
+    vmpa2t *addr;                           /* Emplacement ciblé           */
     unsigned long flags;                    /* Identifiants de ligne visée */
     int ret;                                /* Bilan de lecture des args.  */
     GDbComment *comment;                    /* Version GLib du commentaire */
@@ -92,26 +92,34 @@ static PyObject *py_db_comment_new(PyTypeObject *type, PyObject *args, PyObject
 
     if (flags > BLF_ALL)
     {
+        clean_vmpa_arg(addr);
+
         PyErr_SetString(PyExc_ValueError, _("Invalid flag combination"));
         return NULL;
+
     }
 
     if ((repeatable == -1 && before == -1) || (repeatable != -1 && before != -1))
     {
+        clean_vmpa_arg(addr);
+
         PyErr_SetString(PyExc_ValueError, _("repeatable or before has to be defined"));
         return NULL;
+
     }
 
     /* Construction */
 
     if (repeatable)
-        comment = g_db_comment_new_inlined(&addr, flags, repeatable);
+        comment = g_db_comment_new_inlined(addr, flags, repeatable);
     else
-        comment = g_db_comment_new_area(&addr, flags, text, before);
+        comment = g_db_comment_new_area(addr, flags, text, before);
 
     result = pygobject_new(G_OBJECT(comment));
     g_object_unref(comment);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
diff --git a/plugins/pychrysalide/arch/processor.c b/plugins/pychrysalide/arch/processor.c
index f356a91..c356fa4 100644
--- a/plugins/pychrysalide/arch/processor.c
+++ b/plugins/pychrysalide/arch/processor.c
@@ -645,28 +645,22 @@ static PyObject *py_arch_processor_disassemble(PyObject *self, PyObject *args)
     PyObject *result;                       /* Instance à retourner        */
     GProcContext *ctx;                      /* Contexte de désassemblage   */
     GBinContent *content;                   /* Contenu binaire à parcourir */
-    PyObject *pypos;                        /* Position en objet Python    */
+    vmpa2t *addr;                           /* Position d'analyse courante */
     GExeFormat *format;                     /* Format de fichier associé   */
     int ret;                                /* Bilan de lecture des args.  */
-    vmpa2t pos;                             /* Position d'analyse courante */
     GArchProcessor *proc;                   /* Processeur manipulé         */
     GArchInstruction *instr;                /* Instruction mise en place   */
 
     ret = PyArg_ParseTuple(args, "O&O&OO&",
                            convert_to_proc_context, &ctx,
                            convert_to_binary_content, &content,
-                           &pypos,
+                           convert_any_to_vmpa, &addr,
                            convert_to_executable_format, &format);
     if (!ret) return NULL;
 
-    ret = convert_any_to_vmpa(pypos, &pos);
-    if (ret != 1) return NULL;
-
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
 
-    instr = g_arch_processor_disassemble(proc, ctx, content, &pos, format);
-
-    copy_vmpa(get_internal_vmpa(pypos), &pos);
+    instr = g_arch_processor_disassemble(proc, ctx, content, addr, format);
 
     if (instr != NULL)
     {
@@ -679,6 +673,8 @@ static PyObject *py_arch_processor_disassemble(PyObject *self, PyObject *args)
         Py_INCREF(result);
     }
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -706,7 +702,7 @@ static PyObject *py_arch_processor_disassemble(PyObject *self, PyObject *args)
 static PyObject *py_arch_processor_add_error(PyObject *self, PyObject *args)
 {
     ArchProcessingError type;               /* Type d'erreur détectée      */
-    vmpa2t addr;                            /* Position d'une erreur       */
+    vmpa2t *addr;                           /* Position d'une erreur       */
     const char *desc;                       /* Description d'une erreur    */
     int ret;                                /* Bilan de lecture des args.  */
     GArchProcessor *proc;                   /* Processeur manipulé         */
@@ -716,7 +712,9 @@ static PyObject *py_arch_processor_add_error(PyObject *self, PyObject *args)
 
     proc = G_ARCH_PROCESSOR(pygobject_get(self));
 
-    g_arch_processor_add_error(proc, type, &addr, desc);
+    g_arch_processor_add_error(proc, type, addr, desc);
+
+    clean_vmpa_arg(addr);
 
     Py_RETURN_NONE;
 
diff --git a/plugins/pychrysalide/arch/vmpa.c b/plugins/pychrysalide/arch/vmpa.c
index aa745cf..af4821d 100644
--- a/plugins/pychrysalide/arch/vmpa.c
+++ b/plugins/pychrysalide/arch/vmpa.c
@@ -26,10 +26,13 @@
 
 
 #include <assert.h>
+#include <malloc.h>
+#include <stddef.h>
 #include <string.h>
 
 
 #include <i18n.h>
+#include <common/macros.h>
 
 
 #include "constants.h"
@@ -38,26 +41,22 @@
 
 
 
-
-
-
-
-
-
 /* ---------------------- DEFINITION D'UNE POSITION EN MEMOIRE ---------------------- */
 
 
-
+/* Encapsulation d'une localisation */
 typedef struct _py_vmpa_t
 {
-    PyObject_HEAD
+    PyObject_HEAD                           /* Préambule Python            */
 
-    vmpa2t addr;
+    vmpa2t addr;                            /* Elément natif               */
+    bool tmp_arg;                           /* Nature de l'objet Python    */
 
 } py_vmpa_t;
 
 
-
+/* Initialise un objet Python de type 'vmpa2t'. */
+static int py_vmpa_init(py_vmpa_t *, PyObject *, PyObject *);
 
 /* Fournit une représentation d'une variable 'vmpa_t'. */
 static PyObject *py_vmpa_to_str(PyObject *);
@@ -71,33 +70,30 @@ static PyObject *py_vmpa_get_value(PyObject *, void *);
 /* Définit une partie du contenu de la position représentée. */
 static int py_vmpa_set_value(PyObject *, PyObject *, void *);
 
-/* Initialise un objet Python de type 'vmpa2t'. */
-static int py_vmpa_init(py_vmpa_t *, PyObject *, PyObject *);
-
 /* Effectue une conversion d'un objet Python en type 'vmpa_t'. */
 static bool convert_pyobj_to_vmpa(PyObject *, vmpa2t *);
 
 /* Effectue une opération de type 'add' avec le type 'vmpa'. */
 static PyObject *py_vmpa_nb_add(PyObject *, PyObject *);
 
-/* Définit les constantes pour les localisations. */
-static bool py_vmpa_define_constants(PyTypeObject *);
-
 
 
 /* ------------------------ DEFINITION D'UNE ZONE EN MEMOIRE ------------------------ */
 
 
-/* Couverture mémoire */
+/* Encapsulation d'une couverture mémoire */
 typedef struct _py_mrange_t
 {
     PyObject_HEAD                           /* Préambule Python            */
 
-    mrange_t range;                         /* Informations internes       */
+    mrange_t range;                         /* Elément natif               */
 
 } py_mrange_t;
 
 
+/* Initialise un objet Python de type 'mrange_t'. */
+static int py_mrange_init(py_mrange_t *, PyObject *, PyObject *);
+
 /* Fournit une représentation d'une variable 'mrange_t'. */
 static PyObject *py_mrange_to_str(PyObject *);
 
@@ -131,20 +127,66 @@ static PyObject *py_mrange_get_end_addr(PyObject *, void *);
 
 
 
-/* Initialise un objet Python de type 'mrange_t'. */
-static int py_mrange_init(py_mrange_t *, PyObject *, PyObject *);
+/* ---------------------------------------------------------------------------------- */
+/*                        DEFINITION D'UNE POSITION EN MEMOIRE                        */
+/* ---------------------------------------------------------------------------------- */
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance d'objet à initialiser.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
+*                                                                             *
+*  Description : Initialise un objet Python de type 'vmpa2t'.                 *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+static int py_vmpa_init(py_vmpa_t *self, PyObject *args, PyObject *kwds)
+{
+    int result;                             /* Bilan à retourner           */
+    unsigned long long phy;                 /* Position physique           */
+    unsigned long long virt;                /* Adresse en mémoire virtuelle*/
+    int ret;                                /* Bilan de lecture des args.  */
 
+#define VMPA_DOC                                                            \
+    "VMPA stands for Virtual Memory or Physical Address.\n"                 \
+    "\n"                                                                    \
+    "Thus vmpa objects are locations inside a binary content. Their"        \
+    " coordinates are composed of a physical offset and a virtual address." \
+    " Both of them can be undefined thanks to special values"               \
+    " pychrysalide.arch.vmpa.VmpaSpecialValue."                             \
+    "\n"                                                                    \
+    "Instances can be created using the following constructor:\n"           \
+    "\n"                                                                    \
+    "    vmpa(phys=NO_PHYSICAL, virt=NO_VIRTUAL)"                           \
+    "\n"                                                                    \
+    "Where phys and virt are the values of the physical and virtual"        \
+    " positions for the location."
 
+    result = -1;
 
+    phy = VMPA_NO_PHYSICAL;
+    virt = VMPA_NO_VIRTUAL;
 
-/* ---------------------------------------------------------------------------------- */
-/*                        DEFINITION D'UNE POSITION EN MEMOIRE                        */
-/* ---------------------------------------------------------------------------------- */
+    ret = PyArg_ParseTuple(args, "|KK", &phy, &virt);
+    if (!ret) goto exit;
+
+    init_vmpa(&self->addr, phy, virt);
 
+    self->tmp_arg = false;
 
+    result = 0;
+
+ exit:
+
+    return result;
+
+}
 
 
 /******************************************************************************
@@ -380,48 +422,6 @@ static int py_vmpa_set_value(PyObject *self, PyObject *value, void *closure)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : self = instance d'objet à initialiser.                       *
-*                args = arguments passés pour l'appel.                        *
-*                kwds = mots clefs éventuellement fournis en complément.      *
-*                                                                             *
-*  Description : Initialise un objet Python de type 'vmpa2t'.                 *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static int py_vmpa_init(py_vmpa_t *self, PyObject *args, PyObject *kwds)
-{
-    int result;                             /* Bilan à retourner           */
-    unsigned long long phy;                 /* Position physique           */
-    unsigned long long virt;                /* Adresse en mémoire virtuelle*/
-    int ret;                                /* Bilan de lecture des args.  */
-
-    result = -1;
-
-    phy = VMPA_NO_PHYSICAL;
-    virt = VMPA_NO_VIRTUAL;
-
-    ret = PyArg_ParseTuple(args, "|KK", &phy, &virt);
-    if (!ret) goto exit;
-
-    init_vmpa(&self->addr, phy, virt);
-
-    result = 0;
-
- exit:
-
-    return result;
-
-}
-
-
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : obj  = objet Python à tenter de convertir.                   *
 *                addr = structure équivalente pour Chrysalide.                *
 *                                                                             *
@@ -521,32 +521,6 @@ static PyObject *py_vmpa_nb_add(PyObject *o1, PyObject *o2)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : obj_type = type dont le dictionnaire est à compléter.        *
-*                                                                             *
-*  Description : Définit les constantes pour les localisations.               *
-*                                                                             *
-*  Retour      : true en cas de succès de l'opération, false sinon.           *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static bool py_vmpa_define_constants(PyTypeObject *obj_type)
-{
-    bool result;                            /* Bilan à retourner           */
-
-    result = true;
-
-    if (result) result = PyDict_AddULongMacro(obj_type, VMPA_NO_PHYSICAL);
-    if (result) result = PyDict_AddULongMacro(obj_type, VMPA_NO_VIRTUAL);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
 *  Paramètres  : -                                                            *
 *                                                                             *
 *  Description : Fournit un accès à une définition de type à diffuser.        *
@@ -634,7 +608,7 @@ PyTypeObject *get_python_vmpa_type(void)
 
         .tp_flags       = Py_TPFLAGS_DEFAULT,
 
-        .tp_doc         = "Python object for vmpa_t.",
+        .tp_doc         = VMPA_DOC,
 
         .tp_richcompare = py_vmpa_richcompare,
 
@@ -674,9 +648,6 @@ bool ensure_python_vmpa_is_registered(void)
         if (PyType_Ready(type) != 0)
             return false;
 
-        if (!py_vmpa_define_constants(type))
-            return false;
-
         module = get_access_to_python_module("pychrysalide.arch");
 
         if (!register_python_module_object(module, type))
@@ -763,24 +734,42 @@ PyObject *build_from_internal_vmpa(const vmpa2t *addr)
 int convert_any_to_vmpa(PyObject *arg, void *dst)
 {
     int result;                             /* Bilan à retourner           */
+#ifndef NDEBUG
+    py_vmpa_t *self;                        /* Objet Python alloué         */
+#endif
     int ret;                                /* Test intermédiaire          */
-    vmpa2t *src;                            /* Modèle de données à copier  */
     PY_LONG_LONG value;                     /* Valeur de type générique    */
     int overflow;                           /* Détection d'une grosse val. */
+    py_vmpa_t *tmp;                         /* Objet creux temporaire      */
 
     result = 0;
 
+    /* Nettoyage en cours ? */
+
+    if (arg == NULL)
+    {
+#ifndef NDEBUG
+        self = container_of(*(vmpa2t **)dst, py_vmpa_t, addr);
+        assert(self->tmp_arg);
+#endif
+
+        clean_vmpa_arg(*(vmpa2t **)dst);
+
+        result = 1;
+        goto done;
+
+    }
+
     /* Si l'objet est au bon format, rien à faire ! */
 
     ret = PyObject_IsInstance(arg, (PyObject *)get_python_vmpa_type());
 
     if (ret == 1)
     {
-        src = get_internal_vmpa(arg);
-        copy_vmpa((vmpa2t *)dst, src);
+        *((vmpa2t **)dst) = get_internal_vmpa(arg);
 
         result = 1;
-        goto catv_done;
+        goto done;
 
     }
 
@@ -793,31 +782,100 @@ int convert_any_to_vmpa(PyObject *arg, void *dst)
 
     else
     {
-        init_vmpa((vmpa2t *)dst, VMPA_NO_PHYSICAL, value);
+        tmp = malloc(sizeof(py_vmpa_t));
 
-        result = 1;
-        goto catv_done;
+        init_vmpa(&tmp->addr, VMPA_NO_PHYSICAL, value);
+
+        tmp->tmp_arg = true;
+
+        *((vmpa2t **)dst) = &tmp->addr;
+
+        result = Py_CLEANUP_SUPPORTED;
+        goto done;
 
     }
 
     PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to vmpa");
 
- catv_done:
+ done:
 
     return result;
 
 }
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : addr = localisation obtenue par lecture d'argument.          *
+*                                                                             *
+*  Description : Libère la mémoire allouée pour un passage d'argument.        *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void clean_vmpa_arg(vmpa2t *addr)
+{
+    py_vmpa_t *self;                        /* Objet Python alloué         */
+
+    self = container_of(addr, py_vmpa_t, addr);
+
+    if (self->tmp_arg)
+        free(self);
+
+}
+
+
 
 /* ---------------------------------------------------------------------------------- */
 /*                          DEFINITION D'UNE ZONE EN MEMOIRE                          */
 /* ---------------------------------------------------------------------------------- */
 
 
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : self = instance d'objet à initialiser.                       *
+*                args = arguments passés pour l'appel.                        *
+*                kwds = mots clefs éventuellement fournis en complément.      *
+*                                                                             *
+*  Description : Initialise un objet Python de type 'mrange_t'.               *
+*                                                                             *
+*  Retour      : Bilan de l'opération.                                        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
 
+static int py_mrange_init(py_mrange_t *self, PyObject *args, PyObject *kwds)
+{
+    int result;                             /* Bilan à retourner           */
+    PyObject *py_vmpa;                      /* Localisation version Python */
+    unsigned long long length;              /* Taille physique             */
+    int ret;                                /* Bilan de lecture des args.  */
+    vmpa2t *addr;                           /* Localisation version C      */
 
+    result = -1;
 
+    ret = PyArg_ParseTuple(args, "OK", &py_vmpa, &length);
+    if (!ret) goto exit;
+
+    ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type());
+    if (!ret) goto exit;
+
+    addr = get_internal_vmpa(py_vmpa);
+    if (addr == NULL) goto exit;
+
+    init_mrange(&self->range, addr, length);
+
+    result = 0;
+
+ exit:
+
+    return result;
+
+}
 
 
 /******************************************************************************
@@ -1130,51 +1188,6 @@ static PyObject *py_mrange_get_end_addr(PyObject *self, void *closure)
 
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : self = instance d'objet à initialiser.                       *
-*                args = arguments passés pour l'appel.                        *
-*                kwds = mots clefs éventuellement fournis en complément.      *
-*                                                                             *
-*  Description : Initialise un objet Python de type 'mrange_t'.               *
-*                                                                             *
-*  Retour      : Bilan de l'opération.                                        *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static int py_mrange_init(py_mrange_t *self, PyObject *args, PyObject *kwds)
-{
-    int result;                             /* Bilan à retourner           */
-    PyObject *py_vmpa;                      /* Localisation version Python */
-    unsigned long long length;              /* Taille physique             */
-    int ret;                                /* Bilan de lecture des args.  */
-    vmpa2t *addr;                           /* Localisation version C      */
-
-    result = -1;
-
-    ret = PyArg_ParseTuple(args, "OK", &py_vmpa, &length);
-    if (!ret) goto exit;
-
-    ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type());
-    if (!ret) goto exit;
-
-    addr = get_internal_vmpa(py_vmpa);
-    if (addr == NULL) goto exit;
-
-    init_mrange(&self->range, addr, length);
-
-    result = 0;
-
- exit:
-
-    return result;
-
-}
-
-
-
 
 
 
@@ -1379,13 +1392,13 @@ int convert_any_to_mrange(PyObject *arg, void *dst)
         copy_mrange((mrange_t *)dst, src);
 
         result = 1;
-        goto catm_done;
+        goto done;
 
     }
 
     PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to mrange");
 
- catm_done:
+ done:
 
     return result;
 
diff --git a/plugins/pychrysalide/arch/vmpa.h b/plugins/pychrysalide/arch/vmpa.h
index 9b5ee7a..526283d 100644
--- a/plugins/pychrysalide/arch/vmpa.h
+++ b/plugins/pychrysalide/arch/vmpa.h
@@ -49,6 +49,9 @@ PyObject *build_from_internal_vmpa(const vmpa2t *);
 /* Tente de convertir en adresse n'importe quoi. */
 int convert_any_to_vmpa(PyObject *, void *);
 
+/* Libère la mémoire allouée pour un passage d'argument. */
+void clean_vmpa_arg(vmpa2t *);
+
 
 
 /* ------------------------ DEFINITION D'UNE ZONE EN MEMOIRE ------------------------ */
diff --git a/plugins/pychrysalide/debug/debugger.c b/plugins/pychrysalide/debug/debugger.c
index 0a7f97c..884e644 100644
--- a/plugins/pychrysalide/debug/debugger.c
+++ b/plugins/pychrysalide/debug/debugger.c
@@ -196,7 +196,7 @@ static PyObject *py_binary_debugger_read_memory_u8(PyObject *self, PyObject *arg
     PyObject *result;                       /* Instance à retourner        */
     GBinaryDebugger *debugger;              /* Version GLib du format      */
     int ret;                                /* Bilan de lecture des args.  */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     uint8_t value;                          /* Valeur lue en mémoire       */
     bool status;                            /* Bilan de l'opération        */
 
@@ -206,7 +206,7 @@ static PyObject *py_binary_debugger_read_memory_u8(PyObject *self, PyObject *arg
     ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr);
     if (!ret) return NULL;
 
-    status = g_binary_debugger_read_memory_u8(debugger, get_virt_addr(&addr), &value);
+    status = g_binary_debugger_read_memory_u8(debugger, get_virt_addr(addr), &value);
 
     if (status)
         result = PyLong_FromUnsignedLongLong(value);
@@ -217,6 +217,8 @@ static PyObject *py_binary_debugger_read_memory_u8(PyObject *self, PyObject *arg
         Py_INCREF(result);
     }
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -240,7 +242,7 @@ static PyObject *py_binary_debugger_read_memory_u16(PyObject *self, PyObject *ar
     PyObject *result;                       /* Instance à retourner        */
     GBinaryDebugger *debugger;              /* Version GLib du format      */
     int ret;                                /* Bilan de lecture des args.  */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     uint16_t value;                         /* Valeur lue en mémoire       */
     bool status;                            /* Bilan de l'opération        */
 
@@ -250,7 +252,7 @@ static PyObject *py_binary_debugger_read_memory_u16(PyObject *self, PyObject *ar
     ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr);
     if (!ret) return NULL;
 
-    status = g_binary_debugger_read_memory_u16(debugger, get_virt_addr(&addr), &value);
+    status = g_binary_debugger_read_memory_u16(debugger, get_virt_addr(addr), &value);
 
     if (status)
         result = PyLong_FromUnsignedLongLong(value);
@@ -261,6 +263,8 @@ static PyObject *py_binary_debugger_read_memory_u16(PyObject *self, PyObject *ar
         Py_INCREF(result);
     }
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -284,7 +288,7 @@ static PyObject *py_binary_debugger_read_memory_u32(PyObject *self, PyObject *ar
     PyObject *result;                       /* Instance à retourner        */
     GBinaryDebugger *debugger;              /* Version GLib du format      */
     int ret;                                /* Bilan de lecture des args.  */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     uint32_t value;                         /* Valeur lue en mémoire       */
     bool status;                            /* Bilan de l'opération        */
 
@@ -294,7 +298,7 @@ static PyObject *py_binary_debugger_read_memory_u32(PyObject *self, PyObject *ar
     ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr);
     if (!ret) return NULL;
 
-    status = g_binary_debugger_read_memory_u32(debugger, get_virt_addr(&addr), &value);
+    status = g_binary_debugger_read_memory_u32(debugger, get_virt_addr(addr), &value);
 
     if (status)
         result = PyLong_FromUnsignedLongLong(value);
@@ -305,6 +309,8 @@ static PyObject *py_binary_debugger_read_memory_u32(PyObject *self, PyObject *ar
         Py_INCREF(result);
     }
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -328,7 +334,7 @@ static PyObject *py_binary_debugger_read_memory_u64(PyObject *self, PyObject *ar
     PyObject *result;                       /* Instance à retourner        */
     GBinaryDebugger *debugger;              /* Version GLib du format      */
     int ret;                                /* Bilan de lecture des args.  */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     uint64_t value;                         /* Valeur lue en mémoire       */
     bool status;                            /* Bilan de l'opération        */
 
@@ -338,7 +344,7 @@ static PyObject *py_binary_debugger_read_memory_u64(PyObject *self, PyObject *ar
     ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr);
     if (!ret) return NULL;
 
-    status = g_binary_debugger_read_memory_u64(debugger, get_virt_addr(&addr), &value);
+    status = g_binary_debugger_read_memory_u64(debugger, get_virt_addr(addr), &value);
 
     if (status)
         result = PyLong_FromUnsignedLongLong(value);
@@ -349,6 +355,8 @@ static PyObject *py_binary_debugger_read_memory_u64(PyObject *self, PyObject *ar
         Py_INCREF(result);
     }
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -844,7 +852,7 @@ static PyObject *py_binary_debugger_add_mem_bp(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
     GBinaryDebugger *debugger;              /* Version GLib du format      */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     int ret;                                /* Bilan de lecture des args.  */
     bool status;                            /* Bilan de l'opération        */
 
@@ -854,11 +862,13 @@ static PyObject *py_binary_debugger_add_mem_bp(PyObject *self, PyObject *args)
     ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr);
     if (!ret) return NULL;
 
-    status = g_binary_debugger_add_memory_breakpoint(debugger, get_virt_addr(&addr));
+    status = g_binary_debugger_add_memory_breakpoint(debugger, get_virt_addr(addr));
 
     result = status ? Py_True : Py_False;
     Py_INCREF(result);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
@@ -881,7 +891,7 @@ static PyObject *py_binary_debugger_delete_mem_bp(PyObject *self, PyObject *args
 {
     PyObject *result;                       /* Instance à retourner        */
     GBinaryDebugger *debugger;              /* Version GLib du format      */
-    vmpa2t addr;                            /* Position interne associée   */
+    vmpa2t *addr;                           /* Position interne associée   */
     int ret;                                /* Bilan de lecture des args.  */
     bool status;                            /* Bilan de l'opération        */
 
@@ -891,11 +901,13 @@ static PyObject *py_binary_debugger_delete_mem_bp(PyObject *self, PyObject *args
     ret = PyArg_ParseTuple(args, "O&", convert_any_to_vmpa, &addr);
     if (!ret) return NULL;
 
-    status = g_binary_debugger_delete_memory_breakpoint(debugger, get_virt_addr(&addr));
+    status = g_binary_debugger_delete_memory_breakpoint(debugger, get_virt_addr(addr));
 
     result = status ? Py_True : Py_False;
     Py_INCREF(result);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
diff --git a/plugins/pychrysalide/format/format.c b/plugins/pychrysalide/format/format.c
index 1dc4edd..8afbca9 100644
--- a/plugins/pychrysalide/format/format.c
+++ b/plugins/pychrysalide/format/format.c
@@ -547,7 +547,7 @@ static PyObject *py_binary_format_get_symbols(PyObject *self, void *closure)
 static PyObject *py_binary_format_add_error(PyObject *self, PyObject *args)
 {
     BinaryFormatError type;                 /* Type d'erreur détectée      */
-    vmpa2t addr;                            /* Position d'une erreur       */
+    vmpa2t *addr;                           /* Position d'une erreur       */
     const char *desc;                       /* Description d'une erreur    */
     int ret;                                /* Bilan de lecture des args.  */
     GBinFormat *format;                     /* Format binaire manipulé     */
@@ -557,7 +557,9 @@ static PyObject *py_binary_format_add_error(PyObject *self, PyObject *args)
 
     format = G_BIN_FORMAT(pygobject_get(self));
 
-    g_binary_format_add_error(format, type, &addr, desc);
+    g_binary_format_add_error(format, type, addr, desc);
+
+    clean_vmpa_arg(addr);
 
     Py_RETURN_NONE;
 
diff --git a/plugins/pychrysalide/glibext/binarycursor.c b/plugins/pychrysalide/glibext/binarycursor.c
index 92a4b8c..817cc59 100644
--- a/plugins/pychrysalide/glibext/binarycursor.c
+++ b/plugins/pychrysalide/glibext/binarycursor.c
@@ -109,7 +109,7 @@ static PyObject *py_binary_cursor_new(PyTypeObject *type, PyObject *args, PyObje
 static PyObject *py_binary_cursor_update(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Instance à retourner        */
-    vmpa2t addr;                            /* Emplacement fourni          */
+    vmpa2t *addr;                           /* Emplacement fourni          */
     int ret;                                /* Bilan de lecture des args.  */
     GBinaryCursor *cursor;                  /* Version GLib du type        */
 
@@ -128,11 +128,13 @@ static PyObject *py_binary_cursor_update(PyObject *self, PyObject *args)
 
     cursor = G_BINARY_CURSOR(pygobject_get(self));
 
-    g_binary_cursor_update(cursor, &addr);
+    g_binary_cursor_update(cursor, addr);
 
     result = Py_None;
     Py_INCREF(result);
 
+    clean_vmpa_arg(addr);
+
     return result;
 
 }
diff --git a/plugins/pychrysalide/glibext/binportion.c b/plugins/pychrysalide/glibext/binportion.c
index 9ecc1eb..cbf3969 100644
--- a/plugins/pychrysalide/glibext/binportion.c
+++ b/plugins/pychrysalide/glibext/binportion.c
@@ -156,7 +156,7 @@ static PyObject *py_bin_portion_new(PyTypeObject *type, PyObject *args, PyObject
 static int py_bin_portion_init(PyObject *self, PyObject *args, PyObject *kwds)
 {
     const char *code;                       /* Identifiant de couleur      */
-    vmpa2t addr;                            /* Emplacement de portion      */
+    vmpa2t *addr;                           /* Emplacement de portion      */
     unsigned long long size;                /* Taille de la portion        */
     int ret;                                /* Bilan de lecture des args.  */
     PyObject *new_args;                     /* Nouveaux arguments épurés   */
@@ -181,7 +181,11 @@ static int py_bin_portion_init(PyObject *self, PyObject *args, PyObject *kwds)
     Py_DECREF(new_kwds);
     Py_DECREF(new_args);
 
-    if (ret == -1) return -1;
+    if (ret == -1)
+    {
+        clean_vmpa_arg(addr);
+        return -1;
+    }
 
     /* Eléments de base */
 
@@ -189,7 +193,9 @@ static int py_bin_portion_init(PyObject *self, PyObject *args, PyObject *kwds)
 
     portion->code = strdup(code);
 
-    init_mrange(&portion->range, &addr, size);
+    init_mrange(&portion->range, addr, size);
+
+    clean_vmpa_arg(addr);
 
     return 0;
 
-- 
cgit v0.11.2-87-g4458