From e827eb8bdc797d2a8c194e675bd300e97aee6166 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 4 Jan 2019 19:59:14 +0100
Subject: Handled non null-terminated strings

---
 plugins/pychrysalide/format/strsym.c | 10 ++--
 src/format/strsym.c                  | 89 ++++++++++++++++++++++++++----------
 src/format/strsym.h                  |  4 +-
 src/gui/panels/strings.c             | 10 +++-
 4 files changed, 80 insertions(+), 33 deletions(-)

diff --git a/plugins/pychrysalide/format/strsym.c b/plugins/pychrysalide/format/strsym.c
index 30224f8..8c210a2 100644
--- a/plugins/pychrysalide/format/strsym.c
+++ b/plugins/pychrysalide/format/strsym.c
@@ -73,12 +73,13 @@ static PyObject *py_string_symbol_get_raw(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Valeur à retourner          */
     GStrSymbol *symbol;                     /* Elément à consulter         */
+    size_t len;                             /* Taille de la chaîne         */
     const char *data;                       /* Données à manipuler         */
 
     symbol = G_STR_SYMBOL(pygobject_get(self));
-    data = g_string_symbol_get_raw(symbol);
+    data = g_string_symbol_get_raw(symbol, &len);
 
-    result = PyBytes_FromString(data);
+    result = PyBytes_FromStringAndSize(data, len);
 
     return result;
 
@@ -102,12 +103,13 @@ static PyObject *py_string_symbol_get_utf8(PyObject *self, void *closure)
 {
     PyObject *result;                       /* Valeur à retourner          */
     GStrSymbol *symbol;                     /* Elément à consulter         */
+    size_t len;                             /* Taille de la chaîne         */
     const char *data;                       /* Données à manipuler         */
 
     symbol = G_STR_SYMBOL(pygobject_get(self));
-    data = g_string_symbol_get_raw(symbol);
+    data = g_string_symbol_get_utf8(symbol, &len);
 
-    result = PyUnicode_FromString(data);
+    result = PyUnicode_FromStringAndSize(data, len);
 
     return result;
 
diff --git a/src/format/strsym.c b/src/format/strsym.c
index c921b9a..6feb8a1 100644
--- a/src/format/strsym.c
+++ b/src/format/strsym.c
@@ -315,7 +315,9 @@ GBinSymbol *g_string_symbol_new_dynamic(const char *string, const vmpa2t *addr,
 
 static void g_string_symbol_check_encoding(GStrSymbol *symbol)
 {
+    size_t length;                          /* Taille de la chaîne         */
     const char *string;                     /* Données à analyser          */
+    size_t i;                               /* Boucle de parcours          */
 
     switch (symbol->encoding)
     {
@@ -325,25 +327,47 @@ static void g_string_symbol_check_encoding(GStrSymbol *symbol)
         case SET_UTF_8:
         case SET_MUTF_8:
 
-            string = g_string_symbol_get_utf8(symbol);
+            string = g_string_symbol_get_utf8(symbol, &length);
 
-            if (!g_utf8_validate(string, -1, NULL))
+            if (!g_utf8_validate(string, length, NULL))
                 symbol->encoding = SET_ASCII;
 
             break;
 
         case SET_GUESS:
 
-            string = g_string_symbol_get_utf8(symbol);
+            string = g_string_symbol_get_utf8(symbol, &length);
 
-            if (g_str_is_ascii(string))
-                symbol->encoding = SET_ASCII;
+            /**
+             * Afin de ne pas réaliser d'allocation avec strndup(), on simule
+             * un appel à g_str_is_ascii() :
+             *
+             *    gboolean g_str_is_ascii (const gchar *str);
+             *
+             *    """
+             *    Determines if a string is pure ASCII. A string is pure ASCII
+             *    if it contains no bytes with the high bit set.
+             *    """"
+             */
 
-            else if (g_utf8_validate(string, -1, NULL))
-                symbol->encoding = SET_UTF_8;
+            symbol->encoding = SET_ASCII;
 
-            else
-                symbol->encoding = SET_ASCII;
+            for (i = 0; i < length; i++)
+                if (string[i] & 0x80)
+                {
+                    symbol->encoding = SET_GUESS;
+                    break;
+                }
+
+            if (symbol->encoding == SET_GUESS)
+            {
+                if (g_utf8_validate(string, -1, NULL))
+                    symbol->encoding = SET_UTF_8;
+
+                else
+                    symbol->encoding = SET_ASCII;
+
+            }
 
             break;
 
@@ -385,16 +409,17 @@ StringEncodingType g_string_symbol_get_encoding(const GStrSymbol *symbol)
 *                                                                             *
 *  Retour      : Chaîne de caractères d'origine.                              *
 *                                                                             *
-*  Remarques   : -                                                            *
+*  Remarques   : Cf. fonction g_string_symbol_get_utf8() pour l'existence     *
+*                du paramètre length.                                         *
 *                                                                             *
 ******************************************************************************/
 
-const char *g_string_symbol_get_raw(const GStrSymbol *symbol)
+const char *g_string_symbol_get_raw(const GStrSymbol *symbol, size_t *length)
 {
     const char *result;                     /* Données à retourner         */
     const mrange_t *range;                  /* Couverture du symbole       */
     vmpa2t pos;                             /* Tête de lecture modifiable  */
-    phys_t length;                          /* Taille de la chaîne         */
+    phys_t len;                             /* Taille de la chaîne         */
 
     if (symbol->has_content)
     {
@@ -402,14 +427,19 @@ const char *g_string_symbol_get_raw(const GStrSymbol *symbol)
 
         copy_vmpa(&pos, get_mrange_addr(range));
 
-        length = get_mrange_length(range);
+        len = get_mrange_length(range);
+
+        result = (const char *)g_binary_content_get_raw_access(symbol->content, &pos, len);
 
-        result = (const char *)g_binary_content_get_raw_access(symbol->content, &pos, length);
+        *length = len;
 
     }
 
     else
+    {
         result = symbol->string;
+        *length = strlen(result);
+    }
 
     return result;
 
@@ -419,21 +449,29 @@ const char *g_string_symbol_get_raw(const GStrSymbol *symbol)
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : symbol = symbole à venir consulter.                          *
+*                length = taille de la chaîne renvoyée. [OUT]                 *
 *                                                                             *
 *  Description : Fournit la chaîne de caractères du symbole.                  *
 *                                                                             *
 *  Retour      : Chaîne de caractères, à priori en UTF-8.                     *
 *                                                                             *
-*  Remarques   : -                                                            *
+*  Remarques   : Lorsque la chaîne est lue à partir du contenu brut, elle     *
+*                peut ne pas être terminée par un octet nul (c'est le cas     *
+*                avec le fichier strings.asm par exemple, dans la suite de    *
+*                tests, où la séparation est marquée par un simple retour     *
+*                chariot).                                                    *
+*                                                                             *
+*                Un appel à strlen() sur le résultat renvoyé n'est donc pas   *
+*                fiable à posteriori, donc on renseigne la taille ici.        *
 *                                                                             *
 ******************************************************************************/
 
-const char *g_string_symbol_get_utf8(const GStrSymbol *symbol)
+const char *g_string_symbol_get_utf8(const GStrSymbol *symbol, size_t *length)
 {
     const char *result;                     /* Données à retourner         */
     const mrange_t *range;                  /* Couverture du symbole       */
     vmpa2t pos;                             /* Tête de lecture modifiable  */
-    phys_t length;                          /* Taille de la chaîne         */
+    phys_t len;                             /* Taille de la chaîne         */
 
     if (symbol->has_content)
     {
@@ -441,14 +479,19 @@ const char *g_string_symbol_get_utf8(const GStrSymbol *symbol)
 
         copy_vmpa(&pos, get_mrange_addr(range));
 
-        length = get_mrange_length(range);
+        len = get_mrange_length(range);
 
-        result = (const char *)g_binary_content_get_raw_access(symbol->content, &pos, length);
+        result = (const char *)g_binary_content_get_raw_access(symbol->content, &pos, len);
+
+        *length = len;
 
     }
 
     else
+    {
         result = symbol->string;
+        *length = strlen(result);
+    }
 
     return result;
 
@@ -489,13 +532,11 @@ bool g_string_symbol_build_label(GStrSymbol *symbol, GBinFormat *format)
 
     /* Base de décision */
 
-    base = g_string_symbol_get_utf8(symbol);
+    base = g_string_symbol_get_utf8(symbol, &length);
 
     if (base == NULL)
         return false;
 
-    length = strlen(base);
-
     /* Phase de constitution */
 
     allocated = length + 5 + VMPA_MAX_LEN + 1;
@@ -691,12 +732,10 @@ void g_string_symbol_print(const GStrSymbol *symbol, GBufferLine *line)
     const char *string;                     /* Chaîne de caractères        */
     size_t len;                             /* Taille du texte à créer     */
 
-    string = g_string_symbol_get_utf8(symbol);
+    string = g_string_symbol_get_utf8(symbol, &len);
 
     g_buffer_line_append_text(line, BLC_ASSEMBLY, "\"", 1, RTT_STRING, NULL);
 
-    len = strlen(string);
-
     if (len > 0)
         g_buffer_line_append_text(line, BLC_ASSEMBLY, string, len, RTT_STRING, NULL);
 
diff --git a/src/format/strsym.h b/src/format/strsym.h
index b074a28..4a1404b 100644
--- a/src/format/strsym.h
+++ b/src/format/strsym.h
@@ -76,10 +76,10 @@ GBinSymbol *g_string_symbol_new_dynamic(const char *, const vmpa2t *, StringEnco
 StringEncodingType g_string_symbol_get_encoding(const GStrSymbol *);
 
 /* Fournit la chaîne brute de caractères du symbole. */
-const char *g_string_symbol_get_raw(const GStrSymbol *);
+const char *g_string_symbol_get_raw(const GStrSymbol *, size_t *);
 
 /* Fournit la chaîne de caractères du symbole. */
-const char *g_string_symbol_get_utf8(const GStrSymbol *);
+const char *g_string_symbol_get_utf8(const GStrSymbol *, size_t *);
 
 /* Construit une désignation pour chaîne de caractères. */
 bool g_string_symbol_build_label(GStrSymbol *, GBinFormat *);
diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c
index 5bba0ca..8814c0b 100644
--- a/src/gui/panels/strings.c
+++ b/src/gui/panels/strings.c
@@ -745,7 +745,9 @@ static void reload_strings_for_new_list_view(const GStringsPanel *panel, GtkStat
     VMPA_BUFFER(virt);                      /* Adresse virtuelle           */
     GBinPortion *portion;                   /* Zone mémoire d'appartenance */
     const char *area;                       /* Description de la zone      */
+    size_t len;                             /* Taille de la chaîne         */
     const char *text;                       /* Texte original référencé    */
+    char *real_text;                        /* Texte avec octet nul final  */
     GtkTreeIter iter;                       /* Point d'insertion           */
 
     builder = G_PANEL_ITEM(panel)->builder;
@@ -779,9 +781,11 @@ static void reload_strings_for_new_list_view(const GStringsPanel *panel, GtkStat
         area = g_binary_portion_get_desc(portion);
         g_object_unref(G_OBJECT(portion));
 
-        text = g_string_symbol_get_utf8(G_STR_SYMBOL(symbol));
+        text = g_string_symbol_get_utf8(G_STR_SYMBOL(symbol), &len);
         if (text == NULL) goto rsfnlv_next;
 
+        real_text = strndup(text, len);
+
         gtk_list_store_append(store, &iter);
         gtk_list_store_set(store, &iter,
                            STC_SYMBOL, symbol,
@@ -790,10 +794,12 @@ static void reload_strings_for_new_list_view(const GStringsPanel *panel, GtkStat
                            STC_AREA, area,
                            STC_NAME, NULL,
                            STC_VALUE, NULL,
-                           STC_ORIGINAL, text,
+                           STC_ORIGINAL, real_text,
                            STC_MATCHED, false,
                            -1);
 
+        free(real_text);
+
         update_string_node(data, store, &iter);
 
         data->count++;
-- 
cgit v0.11.2-87-g4458