From ccb49530f930701b1ca57e560564ae098dcef3c9 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 13 Mar 2025 00:53:26 +0100
Subject: Update and improve the operations with LEB128 values.

---
 plugins/pychrysalide/common/Makefile.am |   2 +-
 plugins/pychrysalide/common/leb128.c    | 139 ++++++++++++++------------
 plugins/pychrysalide/common/module.c    |   4 +-
 src/common/bits.c                       |   1 +
 src/common/leb128.c                     | 171 ++++++++++++++++++++++++--------
 src/common/leb128.h                     |  11 +-
 tests/common/leb128.py                  |  80 ++++++---------
 7 files changed, 247 insertions(+), 161 deletions(-)

diff --git a/plugins/pychrysalide/common/Makefile.am b/plugins/pychrysalide/common/Makefile.am
index 43e1fc4..ad58900 100644
--- a/plugins/pychrysalide/common/Makefile.am
+++ b/plugins/pychrysalide/common/Makefile.am
@@ -6,7 +6,6 @@ noinst_LTLIBRARIES = libpychrysacommon.la
 # 	fnv1a.h fnv1a.c							\
 # 	hex.h hex.c								\
 # 	itoa.h itoa.c							\
-# 	leb128.h leb128.c						\
 # 	module.h module.c						\
 # 	packed.h packed.c						\
 # 	pathname.h pathname.c					\
@@ -15,6 +14,7 @@ noinst_LTLIBRARIES = libpychrysacommon.la
 libpychrysacommon_la_SOURCES =				\
 	bits.h bits.c							\
 	entropy.h entropy.c						\
+	leb128.h leb128.c						\
 	module.h module.c						\
 	xdg.h xdg.c
 
diff --git a/plugins/pychrysalide/common/leb128.c b/plugins/pychrysalide/common/leb128.c
index 8b15303..2eeb191 100644
--- a/plugins/pychrysalide/common/leb128.c
+++ b/plugins/pychrysalide/common/leb128.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * leb128.c - équivalent Python du fichier "common/leb128.c"
  *
- * Copyright (C) 2018-2020 Cyrille Bagard
+ * Copyright (C) 2018-2025 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -26,13 +26,13 @@
 
 
 #include <assert.h>
+#include <malloc.h>
 #include <pygobject.h>
 
 
 #include <common/leb128.h>
 
 
-#include "packed.h"
 #include "../access.h"
 #include "../helpers.h"
 
@@ -69,31 +69,29 @@ static PyObject *py_leb128_pack_uleb128(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Valeur à retourner          */
     uleb128_t value;                        /* Valeur à manipuler          */
-    packed_buffer_t *pbuf;                  /* Tampon de données à employer*/
     int ret;                                /* Bilan de lecture des args.  */
-    bool status;                            /* Bilan de l'opération        */
-
-#define LEB128_PACK_ULEB128_METHOD PYTHON_METHOD_DEF                \
-(                                                                   \
-    pack_uleb128, "value, pbuf",                                    \
-    METH_VARARGS, py_leb128,                                        \
-    "Pack an unsigned LEB128 value into a data buffer.\n"           \
-    "\n"                                                            \
-    "The *value* is an integer value. The *pbuf* argument has to"   \
-    " be a pychrysalide.common.PackedBuffer instance where data"    \
-    " will be appended.\n"                                          \
-    "\n"                                                            \
-    "The returned value is the operation status: *True* for"        \
-    " success, *False* for failure."                                \
+    size_t count;                           /* Nombre d'octets produits    */
+    void *bytes;                            /* Octets de représentation    */
+
+#define LEB128_PACK_ULEB128_METHOD PYTHON_METHOD_DEF    \
+(                                                       \
+    pack_uleb128, "value",                              \
+    METH_VARARGS, py_leb128,                            \
+    "Pack an unsigned LEB128 value into bytes.\n"       \
+    "\n"                                                \
+    "The *value* has to be an integer value.\n"         \
+    "\n"                                                \
+    "The returned value is byte data."                  \
 )
 
-    ret = PyArg_ParseTuple(args, "O&O&", convert_to_uleb128_value, &value, convert_to_packed_buffer, &pbuf);
+    ret = PyArg_ParseTuple(args, "O&", convert_to_uleb128_value, &value);
     if (!ret) return NULL;
 
-    status = pack_uleb128(&value, pbuf);
+    bytes = pack_uleb128(&value, &count);
 
-    result = status ? Py_True : Py_False;
-    Py_INCREF(result);
+    result = PyBytes_FromStringAndSize(bytes, count);
+
+    free(bytes);
 
     return result;
 
@@ -117,31 +115,29 @@ static PyObject *py_leb128_pack_leb128(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Valeur à retourner          */
     leb128_t value;                         /* Valeur à manipuler          */
-    packed_buffer_t *pbuf;                  /* Tampon de données à employer*/
     int ret;                                /* Bilan de lecture des args.  */
-    bool status;                            /* Bilan de l'opération        */
-
-#define LEB128_PACK_LEB128_METHOD PYTHON_METHOD_DEF                 \
-(                                                                   \
-    pack_leb128, "value, pbuf",                                     \
-    METH_VARARGS, py_leb128,                                        \
-    "Pack a signed LEB128 value into a data buffer.\n"              \
-    "\n"                                                            \
-    "The *value* is an integer value. The *pbuf* argument has to"   \
-    " be a pychrysalide.common.PackedBuffer instance where data"    \
-    " will be appended.\n"                                          \
-    "\n"                                                            \
-    "The returned value is the operation status: *True* for"        \
-    " success, *False* for failure."                                \
+    size_t count;                           /* Nombre d'octets produits    */
+    void *bytes;                            /* Octets de représentation    */
+
+#define LEB128_PACK_LEB128_METHOD PYTHON_METHOD_DEF     \
+(                                                       \
+    pack_leb128, "value",                               \
+    METH_VARARGS, py_leb128,                            \
+    "Pack a signed LEB128 value into bytes.\n"          \
+    "\n"                                                \
+    "The *value* has to be an integer value.\n"         \
+    "\n"                                                \
+    "The returned value is byte data."                  \
 )
 
-    ret = PyArg_ParseTuple(args, "O&O&", convert_to_leb128_value, &value, convert_to_packed_buffer, &pbuf);
+    ret = PyArg_ParseTuple(args, "O&", convert_to_leb128_value, &value);
     if (!ret) return NULL;
 
-    status = pack_leb128(&value, pbuf);
+    bytes = pack_leb128(&value, &count);
+
+    result = PyBytes_FromStringAndSize(bytes, count);
 
-    result = status ? Py_True : Py_False;
-    Py_INCREF(result);
+    free(bytes);
 
     return result;
 
@@ -164,33 +160,42 @@ static PyObject *py_leb128_pack_leb128(PyObject *self, PyObject *args)
 static PyObject *py_leb128_unpack_uleb128(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Valeur à retourner          */
-    packed_buffer_t *pbuf;                  /* Tampon de données à employer*/
+    const char *bytes;                      /* Octets brutes transmis      */
+    Py_ssize_t count;                       /* Quantité de ces octets      */
     int ret;                                /* Bilan de lecture des args.  */
+    const void *pos;                        /* Tëte de lecture             */
+    const void *max;                        /* Position de lecture maximale*/
     uleb128_t value;                        /* Valeur à manipuler          */
     bool status;                            /* Bilan de l'opération        */
 
 #define LEB128_UNPACK_ULEB128_METHOD PYTHON_METHOD_DEF              \
 (                                                                   \
-    unpack_uleb128, "pbuf",                                         \
+    unpack_uleb128, "buf",                                          \
     METH_VARARGS, py_leb128,                                        \
-    "Unpack an unsigned LEB128 value into a data buffer.\n"         \
+    "Unpack an unsigned LEB128 value from bytes.\n"                 \
     "\n"                                                            \
-    "The *pbuf* argument has to be a"                               \
-    " pychrysalide.common.PackedBuffer instance from where data"    \
-    " will be read.\n"                                              \
+    "The *buf* argument needs to be bytes with enough data aimed"   \
+    " to get translated into an unsigned LEB128 value.\n"           \
     "\n"                                                            \
     "The returned value depends on the operation status: *None*"    \
-    " for failure or a integer value for success."                  \
+    " for failure or a tuple with two items for success: the"       \
+    " decoded value and the remaining bytes."                       \
 )
 
-    ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf);
+    ret = PyArg_ParseTuple(args, "y#", &bytes, &count);
     if (!ret) return NULL;
 
-    status = unpack_uleb128(&value, pbuf);
+    pos = bytes;
+    max = bytes + count;
 
-    if (status)
-        result = PyLong_FromUnsignedLongLong(value);
+    status = unpack_uleb128(&value, &pos, max);
 
+    if (status)
+    {
+        result = PyTuple_New(2);
+        PyTuple_SetItem(result, 0, PyLong_FromUnsignedLongLong(value));
+        PyTuple_SetItem(result, 1, PyBytes_FromStringAndSize(pos, (char *)max - (char *)pos));
+    }
     else
     {
         result = Py_None;
@@ -218,33 +223,43 @@ static PyObject *py_leb128_unpack_uleb128(PyObject *self, PyObject *args)
 static PyObject *py_leb128_unpack_leb128(PyObject *self, PyObject *args)
 {
     PyObject *result;                       /* Valeur à retourner          */
-    packed_buffer_t *pbuf;                  /* Tampon de données à employer*/
+    const char *bytes;                      /* Octets brutes transmis      */
+    Py_ssize_t count;                       /* Quantité de ces octets      */
     int ret;                                /* Bilan de lecture des args.  */
+    const void *pos;                        /* Tëte de lecture             */
+    const void *max;                        /* Position de lecture maximale*/
     leb128_t value;                         /* Valeur à manipuler          */
     bool status;                            /* Bilan de l'opération        */
 
 #define LEB128_UNPACK_LEB128_METHOD PYTHON_METHOD_DEF               \
 (                                                                   \
-    unpack_leb128, "pbuf",                                          \
+    unpack_leb128, "buf",                                           \
     METH_VARARGS, py_leb128,                                        \
-    "Unpack a signed LEB128 value into a data buffer.\n"            \
+    "Unpack a signed LEB128 value from bytes.\n"                    \
     "\n"                                                            \
-    "The *pbuf* argument has to be a"                               \
-    " pychrysalide.common.PackedBuffer instance from where data"    \
-    " will be read.\n"                                              \
+    "\n"                                                            \
+    "The *buf* argument needs to be bytes with enough data aimed"   \
+    " to get translated into a signed LEB128 value.\n"              \
     "\n"                                                            \
     "The returned value depends on the operation status: *None*"    \
-    " for failure or a integer value for success."                  \
+    " for failure or a tuple with two items for success: the"       \
+    " decoded value and the remaining bytes."                       \
 )
 
-    ret = PyArg_ParseTuple(args, "O&", convert_to_packed_buffer, &pbuf);
+    ret = PyArg_ParseTuple(args, "y#", &bytes, &count);
     if (!ret) return NULL;
 
-    status = unpack_leb128(&value, pbuf);
+    pos = bytes;
+    max = bytes + count;
 
-    if (status)
-        result = PyLong_FromLongLong(value);
+    status = unpack_leb128(&value, &pos, max);
 
+    if (status)
+    {
+        result = PyTuple_New(2);
+        PyTuple_SetItem(result, 0, PyLong_FromLongLong(value));
+        PyTuple_SetItem(result, 1, PyBytes_FromStringAndSize(pos, (char *)max - (char *)pos));
+    }
     else
     {
         result = Py_None;
diff --git a/plugins/pychrysalide/common/module.c b/plugins/pychrysalide/common/module.c
index fa2b4de..c82c7bc 100644
--- a/plugins/pychrysalide/common/module.c
+++ b/plugins/pychrysalide/common/module.c
@@ -30,7 +30,7 @@
 //#include "fnv1a.h"
 //#include "hex.h"
 //#include "itoa.h"
-//#include "leb128.h"
+#include "leb128.h"
 //#include "packed.h"
 //#include "pathname.h"
 //#include "pearson.h"
@@ -104,11 +104,11 @@ bool populate_common_module(void)
     if (result) result = populate_common_module_with_fnv1a();
     if (result) result = populate_common_module_with_hex();
     if (result) result = populate_common_module_with_itoa();
-    if (result) result = populate_common_module_with_leb128();
     if (result) result = populate_common_module_with_pathname();
     if (result) result = populate_common_module_with_pearson();
     */
     if (result) result = populate_common_module_with_entropy();
+    if (result) result = populate_common_module_with_leb128();
     if (result) result = populate_common_module_with_xdg();
 
     if (result) result = ensure_python_bitfield_is_registered();
diff --git a/src/common/bits.c b/src/common/bits.c
index 26f570f..27296f2 100644
--- a/src/common/bits.c
+++ b/src/common/bits.c
@@ -31,6 +31,7 @@
 
 
 #include "asm.h"
+#include "io.h"
 #include "leb128.h"
 
 
diff --git a/src/common/leb128.c b/src/common/leb128.c
index 009aff6..7fae4d0 100644
--- a/src/common/leb128.c
+++ b/src/common/leb128.c
@@ -24,9 +24,20 @@
 #include "leb128.h"
 
 
+#include <malloc.h>
+
+
 #include "io.h"
 
 
+/**
+ * Quantité maximale d'octets de représentation.
+ *
+ *    sizeof([u]leb128_t) / 7 = 9.142857142857142
+ *
+ */
+#define MAX_LEB128_BYTES 9
+
 
 /******************************************************************************
 *                                                                             *
@@ -133,7 +144,7 @@ bool load_uleb128(uleb128_t *value, int fd)
     unsigned int shift;                     /* Décalage à appliquer        */
     uint8_t byte;                           /* Octet à transposer          */
 
-    result = true;
+    result = false;
 
     *value = 0;
 
@@ -142,7 +153,7 @@ bool load_uleb128(uleb128_t *value, int fd)
     while (true)
     {
         /* Encodage sur trop d'octets ? */
-        if (shift > (7 * sizeof(uleb128_t)))
+        if (shift > (7 * MAX_LEB128_BYTES))
         {
             result = false;
             break;
@@ -153,6 +164,8 @@ bool load_uleb128(uleb128_t *value, int fd)
 
         *value |= ((byte & 0x7f) << shift);
 
+        result = true;
+
         if ((byte & 0x80) == 0x00)
             break;
 
@@ -207,7 +220,7 @@ bool store_uleb128(const uleb128_t *value, int fd)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : value = valeur à consigner.                                  *
-*                pbuf  = tampon de données à constituer. [OUT]                *
+*                len   = taille du tampon de données à constitué. [OUT]       *
 *                                                                             *
 *  Description : Encode un nombre non signé encodé au format LEB128.          *
 *                                                                             *
@@ -217,26 +230,44 @@ bool store_uleb128(const uleb128_t *value, int fd)
 *                                                                             *
 ******************************************************************************/
 
-bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)
+void *pack_uleb128(const uleb128_t *value, size_t *len)
 {
-    bool result;                            /* Bilan à retourner           */
+    uint8_t *result;                        /* Données à retourner         */
     uleb128_t tmp;                          /* Valeur modifiable           */
-    uint8_t byte;                           /* Octet à transposer          */
+    uint8_t *byte;                          /* Octet à transposer          */
+
+    /* Calcul de la quantité d'octets nécessaires */
+
+    *len = 0;
 
     tmp = *value;
 
     do
     {
-        byte = (tmp & 0x7f);
+        tmp >>= 7;
+        (*len)++;
+    }
+    while (tmp != 0);
+
+    /* Exportation */
+
+    result = malloc(*len * sizeof(uint8_t));
+    byte = result;
+
+    tmp = *value;
+
+    do
+    {
+        *byte = (tmp & 0x7f);
         tmp >>= 7;
 
         if (tmp != 0)
-            byte |= 0x80;
+            *byte |= 0x80;
 
-        result = extend_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
+        byte++;
 
     }
-    while (result && tmp != 0);
+    while (tmp != 0);
 
     return result;
 
@@ -246,7 +277,7 @@ bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : value = valeur à consigner.                                  *
-*                pbuf  = tampon de données à constituer. [OUT]                *
+*                len   = taille du tampon de données à constitué. [OUT]       *
 *                                                                             *
 *  Description : Encode un nombre signé encodé au format LEB128.              *
 *                                                                             *
@@ -256,19 +287,24 @@ bool pack_uleb128(const uleb128_t *value, packed_buffer_t *pbuf)
 *                                                                             *
 ******************************************************************************/
 
-bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
+void *pack_leb128(const leb128_t *value, size_t *len)
 {
-
-    bool result;                            /* Bilan à retourner           */
+    uint8_t *result;                        /* Données à retourner         */
+    bool negative;                          /* Nature de la valeur         */
     uleb128_t tmp;                          /* Valeur modifiable           */
     bool more;                              /* Poursuite des traitements   */
-    bool negative;                          /* Nature de la valeur         */
     uint8_t byte;                           /* Octet à transposer          */
+    uint8_t *iter;                          /* Boucle de parcours          */
+
+    negative = (*value < 0);
+
+    /* Calcul de la quantité d'octets nécessaires */
+
+    *len = 0;
 
     tmp = *value;
 
     more = true;
-    negative = (*value < 0);
 
     while (more)
     {
@@ -291,10 +327,44 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
         if ((tmp == 0 && (byte & 0x40) == 0x00) || (tmp == -1 && (byte & 0x40) == 0x40))
             more = false;
 
+        (*len)++;
+
+    }
+
+    /* Exportation */
+
+    result = malloc(*len * sizeof(uint8_t));
+    iter = result;
+
+    tmp = *value;
+
+    more = true;
+
+    while (more)
+    {
+        *iter = (tmp & 0x7f);
+        tmp >>= 7;
+
+        /**
+         * Propagation forcée du bit de signe pour les implémentations de
+         * décalage basées sur une opération logique et non arithmétique.
+         */
+
+        if (negative)
+            tmp |= (~0llu << (LEB128_BITS_COUNT - 7));
+
+        /**
+         * Le bit de signe n'est pas le bit de poids fort ici :
+         * On travaille sur 7 bits, donc le masque est 0x40 !
+         */
+
+        if ((tmp == 0 && (*iter & 0x40) == 0x00) || (tmp == -1 && (*iter & 0x40) == 0x40))
+            more = false;
+
         else
-            byte |= 0x80;
+            *iter |= 0x80;
 
-        result = extend_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
+        iter++;
 
     }
 
@@ -306,7 +376,8 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : value = valeur à constituer. [OUT]                           *
-*                pbuf  = tampon de données à consulter.                       *
+*                pos   = tête de lecture à faire évoluer. [OUT]               *
+*                max   = position maximale liée à la fin des données.         *
 *                                                                             *
 *  Description : Décode un nombre non signé encodé au format LEB128.          *
 *                                                                             *
@@ -316,38 +387,45 @@ bool pack_leb128(const leb128_t *value, packed_buffer_t *pbuf)
 *                                                                             *
 ******************************************************************************/
 
-bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)
+bool unpack_uleb128(uleb128_t *value, const void **pos, const void *max)
 {
     bool result;                            /* Bilan à retourner           */
     unsigned int shift;                     /* Décalage à appliquer        */
-    uint8_t byte;                           /* Octet à transposer          */
+    uint8_t *byte;                          /* Octet à transposer          */
 
-    result = true;
+    result = false;
 
     *value = 0;
 
     shift = 0;
+    byte = *(uint8_t **)pos;
 
-    while (true)
+    do
     {
         /* Encodage sur trop d'octets ? */
-        if (shift > (7 * sizeof(uleb128_t)))
+        if (shift > (7 * MAX_LEB128_BYTES))
         {
             result = false;
             break;
         }
 
-        result = extract_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
-        if (!result) break;
+        /* Atteinte de la fin des données ? */
+        if ((void *)byte >= max)
+        {
+            result = false;
+            break;
+        }
 
-        *value |= ((byte & 0x7f) << shift);
+        *value |= ((*byte & 0x7f) << shift);
 
-        if ((byte & 0x80) == 0x00)
-            break;
+        result = true;
 
         shift += 7;
 
     }
+    while ((*byte++ & 0x80) == 0x80);
+
+    *pos = byte;
 
     return result;
 
@@ -357,7 +435,8 @@ bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : value = valeur à constituer. [OUT]                           *
-*                pbuf  = tampon de données à consulter.                       *
+*                pos   = tête de lecture à faire évoluer. [OUT]               *
+*                max   = position maximale liée à la fin des données.         *
 *                                                                             *
 *  Description : Décode un nombre signé encodé au format LEB128.              *
 *                                                                             *
@@ -367,44 +446,56 @@ bool unpack_uleb128(uleb128_t *value, packed_buffer_t *pbuf)
 *                                                                             *
 ******************************************************************************/
 
-bool unpack_leb128(leb128_t *value, packed_buffer_t *pbuf)
+bool unpack_leb128(leb128_t *value, const void **pos, const void *max)
 {
     bool result;                            /* Bilan à retourner           */
     unsigned int shift;                     /* Décalage à appliquer        */
-    uint8_t byte;                           /* Octet à transposer          */
+    uint8_t *byte;                          /* Octet à transposer          */
 
-    result = true;
+    result = false;
 
     *value = 0;
 
     shift = 0;
+    byte = *(uint8_t **)pos;
 
     do
     {
         /* Encodage sur trop d'octets ? */
-        if (shift > (7 * sizeof(leb128_t)))
+        if (shift > (7 * MAX_LEB128_BYTES))
         {
             result = false;
             break;
         }
 
-        result = extract_packed_buffer(pbuf, &byte, sizeof(uint8_t), false);
-        if (!result) break;
+        /* Atteinte de la fin des données ? */
+        if ((void *)byte >= max)
+        {
+            result = false;
+            break;
+        }
 
-        *value |= ((byte & 0x7f) << shift);
+        *value |= ((*byte & 0x7f) << shift);
+
+        result = true;
 
         shift += 7;
 
     }
-    while ((byte & 0x80) == 0x80);
+    while ((*byte++ & 0x80) == 0x80);
 
     /**
      * Le bit de signe n'est pas le bit de poids fort ici :
      * On travaille sur 7 bits, donc le masque est 0x40 !
      */
 
-    if (shift < LEB128_BITS_COUNT && (byte & 0x40) == 0x40)
-        *value |= (~0llu << shift);
+    if (result)
+    {
+        if (shift < LEB128_BITS_COUNT && (byte[-1] & 0x40) == 0x40)
+            *value |= (~0llu << shift);
+    }
+
+    *pos = byte;
 
     return result;
 
diff --git a/src/common/leb128.h b/src/common/leb128.h
index 0313f5c..cb712a3 100644
--- a/src/common/leb128.h
+++ b/src/common/leb128.h
@@ -30,7 +30,6 @@
 
 
 #include "datatypes.h"
-#include "packed.h"
 
 
 
@@ -65,16 +64,16 @@ bool load_uleb128(uleb128_t *, int);
 bool store_uleb128(const uleb128_t *, int);
 
 /* Encode un nombre non signé encodé au format LEB128. */
-bool pack_uleb128(const uleb128_t *, packed_buffer_t *);
+void *pack_uleb128(const uleb128_t *, size_t *);
 
 /* Encode un nombre signé encodé au format LEB128. */
-bool pack_leb128(const leb128_t *, packed_buffer_t *);
+void *pack_leb128(const leb128_t *, size_t *);
 
-/* Décode un nombre non signé encodé au format LEB128. */
-bool unpack_uleb128(uleb128_t *, packed_buffer_t *);
+/* Encode un nombre non signé encodé au format LEB128. */
+bool unpack_uleb128(uleb128_t *, const void **, const void *);
 
 /* Décode un nombre signé encodé au format LEB128. */
-bool unpack_leb128(leb128_t *, packed_buffer_t *);
+bool unpack_leb128(leb128_t *, const void **, const void *);
 
 
 
diff --git a/tests/common/leb128.py b/tests/common/leb128.py
index db3013e..037af4d 100644
--- a/tests/common/leb128.py
+++ b/tests/common/leb128.py
@@ -1,7 +1,6 @@
 
 from chrysacase import ChrysalideTestCase
 from pychrysalide.common import pack_uleb128, unpack_uleb128, pack_leb128, unpack_leb128
-from pychrysalide.common import PackedBuffer
 
 
 class TestLEB128Values(ChrysalideTestCase):
@@ -16,34 +15,30 @@ class TestLEB128Values(ChrysalideTestCase):
             128: b'\x80\x01',
         }
 
-        for value, encoding in cases.items():
-
-            pbuf = PackedBuffer()
+        # Lecture depuis des blocs individuels
 
-            status = pack_uleb128(value, pbuf)
-            self.assertTrue(status)
+        for value, encoding in cases.items():
 
-            self.assertEqual(pbuf.payload_length, len(encoding))
+            self.assertEqual(pack_uleb128(value), encoding)
 
-            pbuf.rewind()
+            v, r = unpack_uleb128(encoding)
 
-            got = pbuf.extract(len(encoding))
+            self.assertEqual(value, v)
+            self.assertEqual(b'', r)
 
-            self.assertEqual(got, encoding)
+        # Lecture depuis un bloc commun
 
-            self.assertFalse(pbuf.more_data)
+        data = b''.join(cases.values())
 
-        for value, encoding in cases.items():
+        values = []
 
-            pbuf = PackedBuffer()
-            pbuf.extend(encoding, False)
+        while len(data) > 0:
 
-            pbuf.rewind()
+            val, data = unpack_uleb128(data)
 
-            got = unpack_uleb128(pbuf)
-            self.assertIsNotNone(got)
+            values.append(val)
 
-            self.assertEqual(got, value)
+        self.assertEqual(values, [ k for k in cases.keys() ])
 
 
     def testSignedLeb128Encoding(self):
@@ -55,54 +50,39 @@ class TestLEB128Values(ChrysalideTestCase):
             -9001: b'\xd7\xb9\x7f',
         }
 
-        for value, encoding in cases.items():
+        # Lecture depuis des blocs individuels
 
-            pbuf = PackedBuffer()
+        for value, encoding in cases.items():
 
-            status = pack_leb128(value, pbuf)
-            self.assertTrue(status)
+            self.assertEqual(pack_leb128(value), encoding)
 
-            self.assertEqual(pbuf.payload_length, len(encoding))
+            v, r = unpack_leb128(encoding)
 
-            pbuf.rewind()
+            self.assertEqual(value, v)
+            self.assertEqual(b'', r)
 
-            got = pbuf.extract(len(encoding))
+        # Lecture depuis un bloc commun
 
-            self.assertEqual(got, encoding)
+        data = b''.join(cases.values())
 
-            self.assertFalse(pbuf.more_data)
+        values = []
 
-        for value, encoding in cases.items():
+        while len(data) > 0:
 
-            pbuf = PackedBuffer()
-            pbuf.extend(encoding, False)
+            val, data = unpack_leb128(data)
 
-            pbuf.rewind()
+            values.append(val)
 
-            got = unpack_leb128(pbuf)
-            self.assertIsNotNone(got)
-
-            self.assertEqual(got, value)
+        self.assertEqual(values, [ k for k in cases.keys() ])
 
 
     def testTooBigLeb128Encodings(self):
         """Prevent overflow for LEB128 values."""
 
-        pbuf = PackedBuffer()
-        pbuf.extend(b'\x80' * 10 + b'\x7f', False)
-
-        pbuf.rewind()
-
-        got = unpack_uleb128(pbuf)
-
-        self.assertIsNone(got)
-
-        pbuf = PackedBuffer()
-        pbuf.extend(b'\x80' * 10 + b'\x7f', False)
-
-        pbuf.rewind()
+        v = unpack_uleb128(b'\x80' * 10 + b'\x7f')
 
-        got = unpack_leb128(pbuf)
+        self.assertIsNone(v)
 
-        self.assertIsNone(got)
+        v = unpack_leb128(b'\x80' * 10 + b'\x7f')
 
+        self.assertIsNone(v)
-- 
cgit v0.11.2-87-g4458