diff options
author | Leon Scroggins III <scroggo@google.com> | 2017-03-15 16:34:43 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-03-15 16:34:43 +0000 |
commit | 54f3d6fe60a47f9438ca2b57b128b6c1c5dc0c10 (patch) | |
tree | 67b247f297579046cf6c9226a5dbde2a01dab71f | |
parent | 99f10c5f712e92d3c09aa1e58cc64f25fe528a63 (diff) | |
parent | 279e33d754dfc63a7d5187e6065daa87808b40b4 (diff) | |
download | giflib-54f3d6fe60a47f9438ca2b57b128b6c1c5dc0c10.tar.gz |
Merge "Update GIFLIB to 5.1.4 DO NOT MERGE" into mnc-dev
am: 279e33d754
Change-Id: I7b37b218e2a1c8bbf894b19715ec997c8f3800d5
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | dgif_lib.c | 104 | ||||
-rw-r--r-- | egif_lib.c | 37 | ||||
-rw-r--r-- | gif_err.c | 4 | ||||
-rw-r--r-- | gif_lib.h | 41 | ||||
-rw-r--r-- | gifalloc.c | 46 | ||||
-rw-r--r-- | openbsd-reallocarray.c | 39 | ||||
-rw-r--r-- | quantize.c | 27 |
8 files changed, 216 insertions, 83 deletions
@@ -9,6 +9,7 @@ LOCAL_SRC_FILES := \ gifalloc.c \ gif_err.c \ gif_hash.c \ + openbsd-reallocarray.c \ quantize.c LOCAL_CFLAGS += -Wno-format -Wno-sign-compare -Wno-unused-parameter -DHAVE_CONFIG_H @@ -59,7 +59,6 @@ DGifOpenFileName(const char *FileName, int *Error) } GifFile = DGifOpenFileHandle(FileHandle, Error); - // cppcheck-suppress resourceLeak return GifFile; } @@ -90,7 +89,7 @@ DGifOpenFileHandle(int FileHandle, int *Error) 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; @@ -98,6 +97,9 @@ DGifOpenFileHandle(int FileHandle, int *Error) 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 */ @@ -114,6 +116,7 @@ DGifOpenFileHandle(int FileHandle, int *Error) /*@=mustfreeonly@*/ /* Let's see if this is a GIF file: */ + /* coverity[check_return] */ if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { if (Error != NULL) *Error = D_GIF_ERR_READ_FAILED; @@ -172,13 +175,14 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) 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; @@ -189,6 +193,7 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) GifFile->UserData = userData; /* TVT */ /* Lets see if this is a GIF file: */ + /* coverity[check_return] */ if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { if (Error != NULL) *Error = D_GIF_ERR_READ_FAILED; @@ -210,6 +215,8 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error) if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { free((char *)Private); free((char *)GifFile); + if (Error != NULL) + *Error = D_GIF_ERR_NO_SCRN_DSCR; return NULL; } @@ -267,6 +274,7 @@ DGifGetScreenDesc(GifFileType *GifFile) /* Get the global color map: */ GifFile->SColorMap->SortFlag = SortFlag; for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { + /* coverity[check_return] */ if (READ(GifFile, Buf, 3) != 3) { GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; @@ -299,6 +307,7 @@ DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type) return GIF_ERROR; } + /* coverity[check_return] */ if (READ(GifFile, &Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; @@ -372,6 +381,7 @@ DGifGetImageDesc(GifFileType *GifFile) /* Get the image local color map: */ for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { + /* coverity[check_return] */ if (READ(GifFile, Buf, 3) != 3) { GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Error = D_GIF_ERR_READ_FAILED; @@ -385,12 +395,14 @@ DGifGetImageDesc(GifFileType *GifFile) } if (GifFile->SavedImages) { - if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, - sizeof(SavedImage) * - (GifFile->ImageCount + 1))) == NULL) { + SavedImage* new_saved_images = + (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; } + GifFile->SavedImages = new_saved_images; } else { if ((GifFile->SavedImages = (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { @@ -420,9 +432,7 @@ DGifGetImageDesc(GifFileType *GifFile) (long)GifFile->Image.Height; /* Reset decompress algorithm parameters. */ - (void)DGifSetupDecompress(GifFile); - - return GIF_OK; + return DGifSetupDecompress(GifFile); } /****************************************************************************** @@ -521,6 +531,7 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) return GIF_ERROR; } + /* coverity[check_return] */ if (READ(GifFile, &Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; @@ -548,7 +559,7 @@ DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension) if (Buf > 0) { *Extension = Private->Buf; /* Use private unused buffer. */ (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ - /* coverity[tainted_data] */ + /* coverity[tainted_data,check_return] */ if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; @@ -612,7 +623,7 @@ int DGifSavedExtensionToGCB(GifFileType *GifFile, This routine should be called last, to close the GIF file. ******************************************************************************/ int -DGifCloseFile(GifFileType *GifFile) +DGifCloseFile(GifFileType *GifFile, int *ErrorCode) { GifFilePrivateType *Private; @@ -640,25 +651,25 @@ DGifCloseFile(GifFileType *GifFile) if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ - GifFile->Error = D_GIF_ERR_NOT_READABLE; + if (ErrorCode != NULL) + *ErrorCode = D_GIF_ERR_NOT_READABLE; + free((char *)GifFile->Private); + free(GifFile); return GIF_ERROR; } if (Private->File && (fclose(Private->File) != 0)) { - GifFile->Error = D_GIF_ERR_CLOSE_FAILED; + if (ErrorCode != NULL) + *ErrorCode = D_GIF_ERR_CLOSE_FAILED; + free((char *)GifFile->Private); + free(GifFile); return GIF_ERROR; } free((char *)GifFile->Private); - - /* - * Without the #ifndef, we get spurious warnings because Coverity mistakenly - * thinks the GIF structure is freed on an error return. - */ -#ifndef __COVERITY__ free(GifFile); -#endif /* __COVERITY__ */ - + if (ErrorCode != NULL) + *ErrorCode = D_GIF_SUCCEEDED; return GIF_OK; } @@ -670,6 +681,7 @@ DGifGetWord(GifFileType *GifFile, GifWord *Word) { unsigned char c[2]; + /* coverity[check_return] */ if (READ(GifFile, c, 2) != 2) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; @@ -714,6 +726,7 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; /* coverity[tainted_data_argument] */ + /* coverity[check_return] */ if (READ(GifFile, &Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; @@ -748,9 +761,18 @@ DGifSetupDecompress(GifFileType *GifFile) GifPrefixType *Prefix; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; - READ(GifFile, &CodeSize, 1); /* Read Code size from file. */ + /* coverity[check_return] */ + if (READ(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */ + return GIF_ERROR; /* Failed to read Code size. */ + } 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); @@ -834,19 +856,22 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) * pixels on our stack. If we done, pop the stack in reverse * (thats what stack is good for!) order to output. */ if (Prefix[CrntCode] == NO_SUCH_CODE) { + CrntPrefix = LastCode; + /* Only allowed if CrntCode is exactly the running code: * In that case CrntCode = XXXCode, CrntCode or the * prefix code is last code and the suffix char is * exactly the prefix of last code! */ if (CrntCode == Private->RunningCode - 2) { - CrntPrefix = LastCode; Suffix[Private->RunningCode - 2] = Stack[StackPtr++] = DGifGetPrefixChar(Prefix, LastCode, ClearCode); } else { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; + Suffix[Private->RunningCode - 2] = + Stack[StackPtr++] = DGifGetPrefixChar(Prefix, + CrntCode, + ClearCode); } } else CrntPrefix = CrntCode; @@ -1018,6 +1043,7 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) { if (Buf[0] == 0) { /* Needs to read the next buffer - this one is empty: */ + /* coverity[check_return] */ if (READ(GifFile, Buf, 1) != 1) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; @@ -1030,14 +1056,6 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte) GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } - /* There shouldn't be any empty data blocks here as the LZW spec - * says the LZW termination code should come first. Therefore we - * shouldn't be inside this routine at that point. - */ - if (Buf[0] == 0) { - GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; - } if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) { GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; @@ -1090,7 +1108,7 @@ DGifSlurp(GifFileType *GifFile) 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) { @@ -1135,12 +1153,12 @@ DGifSlurp(GifFileType *GifFile) return (GIF_ERROR); /* Create an extension block with our data */ if (ExtData != NULL) { - if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, - &GifFile->ExtensionBlocks, - ExtFunction, ExtData[0], &ExtData[1]) - == GIF_ERROR) - return (GIF_ERROR); - } + if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, + &GifFile->ExtensionBlocks, + ExtFunction, ExtData[0], &ExtData[1]) + == GIF_ERROR) + return (GIF_ERROR); + } while (ExtData != NULL) { if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return (GIF_ERROR); @@ -1162,6 +1180,12 @@ DGifSlurp(GifFileType *GifFile) } } 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); } @@ -105,6 +105,7 @@ EGifOpenFileHandle(const int FileHandle, int *Error) *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 @@ EGifOpenFileHandle(const int FileHandle, int *Error) 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 @@ EGifOpen(void *userData, OutputFunc writeFunc, int *Error) return NULL; } + memset(Private, '\0', sizeof(GifFilePrivateType)); + Private->HashTable = _InitHashTable(); if (Private->HashTable == NULL) { free (GifFile); @@ -186,7 +190,7 @@ EGifOpen(void *userData, OutputFunc writeFunc, int *Error) /****************************************************************************** Routine to compute the GIF version that will be written on output. ******************************************************************************/ -char * +const char * EGifGetGifVersion(GifFileType *GifFile) { GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; @@ -267,7 +271,7 @@ EGifPutScreenDesc(GifFileType *GifFile, { GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; - char *write_version; + const char *write_version; if (Private->FileState & FILE_STATE_SCREEN) { /* If already has screen descriptor - something is wrong! */ @@ -379,6 +383,10 @@ EGifPutImageDesc(GifFileType *GifFile, GifFile->Image.Height = Height; GifFile->Image.Interlace = Interlace; if (ColorMap) { + if (GifFile->Image.ColorMap != NULL) { + GifFreeMapObject(GifFile->Image.ColorMap); + GifFile->Image.ColorMap = NULL; + } GifFile->Image.ColorMap = GifMakeMapObject(ColorMap->ColorCount, ColorMap->Colors); if (GifFile->Image.ColorMap == NULL) { @@ -496,7 +504,7 @@ EGifPutPixel(GifFileType *GifFile, GifPixelType Pixel) int EGifPutComment(GifFileType *GifFile, const char *Comment) { - unsigned int length = strlen(Comment); + unsigned int length; char *buf; length = strlen(Comment); @@ -750,7 +758,7 @@ EGifPutCodeNext(GifFileType *GifFile, const GifByteType *CodeBlock) This routine should be called last, to close the GIF file. ******************************************************************************/ int -EGifCloseFile(GifFileType *GifFile) +EGifCloseFile(GifFileType *GifFile, int *ErrorCode) { GifByteType Buf; GifFilePrivateType *Private; @@ -764,7 +772,9 @@ EGifCloseFile(GifFileType *GifFile) return GIF_ERROR; if (!IS_WRITEABLE(Private)) { /* This file was NOT open for writing: */ - GifFile->Error = E_GIF_ERR_NOT_WRITEABLE; + if (ErrorCode != NULL) + *ErrorCode = E_GIF_ERR_NOT_WRITEABLE; + free(GifFile); return GIF_ERROR; } @@ -785,22 +795,19 @@ EGifCloseFile(GifFileType *GifFile) if (Private->HashTable) { free((char *) Private->HashTable); } - free((char *) Private); + free((char *) Private); } if (File && fclose(File) != 0) { - GifFile->Error = E_GIF_ERR_CLOSE_FAILED; + if (ErrorCode != NULL) + *ErrorCode = E_GIF_ERR_CLOSE_FAILED; + free(GifFile); return GIF_ERROR; } - /* - * Without the #ifndef, we get spurious warnings because Coverity mistakenly - * thinks the GIF structure is freed on an error return. - */ -#ifndef __COVERITY__ free(GifFile); -#endif /* __COVERITY__ */ - + if (ErrorCode != NULL) + *ErrorCode = E_GIF_SUCCEEDED; return GIF_OK; } @@ -1140,7 +1147,7 @@ EGifSpew(GifFileType *GifFileOut) GifFileOut->ExtensionBlockCount) == GIF_ERROR) return (GIF_ERROR); - if (EGifCloseFile(GifFileOut) == GIF_ERROR) + if (EGifCloseFile(GifFileOut, NULL) == GIF_ERROR) return (GIF_ERROR); return (GIF_OK); @@ -12,10 +12,10 @@ gif_err.c - handle error reporting for the GIF library. /***************************************************************************** Return a string description of the last GIF error *****************************************************************************/ -char * +const char * GifErrorString(int ErrorCode) { - char *Err; + const char *Err; switch (ErrorCode) { case E_GIF_ERR_OPEN_FAILED: @@ -12,12 +12,13 @@ extern "C" { #endif /* __cplusplus */ #define GIFLIB_MAJOR 5 -#define GIFLIB_MINOR 0 +#define GIFLIB_MINOR 1 #define GIFLIB_RELEASE 4 #define GIF_ERROR 0 #define GIF_OK 1 +#include <stddef.h> #include <stdbool.h> #define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */ @@ -127,9 +128,10 @@ GifFileType *EGifOpenFileName(const char *GifFileName, GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error); GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error); int EGifSpew(GifFileType * GifFile); -char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */ -int EGifCloseFile(GifFileType * GifFile); +const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */ +int EGifCloseFile(GifFileType *GifFile, int *ErrorCode); +#define E_GIF_SUCCEEDED 0 #define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */ #define E_GIF_ERR_WRITE_FAILED 2 #define E_GIF_ERR_HAS_SCRN_DSCR 3 @@ -178,8 +180,9 @@ GifFileType *DGifOpenFileName(const char *GifFileName, int *Error); GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error); int DGifSlurp(GifFileType * GifFile); GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */ -int DGifCloseFile(GifFileType * GifFile); + int DGifCloseFile(GifFileType * GifFile, int *ErrorCode); +#define D_GIF_SUCCEEDED 0 #define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */ #define D_GIF_ERR_READ_FAILED 102 #define D_GIF_ERR_NOT_GIF_FILE 103 @@ -222,7 +225,7 @@ int GifQuantizeBuffer(unsigned int Width, unsigned int Height, /****************************************************************************** Error handling and reporting. ******************************************************************************/ -extern char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */ +extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */ /***************************************************************************** Everything below this point is new after version 1.2, supporting `slurp @@ -241,6 +244,9 @@ extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1, 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). ******************************************************************************/ @@ -273,6 +279,31 @@ int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB, GifFileType *GifFile, int ImageIndex); +/****************************************************************************** + The library's internal utility font +******************************************************************************/ + +#define GIF_FONT_WIDTH 8 +#define GIF_FONT_HEIGHT 8 +extern const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH]; + +extern void GifDrawText8x8(SavedImage *Image, + const int x, const int y, + const char *legend, const int color); + +extern void GifDrawBox(SavedImage *Image, + const int x, const int y, + const int w, const int d, const int color); + +extern void GifDrawRectangle(SavedImage *Image, + const int x, const int y, + const int w, const int d, const int color); + +extern void GifDrawBoxedText8x8(SavedImage *Image, + const int x, const int y, + const char *legend, + const int border, const int bg, const int fg); + #ifdef __cplusplus } #endif /* __cplusplus */ @@ -60,6 +60,7 @@ GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) Object->ColorCount = ColorCount; Object->BitsPerPixel = GifBitSize(ColorCount); + Object->SortFlag = false; if (ColorMap != NULL) { memcpy((char *)Object->Colors, @@ -186,9 +187,15 @@ GifUnionColorMap(const ColorMapObject *ColorIn1, Map[j].Red = Map[j].Green = Map[j].Blue = 0; /* perhaps we can shrink the map? */ - if (RoundUpTo < ColorUnion->ColorCount) - ColorUnion->Colors = (GifColorType *)realloc(Map, - sizeof(GifColorType) * RoundUpTo); + if (RoundUpTo < ColorUnion->ColorCount) { + GifColorType *new_map = (GifColorType *)reallocarray(Map, + RoundUpTo, sizeof(GifColorType)); + if( new_map == NULL ) { + GifFreeMapObject(ColorUnion); + return ((ColorMapObject *) NULL); + } + ColorUnion->Colors = new_map; + } } ColorUnion->ColorCount = RoundUpTo; @@ -224,10 +231,14 @@ GifAddExtensionBlock(int *ExtensionBlockCount, if (*ExtensionBlocks == NULL) *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock)); - else - *ExtensionBlocks = (ExtensionBlock *)realloc(*ExtensionBlocks, - sizeof(ExtensionBlock) * - (*ExtensionBlockCount + 1)); + else { + ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray + (*ExtensionBlocks, (*ExtensionBlockCount + 1), + sizeof(ExtensionBlock)); + if( ep_new == NULL ) + return (GIF_ERROR); + *ExtensionBlocks = ep_new; + } if (*ExtensionBlocks == NULL) return (GIF_ERROR); @@ -311,18 +322,16 @@ FreeLastSavedImage(GifFileType *GifFile) SavedImage * GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) { - SavedImage *sp; - 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); else { - sp = &GifFile->SavedImages[GifFile->ImageCount++]; + SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++]; memset((char *)sp, '\0', sizeof(SavedImage)); if (CopyFrom != NULL) { @@ -346,9 +355,10 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) } /* 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); @@ -359,9 +369,9 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom) /* 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..41a3326 --- /dev/null +++ b/openbsd-reallocarray.c @@ -0,0 +1,39 @@ +/* $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> +#include <limits.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); +} @@ -234,6 +234,17 @@ SubdivColorMap(NewColorMapType * NewColorSubdiv, j++, QuantizedColor = QuantizedColor->Pnext) SortArray[j] = QuantizedColor; + /* + * Because qsort isn't stable, this can produce differing + * results for the order of tuples depending on platform + * details of how qsort() is implemented. + * + * We mitigate this problem by sorting on all three axes rather + * than only the one specied by SortRGBAxis; that way the instability + * can only become an issue if there are multiple color indices + * referring to identical RGB tuples. Older versions of this + * sorted on only the one axis. + */ qsort(SortArray, NewColorSubdiv[Index].NumEntries, sizeof(QuantizedColorType *), SortCmpRtn); @@ -298,12 +309,22 @@ SubdivColorMap(NewColorMapType * NewColorSubdiv, /**************************************************************************** Routine called by qsort to compare two entries. *****************************************************************************/ + static int SortCmpRtn(const void *Entry1, const void *Entry2) { - - return (*((QuantizedColorType **) Entry1))->RGB[SortRGBAxis] - - (*((QuantizedColorType **) Entry2))->RGB[SortRGBAxis]; + QuantizedColorType *entry1 = (*((QuantizedColorType **) Entry1)); + QuantizedColorType *entry2 = (*((QuantizedColorType **) Entry2)); + + /* sort on all axes of the color space! */ + int hash1 = entry1->RGB[SortRGBAxis] * 256 * 256 + + entry1->RGB[(SortRGBAxis+1) % 3] * 256 + + entry1->RGB[(SortRGBAxis+2) % 3]; + int hash2 = entry2->RGB[SortRGBAxis] * 256 * 256 + + entry2->RGB[(SortRGBAxis+1) % 3] * 256 + + entry2->RGB[(SortRGBAxis+2) % 3]; + + return hash1 - hash2; } /* end */ |