Fix possible out of bounds access am: 751b4eba25 am: b201f04d8c am: 2d49e2de6e am: a3c15ad42d am: 6c2d0e45b5 am: dbefc1dc4a am: 854fedfa6b am: 2ea3783c81 am: e3574d919b am: 3daffc0fba am: 2a4c12f5e5
am: a0628a0519

Change-Id: Ib5d873506e2d728ce6b86eea402dca5b856deed3
diff --git a/exif.c b/exif.c
index ffe9581..6d8b96d 100644
--- a/exif.c
+++ b/exif.c
@@ -383,6 +383,51 @@
 }
 
 //--------------------------------------------------------------------------
+// Convert a 64 bit signed value from file's native byte order
+//--------------------------------------------------------------------------
+long long Get64s(void * LLong)
+{
+    uchar * ValuePtr = (uchar *)LLong;
+    if (MotorolaOrder){
+        return  (((long long)ValuePtr[0]) << 56) | (((ullong)ValuePtr[1]) << 48)
+              | (((   ullong)ValuePtr[2]) << 40) | (((ullong)ValuePtr[3]) << 32)
+              | (((   ullong)ValuePtr[4]) << 24) | (((ullong)ValuePtr[5]) << 16)
+              | (((   ullong)ValuePtr[6]) << 8 ) | (((ullong)ValuePtr[7]) << 0 );
+    }else{
+        return  (((long long)ValuePtr[7]) << 56) | (((ullong)ValuePtr[6]) << 48)
+              | (((   ullong)ValuePtr[5]) << 40) | (((ullong)ValuePtr[4]) << 32)
+              | (((   ullong)ValuePtr[3]) << 24) | (((ullong)ValuePtr[2]) << 16)
+              | (((   ullong)ValuePtr[1]) << 8 ) | (((ullong)ValuePtr[0]) << 0 );
+    }
+}
+
+//--------------------------------------------------------------------------
+// Convert a 64 bit double value from signed long long value
+//--------------------------------------------------------------------------
+double Get64d(void * Double)
+{
+    union {
+      double ret;
+      long long var;
+    }data;
+    data.var = Get64s(Double);
+    return data.ret;
+}
+
+//--------------------------------------------------------------------------
+// Convert a 32 bit float value from signed int value
+//--------------------------------------------------------------------------
+float Get32f(void * Float)
+{
+    union {
+      float ret;
+      int var;
+    }data;
+    data.var = Get32s(Float);
+    return data.ret;
+}
+
+//--------------------------------------------------------------------------
 // Display a number as one of its many formats
 //--------------------------------------------------------------------------
 void PrintFormatNumber(void * ValuePtr, int Format, int ByteCount)
@@ -403,8 +448,8 @@
                s = 8;
                break;
 
-            case FMT_SINGLE:    printf("%f",(double)*(float *)ValuePtr); s=8; break;
-            case FMT_DOUBLE:    printf("%f",*(double *)ValuePtr);        s=8; break;
+            case FMT_SINGLE:    printf("%f",Get32f(ValuePtr)); s=4; break;
+            case FMT_DOUBLE:    printf("%f",Get64d(ValuePtr)); s=8; break;
             default:
                 printf("Unknown format %d:", Format);
                 return;
@@ -451,9 +496,8 @@
         case FMT_SSHORT:    Value = (signed short)Get16u(ValuePtr);  break;
         case FMT_SLONG:     Value = Get32s(ValuePtr);                break;
 
-        // Not sure if this is correct (never seen float used in Exif format)
-        case FMT_SINGLE:    Value = (double)*(float *)ValuePtr;      break;
-        case FMT_DOUBLE:    Value = *(double *)ValuePtr;             break;
+        case FMT_SINGLE:    Value = Get32f(ValuePtr);                break;
+        case FMT_DOUBLE:    Value = Get64d(ValuePtr);                break;
 
         default:
             ErrNonfatal("Illegal format code %d",Format,0);
diff --git a/jhead.h b/jhead.h
index 0c4ccbb..0ba1592 100644
--- a/jhead.h
+++ b/jhead.h
@@ -30,6 +30,7 @@
 
 
 typedef unsigned char uchar;
+typedef unsigned long long ullong;
 
 #ifndef TRUE
     #define TRUE 1