summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2025-03-12 23:53:26 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2025-03-12 23:53:52 (GMT)
commitccb49530f930701b1ca57e560564ae098dcef3c9 (patch)
treedc4abbca57f6838ac764b545181d01a66e6521f4
parent04d5af777d42d02d0ec580373f7a50be1bfb3dac (diff)
Update and improve the operations with LEB128 values.
-rw-r--r--plugins/pychrysalide/common/Makefile.am2
-rw-r--r--plugins/pychrysalide/common/leb128.c139
-rw-r--r--plugins/pychrysalide/common/module.c4
-rw-r--r--src/common/bits.c1
-rw-r--r--src/common/leb128.c171
-rw-r--r--src/common/leb128.h11
-rw-r--r--tests/common/leb128.py80
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)