diff options
Diffstat (limited to 'dgif_lib.c')
-rw-r--r-- | dgif_lib.c | 104 |
1 files changed, 64 insertions, 40 deletions
@@ -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); } |