From 5792b6c860810915d62365125cafc6bff096e405 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 27 Aug 2017 20:21:17 +0200
Subject: Handled Dalvik code definition loading with more care.

---
 ChangeLog                        | 14 ++++++++++++++
 plugins/pychrysa/format/format.c |  1 +
 src/arch/processor.h             |  7 +++++--
 src/format/dex/dex-int.c         | 33 ++++++++++++++++++++++++++++++++-
 src/format/dex/method.c          |  3 +++
 src/format/format.h              |  6 +++++-
 src/gui/panels/errors.c          | 15 ++++++++++++---
 7 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 452f97c..188a52d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 17-08-27  Cyrille Bagard <nocbos@gmail.com>
 
+	* plugins/pychrysa/format/format.c:
+	* src/arch/processor.h:
+	Update code.
+
+	* src/format/dex/dex-int.c:
+	* src/format/dex/method.c:
+	Handle Dalvik code definition loading with more care.
+
+	* src/format/format.h:
+	* src/gui/panels/errors.c:
+	Update code.
+
+17-08-27  Cyrille Bagard <nocbos@gmail.com>
+
 	* src/format/dex/class.c:
 	Take into account that loading types from the Dex pool may fail.
 
diff --git a/plugins/pychrysa/format/format.c b/plugins/pychrysa/format/format.c
index 773b928..41dab9d 100644
--- a/plugins/pychrysa/format/format.c
+++ b/plugins/pychrysa/format/format.c
@@ -676,6 +676,7 @@ static bool define_python_binary_format_constants(PyTypeObject *obj_type)
 
     result = true;
 
+    result &= PyDict_AddIntMacro(obj_type, BFE_SPECIFICATION);
     result &= PyDict_AddIntMacro(obj_type, BFE_STRUCTURE);
 
     return result;
diff --git a/src/arch/processor.h b/src/arch/processor.h
index 87c0738..900db0c 100644
--- a/src/arch/processor.h
+++ b/src/arch/processor.h
@@ -102,10 +102,13 @@ GArchInstruction *g_arch_processor_get_instruction(const GArchProcessor *, size_
 
 
 /* Types d'erreurs détectées */
+
+#define PROC_ERROR(idx) ((idx << 2) | (1 << 0))
+
 typedef enum _ArchProcessingError
 {
-    APE_DISASSEMBLY = ((0 << 2) | (1 << 0)),/* Code non reconnu            */
-    APE_LABEL       = ((1 << 2) | (1 << 0)) /* Etiquette non référencée    */
+    APE_DISASSEMBLY = PROC_ERROR(0),        /* Code non reconnu            */
+    APE_LABEL       = PROC_ERROR(1)         /* Etiquette non référencée    */
 
 } ArchProcessingError;
 
diff --git a/src/format/dex/dex-int.c b/src/format/dex/dex-int.c
index c49445d..811cf5d 100644
--- a/src/format/dex/dex-int.c
+++ b/src/format/dex/dex-int.c
@@ -28,6 +28,9 @@
 #include <malloc.h>
 
 
+#include <i18n.h>
+
+
 #include "../../arch/dalvik/instruction-def.h"
 #include "../../common/endianness.h"
 
@@ -793,6 +796,7 @@ bool read_dex_code_item(const GDexFormat *format, vmpa2t *pos, code_item *item)
 {
     bool result;                            /* Bilan à retourner           */
     GBinContent *content;                   /* Contenu binaire à lire      */
+    vmpa2t origin;                          /* Mémorisation d'une position */
     uint16_t padding;                       /* Eventuel alignement         */
     uint16_t i;                             /* Boucle de parcours          */
 
@@ -808,12 +812,19 @@ bool read_dex_code_item(const GDexFormat *format, vmpa2t *pos, code_item *item)
     result &= g_binary_content_read_u32(content, pos, SRE_LITTLE, &item->insns_size);
 
     item->insns = (uint16_t *)g_binary_content_get_raw_access(content, pos, item->insns_size * sizeof(uint16_t));
+    if (item->insns == NULL) goto rdci_bad_insns;
 
     /* Padding ? */
     if (item->tries_size > 0 && item->insns_size % 2 == 1)
     {
+        copy_vmpa(&origin, pos);
+
         result &= g_binary_content_read_u16(content, pos, SRE_LITTLE, &padding);
-        assert(padding == 0);
+
+        if (padding != 0)
+            g_binary_format_add_error(G_BIN_FORMAT(format), BFE_SPECIFICATION, &origin,
+                                      _("Expected a null value as padding."));
+
     }
 
     if (item->tries_size > 0 && result)
@@ -821,6 +832,7 @@ bool read_dex_code_item(const GDexFormat *format, vmpa2t *pos, code_item *item)
         assert(get_phy_addr(pos) % 4 == 0);
 
         item->tries = (try_item *)calloc(item->tries_size, sizeof(try_item));
+        if (item->tries == NULL) goto rdci_bad_tries;
 
         for (i = 0; i < item->tries_size && result; i++)
             result &= read_dex_try_item(format, pos, &item->tries[i]);
@@ -831,10 +843,29 @@ bool read_dex_code_item(const GDexFormat *format, vmpa2t *pos, code_item *item)
             result &= read_dex_encoded_catch_handler_list(format, pos, item->handlers);
         }
 
+        else
+            item->handlers = NULL;
+
+    }
+
+    else
+    {
+        item->tries = NULL;
+        item->handlers = NULL;
     }
 
     return result;
 
+ rdci_bad_insns:
+
+    item->tries = NULL;
+
+ rdci_bad_tries:
+
+    item->handlers = NULL;
+
+    return false;
+
 }
 
 
diff --git a/src/format/dex/method.c b/src/format/dex/method.c
index ec12119..0f49154 100644
--- a/src/format/dex/method.c
+++ b/src/format/dex/method.c
@@ -157,6 +157,9 @@ static void g_dex_method_dispose(GDexMethod *method)
 
 static void g_dex_method_finalize(GDexMethod *method)
 {
+    if (method->has_body)
+        reset_dex_code_item(&method->body);
+
     G_OBJECT_CLASS(g_dex_method_parent_class)->finalize(G_OBJECT(method));
 
 }
diff --git a/src/format/format.h b/src/format/format.h
index 09ac07a..8247478 100644
--- a/src/format/format.h
+++ b/src/format/format.h
@@ -109,9 +109,13 @@ const char * const *g_binary_format_get_source_files(const GBinFormat *, size_t
 
 
 /* Types d'erreurs détectées */
+
+#define FMT_ERROR(idx) ((idx << 2) | (0 << 0))
+
 typedef enum _BinaryFormatError
 {
-    BFE_STRUCTURE = ((0 << 2) | (0 << 0))   /* Code non reconnu            */
+    BFE_SPECIFICATION = FMT_ERROR(0),       /* Non respect des specs       */
+    BFE_STRUCTURE     = FMT_ERROR(1)        /* Code non reconnu            */
 
 } BinaryFormatError;
 
diff --git a/src/gui/panels/errors.c b/src/gui/panels/errors.c
index 9f5cef4..1c2c54f 100644
--- a/src/gui/panels/errors.c
+++ b/src/gui/panels/errors.c
@@ -597,7 +597,10 @@ static void update_error_panel(GErrorPanel *panel, GtkStatusStack *status, activ
 
             if (fmt)
             {
-                if (show_format && e->ftype == BFE_STRUCTURE)
+                if (show_format && e->ftype == BFE_SPECIFICATION)
+                    visible = TRUE;
+
+                else if (show_format && e->ftype == BFE_STRUCTURE)
                     visible = TRUE;
 
             }
@@ -624,7 +627,10 @@ static void update_error_panel(GErrorPanel *panel, GtkStatusStack *status, activ
 
             if (fmt)
             {
-                if (show_format && e->ftype == BFE_STRUCTURE)
+                if (show_format && e->ftype == BFE_SPECIFICATION)
+                    icon = G_ERROR_PANEL_GET_CLASS(panel)->format_img;
+
+                else if (show_format && e->ftype == BFE_STRUCTURE)
                     icon = G_ERROR_PANEL_GET_CLASS(panel)->format_img;
 
             }
@@ -834,7 +840,10 @@ static void filter_error_panel(GErrorPanel *panel, GtkStatusStack *status, activ
 
         if (fmt)
         {
-            if (show_format && type == BFE_STRUCTURE)
+            if (show_format && type == BFE_SPECIFICATION)
+                visible = TRUE;
+
+            else if (show_format && type == BFE_STRUCTURE)
                 visible = TRUE;
 
         }
-- 
cgit v0.11.2-87-g4458