From 041056d04032d41a5c092c62cbfd67b199094991 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Mon, 18 May 2020 23:50:26 +0200 Subject: Updated the Python API for string symbols. --- plugins/dex/pool.c | 2 +- plugins/elf/strings.c | 2 +- plugins/pychrysalide/format/constants.c | 100 ++++++++++++ plugins/pychrysalide/format/constants.h | 6 + plugins/pychrysalide/format/strsym.c | 274 +++++++++++++++++++++++++------- plugins/pychrysalide/format/symbol.c | 2 +- plugins/readelf/strtab.c | 2 +- src/format/strsym.c | 92 ++++++++--- src/format/strsym.h | 10 +- tests/format/strsym.py | 33 ++++ 10 files changed, 440 insertions(+), 83 deletions(-) create mode 100644 tests/format/strsym.py diff --git a/plugins/dex/pool.c b/plugins/dex/pool.c index cf7b794..dc9031b 100644 --- a/plugins/dex/pool.c +++ b/plugins/dex/pool.c @@ -387,7 +387,7 @@ GBinSymbol *g_dex_pool_get_string_symbol(GDexPool *pool, uint32_t index) base = G_BIN_FORMAT(pool->format); - new = g_string_symbol_new_read_only(base, &range, SET_MUTF_8); + new = g_string_symbol_new_read_only(SET_MUTF_8, base, &range); if (new != NULL) g_string_symbol_build_label(G_STR_SYMBOL(new), base); diff --git a/plugins/elf/strings.c b/plugins/elf/strings.c index 7a2b34a..9b14753 100644 --- a/plugins/elf/strings.c +++ b/plugins/elf/strings.c @@ -359,7 +359,7 @@ static bool do_elf_string_loading(GElfLoading *loading, GElfFormat *format, phys { range = g_arch_instruction_get_range(instr); - symbol = g_string_symbol_new_read_only(base, range, SET_GUESS); + symbol = g_string_symbol_new_read_only(SET_GUESS, base, range); g_object_ref(G_OBJECT(symbol)); diff --git a/plugins/pychrysalide/format/constants.c b/plugins/pychrysalide/format/constants.c index 0df7bd4..9669b46 100644 --- a/plugins/pychrysalide/format/constants.c +++ b/plugins/pychrysalide/format/constants.c @@ -26,6 +26,7 @@ #include +#include #include @@ -159,3 +160,102 @@ bool define_binary_symbol_constants(PyTypeObject *type) return result; } + + +/****************************************************************************** +* * +* Paramètres : type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les symboles liés à des chaînes. * +* * +* Retour : true en cas de succès de l'opération, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool define_string_symbol_constants(PyTypeObject *type) +{ + bool result; /* Bilan à retourner */ + PyObject *values; /* Groupe de valeurs à établir */ + + result = true; + + values = PyDict_New(); + + if (result) result = add_const_to_group(values, "NONE", SET_NONE); + if (result) result = add_const_to_group(values, "ASCII", SET_ASCII); + if (result) result = add_const_to_group(values, "UTF_8", SET_UTF_8); + if (result) result = add_const_to_group(values, "MUTF_8", SET_MUTF_8); + if (result) result = add_const_to_group(values, "GUESS", SET_GUESS); + + if (!result) + { + Py_DECREF(values); + goto exit; + } + + result = attach_constants_group_to_type(type, false, "StringEncodingType", values, + "Kinds of encoding for strings."); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : arg = argument quelconque à tenter de convertir. * +* dst = destination des valeurs récupérées en cas de succès. * +* * +* Description : Tente de convertir en constante StringEncodingType. * +* * +* Retour : Bilan de l'opération, voire indications supplémentaires. * +* * +* Remarques : - * +* * +******************************************************************************/ + +int convert_to_string_encoding_type(PyObject *arg, void *dst) +{ + int result; /* Bilan à retourner */ + unsigned long value; /* Valeur transcrite */ + + result = PyObject_IsInstance(arg, (PyObject *)&PyLong_Type); + + switch (result) + { + case -1: + /* L'exception est déjà fixée par Python */ + result = 0; + break; + + case 0: + PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to StringEncodingType"); + break; + + case 1: + value = PyLong_AsUnsignedLong(arg); + + if (value > SET_GUESS) + { + PyErr_SetString(PyExc_TypeError, "invalid value for StringEncodingType"); + result = 0; + } + + else + *((StringEncodingType *)dst) = value; + + break; + + default: + assert(false); + break; + + } + + return result; + +} diff --git a/plugins/pychrysalide/format/constants.h b/plugins/pychrysalide/format/constants.h index ad7b9a5..bbed6ae 100644 --- a/plugins/pychrysalide/format/constants.h +++ b/plugins/pychrysalide/format/constants.h @@ -37,6 +37,12 @@ bool define_binary_format_constants(PyTypeObject *); /* Définit les constantes pour les symboles binaires. */ bool define_binary_symbol_constants(PyTypeObject *); +/* Définit les constantes pour les symboles liés à des chaînes. */ +bool define_string_symbol_constants(PyTypeObject *); + +/* Tente de convertir en constante StringEncodingType. */ +int convert_to_string_encoding_type(PyObject *, void *); + #endif /* _PLUGINS_PYCHRYSALIDE_FORMAT_CONSTANTS_H */ diff --git a/plugins/pychrysalide/format/strsym.c b/plugins/pychrysalide/format/strsym.c index e465002..2824677 100644 --- a/plugins/pychrysalide/format/strsym.c +++ b/plugins/pychrysalide/format/strsym.c @@ -33,15 +33,33 @@ #include +#include +#include "constants.h" +#include "format.h" #include "symbol.h" #include "../access.h" #include "../helpers.h" #include "../arch/feeder.h" +#include "../arch/vmpa.h" +/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */ + + +/* Accompagne la création d'une instance dérivée en Python. */ +static PyObject *py_string_symbol_new(PyTypeObject *, PyObject *, PyObject *); + +/* Initialise une instance sur la base du dérivé de GObject. */ +static int py_string_symbol_init(PyObject *, PyObject *, PyObject *); + + + +/* ----------------------- VITRINE POUR CHAINES DE CARACTERES ----------------------- */ + + /* Indique si une chaîne de caractères est liée au format. */ static PyObject *py_string_symbol_get_structural(PyObject *, void *); @@ -57,10 +75,173 @@ static PyObject *py_string_symbol_get_raw(PyObject *, void *); /* Fournit la chaîne de caractères du symbole. */ static PyObject *py_string_symbol_get_utf8(PyObject *, void *); -/* Définit les constantes pour les chaînes de caractères. */ -static bool py_string_symbol_define_constants(PyTypeObject *); +/* ---------------------------------------------------------------------------------- */ +/* GLUE POUR CREATION DEPUIS PYTHON */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : type = type du nouvel objet à mettre en place. * +* args = éventuelle liste d'arguments. * +* kwds = éventuel dictionnaire de valeurs mises à disposition. * +* * +* Description : Accompagne la création d'une instance dérivée en Python. * +* * +* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_string_symbol_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + PyObject *result; /* Objet à retourner */ + PyTypeObject *base; /* Type de base à dériver */ + bool first_time; /* Evite les multiples passages*/ + GType gtype; /* Nouveau type de processeur */ + bool status; /* Bilan d'un enregistrement */ + + /* Validations diverses */ + + base = get_python_string_symbol_type(); + + if (type == base) + goto simple_way; + + /* Mise en place d'un type dédié */ + + first_time = (g_type_from_name(type->tp_name) == 0); + + gtype = build_dynamic_type(G_TYPE_STR_SYMBOL, type->tp_name, NULL, NULL, NULL); + + if (first_time) + { + status = register_class_for_dynamic_pygobject(gtype, type, base); + + if (!status) + { + result = NULL; + goto exit; + } + + } + + /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */ + + simple_way: + + result = PyType_GenericNew(type, args, kwds); + + exit: + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : self = objet à initialiser (théoriquement). * +* args = arguments fournis à l'appel. * +* kwds = arguments de type key=val fournis. * +* * +* Description : Initialise une instance sur la base du dérivé de GObject. * +* * +* Retour : 0. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static int py_string_symbol_init(PyObject *self, PyObject *args, PyObject *kwds) +{ + StringEncodingType encoding; /* Encodage spécifié */ + GBinFormat *format; /* Format au contenu à relire */ + mrange_t range; /* Version native d'un espace */ + const char *string; /* Chaîne de caractères soumise*/ + vmpa2t *addr; /* Emplacement de chaîne */ + int ret; /* Bilan de lecture des args. */ + GStrSymbol *symbol; /* Version GLib du symbole */ + + static char *kwlist[] = { "encoding", "format", "range", "string", "addr", NULL }; + +#define STRING_SYMBOL_DOC \ + "StrSymbol is a special symbol object dedicated to strings.\n" \ + "\n" \ + "Instances can be created using one of the following constructors:\n" \ + "\n" \ + " StrSymbol(encoding, format=pychrysalide.format.BinFormat," \ + " range=pychrysalide.arch.mrange)" \ + "\n" \ + " StrSymbol(encoding, string=string, addr=pychrysalide.arch.vmpa)" \ + "\n" \ + "The first constructor is aimed to be used for read-only strings available" \ + " from the raw data of the analyzed binary. The format provides the raw" \ + " content, and the memory range specifies the location of the string.\n" \ + "\n" \ + "The second constructor is useful for strings which can not be extracted" \ + " directly from the original content, such as obfuscted strings. A dynamic" \ + " string is then provided here, and the start point of this string has to" \ + " be provided.\n" \ + "\n" \ + "In both cases, the encoding remains the first argument, as a" \ + " pychrysalide.format.StrSymbol.StringEncodingType value." + + /* Récupération des paramètres */ + + format = NULL; + string = NULL; + addr = NULL; + + ret = PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&sO&", kwlist, + convert_to_string_encoding_type, &encoding, + convert_to_binary_format, &format, + convert_any_to_mrange, &range, + &string, convert_any_to_vmpa, &addr); + if (!ret) return -1; + + /* Initialisation d'un objet GLib */ + + ret = forward_pygobjet_init(self); + if (ret == -1) return -1; + + /* Eléments de base */ + + symbol = G_STR_SYMBOL(pygobject_get(self)); + + if (format != NULL) + g_string_symbol_init_read_only(symbol, encoding, format, &range); + + else if (string != NULL && addr != NULL) + { + g_string_symbol_init_dynamic(symbol, encoding, string, addr); + clean_vmpa_arg(addr); + } + + else + { + PyErr_SetString(PyExc_ValueError, _("Invalid argument combination.")); + + if (addr != NULL) + clean_vmpa_arg(addr); + + return -1; + + } + + return 0; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* VITRINE POUR CHAINES DE CARACTERES */ +/* ---------------------------------------------------------------------------------- */ + /****************************************************************************** * * @@ -149,10 +330,17 @@ static PyObject *py_string_symbol_get_encoding(PyObject *self, void *closure) GStrSymbol *symbol; /* Elément à consulter */ StringEncodingType encoding; /* Encodage associé à la chaîne*/ +#define STRING_SYMBOL_ENCODING_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + encoding, py_string_symbol, \ + "Encoding of the string, provided as a" \ + " pychrysalide.format.StrSymbol.StringEncodingType value." \ +) + symbol = G_STR_SYMBOL(pygobject_get(self)); encoding = g_string_symbol_get_encoding(symbol); - result = PyLong_FromLong(encoding); + result = cast_with_constants_group_from_type(get_python_string_symbol_type(), "StringEncodingType", encoding); return result; @@ -179,6 +367,12 @@ static PyObject *py_string_symbol_get_raw(PyObject *self, void *closure) size_t len; /* Taille de la chaîne */ const char *data; /* Données à manipuler */ +#define STRING_SYMBOL_RAW_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + raw, py_string_symbol, \ + "Raw data of the string, provided as bytes." \ +) + symbol = G_STR_SYMBOL(pygobject_get(self)); data = g_string_symbol_get_raw(symbol, &len); @@ -209,6 +403,12 @@ static PyObject *py_string_symbol_get_utf8(PyObject *self, void *closure) size_t len; /* Taille de la chaîne */ const char *data; /* Données à manipuler */ +#define STRING_SYMBOL_UTF8_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + utf8, py_string_symbol, \ + "String content as UTF-8 data." \ +) + symbol = G_STR_SYMBOL(pygobject_get(self)); data = g_string_symbol_get_utf8(symbol, &len); @@ -221,37 +421,6 @@ static PyObject *py_string_symbol_get_utf8(PyObject *self, void *closure) /****************************************************************************** * * -* Paramètres : obj_type = type dont le dictionnaire est à compléter. * -* * -* Description : Définit les constantes pour les chaînes de caractères. * -* * -* Retour : true en cas de succès de l'opération, false sinon. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool py_string_symbol_define_constants(PyTypeObject *obj_type) -{ - bool result; /* Bilan à retourner */ - - result = true; - - result &= PyDict_AddULongMacro(obj_type, SET_NONE); - - result &= PyDict_AddULongMacro(obj_type, SET_ASCII); - result &= PyDict_AddULongMacro(obj_type, SET_UTF_8); - result &= PyDict_AddULongMacro(obj_type, SET_MUTF_8); - - result &= PyDict_AddULongMacro(obj_type, SET_GUESS); - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -264,28 +433,19 @@ static bool py_string_symbol_define_constants(PyTypeObject *obj_type) PyTypeObject *get_python_string_symbol_type(void) { - static PyMethodDef py_str_symbol_methods[] = { + static PyMethodDef py_string_symbol_methods[] = { { NULL } }; - static PyGetSetDef py_str_symbol_getseters[] = { + static PyGetSetDef py_string_symbol_getseters[] = { STRING_SYMBOL_STRUCTURAL_ATTRIB, - { - "encoding", py_string_symbol_get_encoding, NULL, - "Encoding of the string.", NULL - }, - { - "raw", py_string_symbol_get_raw, NULL, - "String content as raw data.", NULL - }, - { - "utf8", py_string_symbol_get_utf8, NULL, - "String content as UTF-8 data.", NULL - }, + STRING_SYMBOL_ENCODING_ATTRIB, + STRING_SYMBOL_RAW_ATTRIB, + STRING_SYMBOL_UTF8_ATTRIB, { NULL } }; - static PyTypeObject py_str_symbol_type = { + static PyTypeObject py_string_symbol_type = { PyVarObject_HEAD_INIT(NULL, 0) @@ -294,14 +454,17 @@ PyTypeObject *get_python_string_symbol_type(void) .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - .tp_doc = "PyChrysalide string symbol", + .tp_doc = STRING_SYMBOL_DOC, - .tp_methods = py_str_symbol_methods, - .tp_getset = py_str_symbol_getseters + .tp_methods = py_string_symbol_methods, + .tp_getset = py_string_symbol_getseters, + + .tp_init = py_string_symbol_init, + .tp_new = py_string_symbol_new }; - return &py_str_symbol_type; + return &py_string_symbol_type; } @@ -335,10 +498,13 @@ bool ensure_python_string_symbol_is_registered(void) if (!ensure_python_proxy_feeder_is_registered()) return false; + if (!ensure_python_binary_symbol_is_registered()) + return false; + if (!register_class_for_pygobject(dict, G_TYPE_STR_SYMBOL, type, get_python_binary_symbol_type())) return false; - if (!py_string_symbol_define_constants(type)) + if (!define_string_symbol_constants(type)) return false; } diff --git a/plugins/pychrysalide/format/symbol.c b/plugins/pychrysalide/format/symbol.c index 7ecc576..d6d6402 100644 --- a/plugins/pychrysalide/format/symbol.c +++ b/plugins/pychrysalide/format/symbol.c @@ -270,7 +270,7 @@ static int py_binary_symbol_init(PyObject *self, PyObject *args, PyObject *kwds) mrange_t range; /* Version native d'un espace */ unsigned long stype; /* Type prévu pour le symbole */ int ret; /* Bilan de lecture des args. */ - GBinSymbol *symbol; /* Version GLib du symble */ + GBinSymbol *symbol; /* Version GLib du symbole */ #define BINARY_SYMBOL_DOC \ "BinSymbol represents all kinds of symbols, such as strings, routines or" \ diff --git a/plugins/readelf/strtab.c b/plugins/readelf/strtab.c index 2420da6..19b44bf 100644 --- a/plugins/readelf/strtab.c +++ b/plugins/readelf/strtab.c @@ -118,7 +118,7 @@ static void parse_elf_string_table(GElfFormat *format, GPreloadInfo *info, const { irange = g_arch_instruction_get_range(instr); - symbol = g_string_symbol_new_read_only(base, irange, SET_GUESS); + symbol = g_string_symbol_new_read_only(SET_GUESS, base, irange); g_object_ref(G_OBJECT(symbol)); diff --git a/src/format/strsym.c b/src/format/strsym.c index b078fe1..91232f4 100644 --- a/src/format/strsym.c +++ b/src/format/strsym.c @@ -233,9 +233,9 @@ static void g_string_symbol_finalize(GStrSymbol *symbol) /****************************************************************************** * * -* Paramètres : format = format binaire reconnu. * +* Paramètres : encoding = encodage de la chaîne de caractères à représenter.* +* format = format binaire reconnu. * * range = espace couvert par le nouveau symbole. * -* encoding = encodage de la chaîne de caractères à représenter.* * * * Description : Crée un nouveau symbole pour chaîne de caractères. * * * @@ -245,35 +245,58 @@ static void g_string_symbol_finalize(GStrSymbol *symbol) * * ******************************************************************************/ -GBinSymbol *g_string_symbol_new_read_only(GBinFormat *format, const mrange_t *range, StringEncodingType encoding) +GBinSymbol *g_string_symbol_new_read_only(StringEncodingType encoding, GBinFormat *format, const mrange_t *range) { GStrSymbol *result; /* Nouveau symbole à renvoyer */ - GBinSymbol *parent; /* Type d'instance parent */ result = g_object_new(G_TYPE_STR_SYMBOL, NULL); - parent = G_BIN_SYMBOL(result); + g_string_symbol_init_read_only(result, encoding, format, range); + + return G_BIN_SYMBOL(result); + +} + + +/****************************************************************************** +* * +* Paramètres : symbole = symbole dont la définition est à initialiser. * +* encoding = encodage de la chaîne de caractères à représenter.* +* format = format binaire reconnu. * +* range = espace couvert par le nouveau symbole. * +* * +* Description : Réalise la complète initialisation d'unsymbole pour chaîne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_string_symbol_init_read_only(GStrSymbol *symbol, StringEncodingType encoding, GBinFormat *format, const mrange_t *range) +{ + GBinSymbol *parent; /* Type d'instance parent */ + + parent = G_BIN_SYMBOL(symbol); g_binary_symbol_set_range(parent, range); g_binary_symbol_set_stype(parent, STP_RO_STRING); - result->encoding = encoding; - - result->content = g_binary_format_get_content(format); - result->has_content = true; + symbol->encoding = encoding; - g_string_symbol_check_encoding(result); + symbol->content = g_binary_format_get_content(format); + symbol->has_content = true; - return G_BIN_SYMBOL(result); + g_string_symbol_check_encoding(symbol); } /****************************************************************************** * * -* Paramètres : string = contenu de la chaîne de caractères. * +* Paramètres : encoding = encodage de la chaîne de caractères à représenter.* +* string = contenu de la chaîne de caractères. * * addr = emplacement de cette chaîne virtuelle. * -* encoding = encodage de la chaîne de caractères à représenter.* * * * Description : Crée un nouveau symbole pour chaîne de caractères. * * * @@ -283,29 +306,52 @@ GBinSymbol *g_string_symbol_new_read_only(GBinFormat *format, const mrange_t *ra * * ******************************************************************************/ -GBinSymbol *g_string_symbol_new_dynamic(const char *string, const vmpa2t *addr, StringEncodingType encoding) +GBinSymbol *g_string_symbol_new_dynamic(StringEncodingType encoding, const char *string, const vmpa2t *addr) { GStrSymbol *result; /* Nouveau symbole à renvoyer */ - GBinSymbol *parent; /* Type d'instance parent */ - mrange_t range; /* Emplacement à constituer */ result = g_object_new(G_TYPE_STR_SYMBOL, NULL); - parent = G_BIN_SYMBOL(result); + g_string_symbol_init_dynamic(result, encoding, string, addr); + + return G_BIN_SYMBOL(result); + +} + + +/****************************************************************************** +* * +* Paramètres : symbole = symbole dont la définition est à initialiser. * +* encoding = encodage de la chaîne de caractères à représenter.* +* string = contenu de la chaîne de caractères. * +* addr = emplacement de cette chaîne virtuelle. * +* * +* Description : Réalise la complète initialisation d'unsymbole pour chaîne. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_string_symbol_init_dynamic(GStrSymbol *symbol, StringEncodingType encoding, const char *string, const vmpa2t *addr) +{ + GBinSymbol *parent; /* Type d'instance parent */ + mrange_t range; /* Emplacement à constituer */ + + parent = G_BIN_SYMBOL(symbol); init_mrange(&range, addr, strlen(string)); g_binary_symbol_set_range(parent, &range); g_binary_symbol_set_stype(parent, STP_DYN_STRING); - result->encoding = encoding; + symbol->encoding = encoding; - result->string = strdup(string); - result->has_content = false; - - g_string_symbol_check_encoding(result); + symbol->string = strdup(string); + symbol->has_content = false; - return G_BIN_SYMBOL(result); + g_string_symbol_check_encoding(symbol); } diff --git a/src/format/strsym.h b/src/format/strsym.h index 2400e59..6900251 100644 --- a/src/format/strsym.h +++ b/src/format/strsym.h @@ -69,10 +69,16 @@ typedef struct _GStrSymbolClass GStrSymbolClass; GType g_string_symbol_get_type(void); /* Crée un nouveau symbole pour chaîne de caractères. */ -GBinSymbol *g_string_symbol_new_read_only(GBinFormat *, const mrange_t *, StringEncodingType); +GBinSymbol *g_string_symbol_new_read_only(StringEncodingType, GBinFormat *, const mrange_t *); + +/* Réalise la complète initialisation d'unsymbole pour chaîne. */ +void g_string_symbol_init_read_only(GStrSymbol *, StringEncodingType, GBinFormat *, const mrange_t *); /* Crée un nouveau symbole pour chaîne de caractères. */ -GBinSymbol *g_string_symbol_new_dynamic(const char *, const vmpa2t *, StringEncodingType); +GBinSymbol *g_string_symbol_new_dynamic(StringEncodingType, const char *, const vmpa2t *); + +/* Réalise la complète initialisation d'unsymbole pour chaîne. */ +void g_string_symbol_init_dynamic(GStrSymbol *, StringEncodingType, const char *, const vmpa2t *); /* Définit si une chaîne de caractères est liée au format. */ void g_string_symbol_set_structural(GStrSymbol *, bool); diff --git a/tests/format/strsym.py b/tests/format/strsym.py new file mode 100644 index 0000000..ba1d92f --- /dev/null +++ b/tests/format/strsym.py @@ -0,0 +1,33 @@ + +from chrysacase import ChrysalideTestCase +from pychrysalide.analysis import BinContent +from pychrysalide.analysis.contents import MemoryContent +from pychrysalide.arch import vmpa, mrange +from pychrysalide.format import FlatFormat, StrSymbol + + +class TestBinarySymbols(ChrysalideTestCase): + """TestCase for format.StrSymbol.""" + + def testStringSymbolConstructors(self): + """Build string symbols.""" + + data = b'ABCD1234' + + cnt = MemoryContent(data) + fmt = FlatFormat(cnt, 'xxx', BinContent.SourceEndian.LITTLE) + + saddr = vmpa(0x0, vmpa.VmpaSpecialValue.NO_VIRTUAL) + srange = mrange(saddr, 0x5) + + symbol = StrSymbol(StrSymbol.StringEncodingType.GUESS, fmt, srange) + + self.assertEqual(symbol.raw, b'ABCD1') + self.assertEqual(symbol.utf8, 'ABCD1') + self.assertEqual(symbol.encoding, StrSymbol.StringEncodingType.ASCII) + + symbol = StrSymbol(StrSymbol.StringEncodingType.GUESS, string='abcdef', addr=saddr) + + self.assertEqual(symbol.raw, b'abcdef') + self.assertEqual(symbol.utf8, 'abcdef') + self.assertEqual(symbol.encoding, StrSymbol.StringEncodingType.ASCII) -- cgit v0.11.2-87-g4458