From 565f89056e28576dfae47dbc347a300c5415e027 Mon Sep 17 00:00:00 2001
From: Ann Priestman <apriestman@basistech.com>
Date: Thu, 13 Oct 2016 16:58:51 -0400
Subject: [PATCH] Minor fixes to GPT processing

---
 tsk/base/tsk_base_i.h |  3 +++
 tsk/base/tsk_endian.c | 26 ++++++++++++++++++++++++++
 tsk/fs/tsk_fs_i.h     |  2 ++
 tsk/vs/gpt.c          | 20 ++++++++++----------
 tsk/vs/tsk_gpt.h      |  2 +-
 tsk/vs/tsk_vs_i.h     |  4 ++++
 6 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/tsk/base/tsk_base_i.h b/tsk/base/tsk_base_i.h
index 4506b93e3..d79787297 100644
--- a/tsk/base/tsk_base_i.h
+++ b/tsk/base/tsk_base_i.h
@@ -67,6 +67,9 @@ extern "C" {
         uint16_t);
     extern uint8_t tsk_guess_end_u32(TSK_ENDIAN_ENUM *, uint8_t *,
         uint32_t);
+    extern uint8_t tsk_guess_end_u64(TSK_ENDIAN_ENUM *, uint8_t *,
+        uint64_t);
+
 
 /** \internal
 * Read a 16-bit unsigned value.
diff --git a/tsk/base/tsk_endian.c b/tsk/base/tsk_endian.c
index fb75250e6..a69bdcbf2 100644
--- a/tsk/base/tsk_endian.c
+++ b/tsk/base/tsk_endian.c
@@ -74,3 +74,29 @@ tsk_guess_end_u32(TSK_ENDIAN_ENUM * flag, uint8_t * x, uint32_t val)
 
     return 1;
 }
+
+/** \internal
+ * same idea as tsk_guess_end_u16 except that val is a 64-bit value
+ *
+* @param flag Pointer to location where proper endian flag should be stored.
+* @param x Pointer to array of bytes to analyze.
+* @param val Target value to compare to
+* @returns 1 if match cannot be made, 0 if it can. 
+ */
+uint8_t
+tsk_guess_end_u64(TSK_ENDIAN_ENUM * flag, uint8_t * x, uint64_t val)
+{
+    /* try little */
+    if (tsk_getu64(TSK_LIT_ENDIAN, x) == val) {
+        *flag = TSK_LIT_ENDIAN;
+        return 0;
+    }
+
+    /* ok, big now */
+    if (tsk_getu64(TSK_BIG_ENDIAN, x) == val) {
+        *flag = TSK_BIG_ENDIAN;
+        return 0;
+    }
+
+    return 1;
+}
diff --git a/tsk/fs/tsk_fs_i.h b/tsk/fs/tsk_fs_i.h
index 58df7e96f..ee15e2734 100644
--- a/tsk/fs/tsk_fs_i.h
+++ b/tsk/fs/tsk_fs_i.h
@@ -239,6 +239,8 @@ extern "C" {
      tsk_guess_end_u16(&(fs->endian), (x), (mag))
 #define tsk_fs_guessu32(fs, x, mag)   \
      tsk_guess_end_u32(&(fs->endian), (x), (mag))
+#define tsk_fs_guessu64(fs, x, mag)   \
+     tsk_guess_end_u64(&(fs->endian), (x), (mag))
 #ifdef __cplusplus
 }
 #endif                          /*  */
diff --git a/tsk/vs/gpt.c b/tsk/vs/gpt.c
index d14bd1bb4..9ff999089 100644
--- a/tsk/vs/gpt.c
+++ b/tsk/vs/gpt.c
@@ -22,7 +22,7 @@
  * It is loaded into the internal sorted list 
  */
 static uint8_t
-gpt_load_table(TSK_VS_INFO * vs, GPT_TYPE_ENUM gpt_type)
+gpt_load_table(TSK_VS_INFO * vs, GPT_LOCATION_ENUM gpt_type)
 {
     gpt_head *head;
     gpt_entry *ent;
@@ -35,12 +35,8 @@ gpt_load_table(TSK_VS_INFO * vs, GPT_TYPE_ENUM gpt_type)
     TSK_DADDR_T max_addr = (vs->img_info->size - vs->offset) / vs->block_size;  // max sector
     TSK_DADDR_T gpt_relative_addr;
     TSK_DADDR_T gpt_absolute_addr;
-    TSK_DADDR_T dos_sect_relative_addr;
-    TSK_DADDR_T dos_sect_absolute_addr;
 
     if(gpt_type == PRIMARY_TABLE){
-        dos_sect_relative_addr = GPT_PART_SOFFSET;
-        dos_sect_absolute_addr = vs->offset / vs->block_size + GPT_PART_SOFFSET;
         gpt_relative_addr = GPT_PART_SOFFSET + 1;
         gpt_absolute_addr = vs->offset / vs->block_size + GPT_PART_SOFFSET + 1;
     } else {
@@ -48,7 +44,6 @@ gpt_load_table(TSK_VS_INFO * vs, GPT_TYPE_ENUM gpt_type)
         gpt_absolute_addr = (vs->img_info->size / vs->block_size) - 1;
     }
 
-
     if (tsk_verbose)
         tsk_fprintf(stderr, "gpt_load_table: Sector: %" PRIuDADDR "\n",
             gpt_absolute_addr);
@@ -57,6 +52,8 @@ gpt_load_table(TSK_VS_INFO * vs, GPT_TYPE_ENUM gpt_type)
         return 1;
 
     if(gpt_type == PRIMARY_TABLE){
+        TSK_DADDR_T dos_sect_relative_addr = GPT_PART_SOFFSET;
+        TSK_DADDR_T dos_sect_absolute_addr = vs->offset / vs->block_size + GPT_PART_SOFFSET;
         dos_part = (dos_sect *) sect_buf;
 
         cnt = tsk_vs_read_block
@@ -113,10 +110,13 @@ gpt_load_table(TSK_VS_INFO * vs, GPT_TYPE_ENUM gpt_type)
 
     /* Do the endianness test for the secondary table since the test in the dos safety table was skipped */
     if(gpt_type == SECONDARY_TABLE){
-        if(tsk_getu64(TSK_BIG_ENDIAN, head->head_lba) == gpt_relative_addr){
-            vs->endian = TSK_BIG_ENDIAN;
-        } else {
-            vs->endian = TSK_LIT_ENDIAN;
+        if (tsk_vs_guessu64(vs, head->signature, GPT_HEAD_SIG)) {
+            tsk_error_reset();
+            tsk_error_set_errno(TSK_ERR_VS_MAGIC);
+            tsk_error_set_errstr("GPT Header: %" PRIx64, tsk_getu64(vs->endian,
+                &head->signature));
+            free(sect_buf);
+            return 1;
         }
     }
 
diff --git a/tsk/vs/tsk_gpt.h b/tsk/vs/tsk_gpt.h
index d74a4fef4..81a09b047 100644
--- a/tsk/vs/tsk_gpt.h
+++ b/tsk/vs/tsk_gpt.h
@@ -60,7 +60,7 @@ extern "C" {
     typedef enum {
         PRIMARY_TABLE,
         SECONDARY_TABLE,
-    } GPT_TYPE_ENUM;
+    } GPT_LOCATION_ENUM;
 
 
 #ifdef __cplusplus
diff --git a/tsk/vs/tsk_vs_i.h b/tsk/vs/tsk_vs_i.h
index cb2c5aeeb..910657692 100644
--- a/tsk/vs/tsk_vs_i.h
+++ b/tsk/vs/tsk_vs_i.h
@@ -41,4 +41,8 @@ extern void tsk_vs_part_free(TSK_VS_INFO *);
 
 #define tsk_vs_guessu32(vs, x, mag)   \
     tsk_guess_end_u32(&(vs->endian), (x), (mag))
+
+#define tsk_vs_guessu64(vs, x, mag)   \
+    tsk_guess_end_u64(&(vs->endian), (x), (mag))
+
 #endif
-- 
GitLab