Update GIFLIB to 5.1.4

Test: compile plus existing CTS tests

Bug:34697653
Change-Id: Iec03e5cd9caf8cd6401639234c5b889d12189e40
diff --git a/Android.bp b/Android.bp
index 69cb704..9bfb163 100644
--- a/Android.bp
+++ b/Android.bp
@@ -9,6 +9,7 @@
         "gifalloc.c",
         "gif_err.c",
         "gif_hash.c",
+        "openbsd-reallocarray.c",
         "quantize.c",
     ],
 
diff --git a/dgif_lib.c b/dgif_lib.c
index 320fdb9..66a1d6a 100644
--- a/dgif_lib.c
+++ b/dgif_lib.c
@@ -89,7 +89,7 @@
     GifFile->SavedImages = NULL;
     GifFile->SColorMap = NULL;
 
-    Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
+    Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
     if (Private == NULL) {
         if (Error != NULL)
 	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
@@ -97,6 +97,9 @@
         free((char *)GifFile);
         return NULL;
     }
+
+    /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
+
 #ifdef _WIN32
     _setmode(FileHandle, O_BINARY);    /* Make sure it is in binary mode. */
 #endif /* _WIN32 */
@@ -172,13 +175,14 @@
     GifFile->SavedImages = NULL;
     GifFile->SColorMap = NULL;
 
-    Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
+    Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
     if (!Private) {
         if (Error != NULL)
 	    *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
         free((char *)GifFile);
         return NULL;
     }
+    /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
 
     GifFile->Private = (void *)Private;
     Private->FileHandle = 0;
@@ -392,8 +396,8 @@
 
     if (GifFile->SavedImages) {
         SavedImage* new_saved_images =
-            (SavedImage *)realloc(GifFile->SavedImages,
-                            sizeof(SavedImage) * (GifFile->ImageCount + 1));
+            (SavedImage *)reallocarray(GifFile->SavedImages,
+                            (GifFile->ImageCount + 1), sizeof(SavedImage));
         if (new_saved_images == NULL) {
             GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
             return GIF_ERROR;
@@ -763,6 +767,12 @@
     }
     BitsPerPixel = CodeSize;
 
+    /* this can only happen on a severely malformed GIF */
+    if (BitsPerPixel > 8) {
+	GifFile->Error = D_GIF_ERR_READ_FAILED;	/* somewhat bogus error code */
+	return GIF_ERROR;    /* Failed to read Code size. */
+    }
+
     Private->Buf[0] = 0;    /* Input Buffer empty. */
     Private->BitsPerPixel = BitsPerPixel;
     Private->ClearCode = (1 << BitsPerPixel);
@@ -1098,7 +1108,7 @@
               if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
                   return GIF_ERROR;
               }
-              sp->RasterBits = (unsigned char *)malloc(ImageSize *
+              sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
                       sizeof(GifPixelType));
 
               if (sp->RasterBits == NULL) {
@@ -1170,6 +1180,12 @@
         }
     } while (RecordType != TERMINATE_RECORD_TYPE);
 
+    /* Sanity check for corrupted file */
+    if (GifFile->ImageCount == 0) {
+	GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
+	return(GIF_ERROR);
+    }
+
     return (GIF_OK);
 }
 
diff --git a/egif_lib.c b/egif_lib.c
index 754d914..3917ec6 100644
--- a/egif_lib.c
+++ b/egif_lib.c
@@ -105,6 +105,7 @@
 	    *Error = E_GIF_ERR_NOT_ENOUGH_MEM;
         return NULL;
     }
+    /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
     if ((Private->HashTable = _InitHashTable()) == NULL) {
         free(GifFile);
         free(Private);
@@ -123,6 +124,7 @@
     Private->FileHandle = FileHandle;
     Private->File = f;
     Private->FileState = FILE_STATE_WRITE;
+    Private->gif89 = false;
 
     Private->Write = (OutputFunc) 0;    /* No user write routine (MRB) */
     GifFile->UserData = (void *)NULL;    /* No user write handle (MRB) */
@@ -159,6 +161,8 @@
         return NULL;
     }
 
+    memset(Private, '\0', sizeof(GifFilePrivateType));
+
     Private->HashTable = _InitHashTable();
     if (Private->HashTable == NULL) {
         free (GifFile);
diff --git a/gif_font.c b/gif_font.c
index ba47b29..8a02b2d 100644
--- a/gif_font.c
+++ b/gif_font.c
@@ -5,6 +5,7 @@
 ****************************************************************************/
 
 #include <string.h>
+#include <stdlib.h>
 
 #include "gif_lib.h"
 
@@ -209,8 +210,9 @@
               const int border,
               const int bg, const int fg)
 {
-    int i, j = 0, LineCount = 0, TextWidth = 0;
+    int j = 0, LineCount = 0, TextWidth = 0;
     const char *cp;
+    char *dup;
 
     /* compute size of text to box */
     for (cp = legend; *cp; cp++)
@@ -225,28 +227,33 @@
     if (j > TextWidth)    /* last line might be longer than any previous */
         TextWidth = j;
 
-    /* fill the box */
-    GifDrawRectangle(Image, x + 1, y + 1,
-                  border + TextWidth * GIF_FONT_WIDTH + border - 1,
-                  border + LineCount * GIF_FONT_HEIGHT + border - 1, bg);
-
     /* draw the text */
-    i = 0;
-    cp = strtok((char *)legend, "\r\n");
-    do {
-        int leadspace = 0;
+    dup = malloc(strlen(legend)+1);
+    /* FIXME: should return bad status, but that would require API change */
+    if (dup != NULL) {
+	int i = 0;
+	/* fill the box */
+	GifDrawRectangle(Image, x + 1, y + 1,
+		      border + TextWidth * GIF_FONT_WIDTH + border - 1,
+		      border + LineCount * GIF_FONT_HEIGHT + border - 1, bg);
+	(void)strcpy(dup, (char *)legend);
+	cp = strtok((char *)dup, "\r\n");
+	do {
+	    int leadspace = 0;
 
-        if (cp[0] == '\t')
-            leadspace = (TextWidth - strlen(++cp)) / 2;
+	    if (cp[0] == '\t')
+		leadspace = (TextWidth - strlen(++cp)) / 2;
 
-        GifDrawText8x8(Image, x + border + (leadspace * GIF_FONT_WIDTH),
-                 y + border + (GIF_FONT_HEIGHT * i++), cp, fg);
-        cp = strtok((char *)NULL, "\r\n");
-    } while (cp);
+	    GifDrawText8x8(Image, x + border + (leadspace * GIF_FONT_WIDTH),
+			   y + border + (GIF_FONT_HEIGHT * i++), cp, fg);
+	    cp = strtok((char *)NULL, "\r\n");
+	} while (cp);
+	(void)free((void *)dup);
 
-    /* outline the box */
-    GifDrawBox(Image, x, y, border + TextWidth * GIF_FONT_WIDTH + border,
-            border + LineCount * GIF_FONT_HEIGHT + border, fg);
+	/* outline the box */
+	GifDrawBox(Image, x, y, border + TextWidth * GIF_FONT_WIDTH + border,
+		   border + LineCount * GIF_FONT_HEIGHT + border, fg);
+    }
 }
 
 /* end */
diff --git a/gif_lib.h b/gif_lib.h
index ac0307d..078930c 100644
--- a/gif_lib.h
+++ b/gif_lib.h
@@ -13,7 +13,7 @@
 
 #define GIFLIB_MAJOR 5
 #define GIFLIB_MINOR 1
-#define GIFLIB_RELEASE 1
+#define GIFLIB_RELEASE 4
 
 #define GIF_ERROR   0
 #define GIF_OK      1
@@ -244,6 +244,9 @@
                                      GifPixelType ColorTransIn2[]);
 extern int GifBitSize(int n);
 
+extern void *
+reallocarray(void *optr, size_t nmemb, size_t size);
+
 /******************************************************************************
  Support for the in-core structures allocation (slurp mode).              
 ******************************************************************************/
diff --git a/gifalloc.c b/gifalloc.c
index f4118d6..3b51868 100644
--- a/gifalloc.c
+++ b/gifalloc.c
@@ -188,8 +188,8 @@
 
         /* perhaps we can shrink the map? */
         if (RoundUpTo < ColorUnion->ColorCount) {
-            GifColorType *new_map = (GifColorType *)realloc(Map,
-                                 sizeof(GifColorType) * RoundUpTo);
+            GifColorType *new_map = (GifColorType *)reallocarray(Map,
+                                 RoundUpTo, sizeof(GifColorType));
             if( new_map == NULL ) {
                 GifFreeMapObject(ColorUnion);
                 return ((ColorMapObject *) NULL);
@@ -232,9 +232,9 @@
     if (*ExtensionBlocks == NULL)
         *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
     else {
-        ExtensionBlock* ep_new = (ExtensionBlock *)realloc(*ExtensionBlocks,
-                                      sizeof(ExtensionBlock) *
-                                      (*ExtensionBlockCount + 1));
+        ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray
+				 (*ExtensionBlocks, (*ExtensionBlockCount + 1),
+                                      sizeof(ExtensionBlock));
         if( ep_new == NULL )
             return (GIF_ERROR);
         *ExtensionBlocks = ep_new;
@@ -325,8 +325,8 @@
     if (GifFile->SavedImages == NULL)
         GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
     else
-        GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
-                               sizeof(SavedImage) * (GifFile->ImageCount + 1));
+        GifFile->SavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
+                               (GifFile->ImageCount + 1), sizeof(SavedImage));
 
     if (GifFile->SavedImages == NULL)
         return ((SavedImage *)NULL);
@@ -355,9 +355,10 @@
             }
 
             /* next, the raster */
-            sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) *
-                                                   CopyFrom->ImageDesc.Height *
-                                                   CopyFrom->ImageDesc.Width);
+            sp->RasterBits = (unsigned char *)reallocarray(NULL,
+                                                  (CopyFrom->ImageDesc.Height *
+                                                  CopyFrom->ImageDesc.Width),
+						  sizeof(GifPixelType));
             if (sp->RasterBits == NULL) {
                 FreeLastSavedImage(GifFile);
                 return (SavedImage *)(NULL);
@@ -368,9 +369,9 @@
 
             /* finally, the extension blocks */
             if (sp->ExtensionBlocks != NULL) {
-                sp->ExtensionBlocks = (ExtensionBlock *)malloc(
-                                      sizeof(ExtensionBlock) *
-                                      CopyFrom->ExtensionBlockCount);
+                sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,
+                                      CopyFrom->ExtensionBlockCount,
+				      sizeof(ExtensionBlock));
                 if (sp->ExtensionBlocks == NULL) {
                     FreeLastSavedImage(GifFile);
                     return (SavedImage *)(NULL);
diff --git a/openbsd-reallocarray.c b/openbsd-reallocarray.c
new file mode 100644
index 0000000..aa70686
--- /dev/null
+++ b/openbsd-reallocarray.c
@@ -0,0 +1,38 @@
+/*	$OpenBSD: reallocarray.c,v 1.1 2014/05/08 21:43:49 deraadt Exp $	*/
+/*
+ * Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
+
+void *
+reallocarray(void *optr, size_t nmemb, size_t size)
+{
+	if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    nmemb > 0 && SIZE_MAX / nmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	return realloc(optr, size * nmemb);
+}