< prev index next >

src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c

Print this page

        

*** 21,301 **** * or visit www.oracle.com if you need additional information or have any * questions. */ /****************************************************************************** ! * "Gif-Lib" - Yet another gif library. ! * ! * Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 ! ****************************************************************************** ! * The kernel of the GIF Decoding process can be found here. ! ****************************************************************************** ! * History: ! * 16 Jun 89 - Version 1.0 by Gershon Elber. ! * 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). ! *****************************************************************************/ ! ! /* !!!! */ ! ! #ifdef HAVE_CONFIG_H ! #include <config.h> ! #endif #include <stdlib.h> ! #if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__) ! #include <io.h> ! #include <alloc.h> ! #include <sys\stat.h> ! #else ! #include <sys/types.h> ! #include <sys/stat.h> ! #endif /* __MSDOS__ */ #ifdef _WIN32 #include <io.h> - #define _OPEN_BINARY #else #include <unistd.h> ! #endif ! ! #include <fcntl.h> - #include <stdio.h> - #include <string.h> #include "gif_lib.h" #include "gif_lib_private.h" ! #define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for ! comment. */ /* avoid extra function call in case we use fread (TVT) */ #define READ(_gif,_buf,_len) \ (((GifFilePrivateType*)_gif->Private)->Read ? \ ! (size_t)((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \ fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File)) ! static int DGifGetWord(GifFileType *GifFile, int *Word); static int DGifSetupDecompress(GifFileType *GifFile); static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen); ! static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode); static int DGifDecompressInput(GifFileType *GifFile, int *Code); static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte); /****************************************************************************** ! * Open a new gif file for read, given by its name. ! * Returns GifFileType pointer dynamically allocated which serves as the gif ! * info record. _GifError is cleared if succesfull. ! *****************************************************************************/ GifFileType * ! DGifOpenFileName(const char *FileName) { int FileHandle; GifFileType *GifFile; ! if ((FileHandle = open(FileName, O_RDONLY ! #if defined(__MSDOS__) || defined(_OPEN_BINARY) ! | O_BINARY ! #endif /* __MSDOS__ || _OPEN_BINARY */ ! )) == -1) { ! _GifError = D_GIF_ERR_OPEN_FAILED; return NULL; } ! GifFile = DGifOpenFileHandle(FileHandle); ! if (GifFile == (GifFileType *)NULL) ! close(FileHandle); return GifFile; } /****************************************************************************** ! * Update a new gif file, given its file handle. ! * Returns GifFileType pointer dynamically allocated which serves as the gif ! * info record. _GifError is cleared if succesfull. ! *****************************************************************************/ GifFileType * ! DGifOpenFileHandle(int FileHandle) { ! ! unsigned char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; FILE *f; GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return NULL; } ! memset(GifFile, '\0', sizeof(GifFileType)); Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); if (Private == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; free((char *)GifFile); return NULL; } ! #ifdef __MSDOS__ ! setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ ! #endif /* __MSDOS__ */ f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ ! #ifdef __MSDOS__ ! setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE); /* And inc. stream ! buffer. */ ! #endif /* __MSDOS__ */ ! ! GifFile->Private = (VoidPtr)Private; Private->FileHandle = FileHandle; Private->File = f; Private->FileState = FILE_STATE_READ; ! Private->Read = 0; /* don't use alternate input method (TVT) */ ! GifFile->UserData = 0; /* TVT */ ! ! /* Lets see if this is a GIF file: */ ! if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { ! _GifError = D_GIF_ERR_READ_FAILED; ! fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } ! /* The GIF Version number is ignored at this time. Maybe we should do ! * something more useful with it. */ Buf[GIF_STAMP_LEN] = 0; ! if (strncmp(GIF_STAMP, (const char*)Buf, GIF_VERSION_POS) != 0) { ! _GifError = D_GIF_ERR_NOT_GIF_FILE; ! fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { ! fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } ! _GifError = 0; return GifFile; } /****************************************************************************** ! * GifFileType constructor with user supplied input function (TVT) ! *****************************************************************************/ GifFileType * ! DGifOpen(void *userData, ! InputFunc readFunc) { ! ! unsigned char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; - if (!readFunc) { - _GifError = D_GIF_ERR_READ_FAILED; - return NULL; - } - GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return NULL; } memset(GifFile, '\0', sizeof(GifFileType)); Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); if (!Private) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; free((char *)GifFile); return NULL; } ! GifFile->Private = (VoidPtr)Private; Private->FileHandle = 0; ! Private->File = 0; Private->FileState = FILE_STATE_READ; Private->Read = readFunc; /* TVT */ GifFile->UserData = userData; /* TVT */ /* Lets see if this is a GIF file: */ ! if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { ! _GifError = D_GIF_ERR_READ_FAILED; free((char *)Private); free((char *)GifFile); return NULL; } ! /* The GIF Version number is ignored at this time. Maybe we should do ! * something more useful with it. */ ! Buf[GIF_STAMP_LEN] = 0; ! if (strncmp(GIF_STAMP, (const char*)Buf, GIF_VERSION_POS) != 0) { ! _GifError = D_GIF_ERR_NOT_GIF_FILE; free((char *)Private); free((char *)GifFile); return NULL; } if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { free((char *)Private); free((char *)GifFile); return NULL; } ! _GifError = 0; return GifFile; } /****************************************************************************** ! * This routine should be called before any other DGif calls. Note that ! * this routine is called automatically from DGif file open routines. ! *****************************************************************************/ int ! DGifGetScreenDesc(GifFileType * GifFile) { ! ! int i, BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } /* Put the screen descriptor into the file: */ if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; if (Buf[0] & 0x80) { /* Do we have global color map? */ ! GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* Get the global color map: */ for (i = 0; i < GifFile->SColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { ! FreeMapObject(GifFile->SColorMap); ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; GifFile->SColorMap->Colors[i].Green = Buf[1]; GifFile->SColorMap->Colors[i].Blue = Buf[2]; --- 21,307 ---- * or visit www.oracle.com if you need additional information or have any * questions. */ /****************************************************************************** ! ! dgif_lib.c - GIF decoding ! ! The functions here and in egif_lib.c are partitioned carefully so that ! if you only require one of read and write capability, only one of these ! two modules will be linked. Preserve this property! ! ! *****************************************************************************/ #include <stdlib.h> ! #include <limits.h> ! #include <stdint.h> ! #include <fcntl.h> ! #include <stdio.h> ! #include <string.h> #ifdef _WIN32 #include <io.h> #else #include <unistd.h> ! #endif /* _WIN32 */ #include "gif_lib.h" #include "gif_lib_private.h" ! /* compose unsigned little endian value */ ! #define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8)) /* avoid extra function call in case we use fread (TVT) */ #define READ(_gif,_buf,_len) \ (((GifFilePrivateType*)_gif->Private)->Read ? \ ! ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \ fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File)) ! static int DGifGetWord(GifFileType *GifFile, GifWord *Word); static int DGifSetupDecompress(GifFileType *GifFile); static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen); ! static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode); static int DGifDecompressInput(GifFileType *GifFile, int *Code); static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte); /****************************************************************************** ! Open a new GIF file for read, given by its name. ! Returns dynamically allocated GifFileType pointer which serves as the GIF ! info record. ! ******************************************************************************/ GifFileType * ! DGifOpenFileName(const char *FileName, int *Error) ! { int FileHandle; GifFileType *GifFile; ! if ((FileHandle = open(FileName, O_RDONLY)) == -1) { ! if (Error != NULL) ! *Error = D_GIF_ERR_OPEN_FAILED; return NULL; } ! GifFile = DGifOpenFileHandle(FileHandle, Error); return GifFile; } /****************************************************************************** ! Update a new GIF file, given its file handle. ! Returns dynamically allocated GifFileType pointer which serves as the GIF ! info record. ! ******************************************************************************/ GifFileType * ! DGifOpenFileHandle(int FileHandle, int *Error) ! { ! char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; FILE *f; GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { ! if (Error != NULL) ! *Error = D_GIF_ERR_NOT_ENOUGH_MEM; ! (void)close(FileHandle); return NULL; } ! /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType)); ! ! /* Belt and suspenders, in case the null pointer isn't zero */ ! GifFile->SavedImages = NULL; ! GifFile->SColorMap = NULL; Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); if (Private == NULL) { ! if (Error != NULL) ! *Error = D_GIF_ERR_NOT_ENOUGH_MEM; ! (void)close(FileHandle); free((char *)GifFile); return NULL; } ! #ifdef _WIN32 ! _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ ! #endif /* _WIN32 */ f = fdopen(FileHandle, "rb"); /* Make it into a stream: */ ! /*@-mustfreeonly@*/ ! GifFile->Private = (void *)Private; Private->FileHandle = FileHandle; Private->File = f; Private->FileState = FILE_STATE_READ; ! Private->Read = NULL; /* don't use alternate input method (TVT) */ ! GifFile->UserData = NULL; /* TVT */ ! /*@=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; ! (void)fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } ! /* Check for GIF prefix at start of file */ Buf[GIF_STAMP_LEN] = 0; ! if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { ! if (Error != NULL) ! *Error = D_GIF_ERR_NOT_GIF_FILE; ! (void)fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { ! (void)fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } ! GifFile->Error = 0; ! ! /* What version of GIF? */ ! Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); return GifFile; } /****************************************************************************** ! GifFileType constructor with user supplied input function (TVT) ! ******************************************************************************/ GifFileType * ! DGifOpen(void *userData, InputFunc readFunc, int *Error) ! { ! char Buf[GIF_STAMP_LEN + 1]; GifFileType *GifFile; GifFilePrivateType *Private; GifFile = (GifFileType *)malloc(sizeof(GifFileType)); if (GifFile == NULL) { ! if (Error != NULL) ! *Error = D_GIF_ERR_NOT_ENOUGH_MEM; return NULL; } memset(GifFile, '\0', sizeof(GifFileType)); + /* Belt and suspenders, in case the null pointer isn't zero */ + GifFile->SavedImages = NULL; + GifFile->SColorMap = NULL; + Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType)); if (!Private) { ! if (Error != NULL) ! *Error = D_GIF_ERR_NOT_ENOUGH_MEM; free((char *)GifFile); return NULL; } ! GifFile->Private = (void *)Private; Private->FileHandle = 0; ! Private->File = NULL; Private->FileState = FILE_STATE_READ; Private->Read = readFunc; /* TVT */ 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; free((char *)Private); free((char *)GifFile); return NULL; } ! /* Check for GIF prefix at start of file */ ! Buf[GIF_STAMP_LEN] = '\0'; ! if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) { ! if (Error != NULL) ! *Error = D_GIF_ERR_NOT_GIF_FILE; free((char *)Private); free((char *)GifFile); return NULL; } if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { free((char *)Private); free((char *)GifFile); + if (Error != NULL) + *Error = D_GIF_ERR_NO_SCRN_DSCR; return NULL; } ! GifFile->Error = 0; ! ! /* What version of GIF? */ ! Private->gif89 = (Buf[GIF_VERSION_POS] == '9'); return GifFile; } /****************************************************************************** ! This routine should be called before any other DGif calls. Note that ! this routine is called automatically from DGif file open routines. ! ******************************************************************************/ int ! DGifGetScreenDesc(GifFileType *GifFile) ! { ! int BitsPerPixel; ! bool SortFlag; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } /* Put the screen descriptor into the file: */ if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { ! GifFile->Error = D_GIF_ERR_READ_FAILED; ! GifFreeMapObject(GifFile->SColorMap); ! GifFile->SColorMap = NULL; return GIF_ERROR; } GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1; + SortFlag = (Buf[0] & 0x08) != 0; BitsPerPixel = (Buf[0] & 0x07) + 1; GifFile->SBackGroundColor = Buf[1]; + GifFile->AspectByte = Buf[2]; if (Buf[0] & 0x80) { /* Do we have global color map? */ + int i; ! GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { ! GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* 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; ! GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; GifFile->SColorMap->Colors[i].Green = Buf[1]; GifFile->SColorMap->Colors[i].Blue = Buf[2];
*** 306,435 **** return GIF_OK; } /****************************************************************************** ! * This routine should be called before any attempt to read an image. ! *****************************************************************************/ int ! DGifGetRecordType(GifFileType * GifFile, ! GifRecordType * Type) { ! GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (READ(GifFile, &Buf, 1) != 1) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } switch (Buf) { ! case ',': *Type = IMAGE_DESC_RECORD_TYPE; break; ! case '!': *Type = EXTENSION_RECORD_TYPE; break; ! case ';': *Type = TERMINATE_RECORD_TYPE; break; default: *Type = UNDEFINED_RECORD_TYPE; ! _GifError = D_GIF_ERR_WRONG_RECORD; return GIF_ERROR; } return GIF_OK; } /****************************************************************************** ! * This routine should be called before any attempt to read an image. ! * Note it is assumed the Image desc. header (',') has been read. ! *****************************************************************************/ int ! DGifGetImageDesc(GifFileType * GifFile) { ! ! int i, BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; SavedImage *sp; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 1) != 1) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; ! GifFile->Image.Interlace = (Buf[0] & 0x40); ! if (Buf[0] & 0x80) { /* Does this image have local color map? */ ! /*** FIXME: Why do we check both of these in order to do this? ! * Why do we have both Image and SavedImages? */ ! if (GifFile->Image.ColorMap && GifFile->SavedImages == NULL) ! FreeMapObject(GifFile->Image.ColorMap); ! GifFile->Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* Get the image local color map: */ for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) { if (READ(GifFile, Buf, 3) != 3) { ! FreeMapObject(GifFile->Image.ColorMap); ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } - } else if (GifFile->Image.ColorMap) { - FreeMapObject(GifFile->Image.ColorMap); - GifFile->Image.ColorMap = NULL; } if (GifFile->SavedImages) { ! if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages, ! sizeof(SavedImage) * ! (GifFile->ImageCount + 1))) == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } else { if ((GifFile->SavedImages = (SavedImage *) malloc(sizeof(SavedImage))) == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { ! sp->ImageDesc.ColorMap = MakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { ! _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp->RasterBits = (unsigned char *)NULL; sp->ExtensionBlockCount = 0; --- 312,447 ---- return GIF_OK; } /****************************************************************************** ! This routine should be called before any attempt to read an image. ! ******************************************************************************/ int ! DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type) ! { GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } + /* coverity[check_return] */ if (READ(GifFile, &Buf, 1) != 1) { ! GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } switch (Buf) { ! case DESCRIPTOR_INTRODUCER: *Type = IMAGE_DESC_RECORD_TYPE; break; ! case EXTENSION_INTRODUCER: *Type = EXTENSION_RECORD_TYPE; break; ! case TERMINATOR_INTRODUCER: *Type = TERMINATE_RECORD_TYPE; break; default: *Type = UNDEFINED_RECORD_TYPE; ! GifFile->Error = D_GIF_ERR_WRONG_RECORD; return GIF_ERROR; } return GIF_OK; } /****************************************************************************** ! This routine should be called before any attempt to read an image. ! Note it is assumed the Image desc. header has been read. ! ******************************************************************************/ int ! DGifGetImageDesc(GifFileType *GifFile) ! { ! unsigned int BitsPerPixel; GifByteType Buf[3]; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; SavedImage *sp; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR || DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 1) != 1) { ! GifFile->Error = D_GIF_ERR_READ_FAILED; ! GifFreeMapObject(GifFile->Image.ColorMap); ! GifFile->Image.ColorMap = NULL; return GIF_ERROR; } BitsPerPixel = (Buf[0] & 0x07) + 1; ! GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false; ! /* Setup the colormap */ ! if (GifFile->Image.ColorMap) { ! GifFreeMapObject(GifFile->Image.ColorMap); ! GifFile->Image.ColorMap = NULL; ! } ! /* Does this image have local color map? */ ! if (Buf[0] & 0x80) { ! unsigned int i; ! GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { ! GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } /* 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; ! GifFile->Image.ColorMap = NULL; return GIF_ERROR; } GifFile->Image.ColorMap->Colors[i].Red = Buf[0]; GifFile->Image.ColorMap->Colors[i].Green = Buf[1]; GifFile->Image.ColorMap->Colors[i].Blue = Buf[2]; } } if (GifFile->SavedImages) { ! SavedImage* new_saved_images = ! (SavedImage *)realloc(GifFile->SavedImages, ! sizeof(SavedImage) * (GifFile->ImageCount + 1)); ! 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) { ! GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { ! sp->ImageDesc.ColorMap = GifMakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { ! GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } sp->RasterBits = (unsigned char *)NULL; sp->ExtensionBlockCount = 0;
*** 438,484 **** GifFile->ImageCount++; Private->PixelCount = (long)GifFile->Image.Width * (long)GifFile->Image.Height; ! return DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ } /****************************************************************************** ! * Get one full scanned line (Line) of length LineLen from GIF file. ! *****************************************************************************/ int ! DGifGetLine(GifFileType * GifFile, ! GifPixelType * Line, ! int LineLen) { ! GifByteType *Dummy; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (!LineLen) LineLen = GifFile->Image.Width; - #if defined(__MSDOS__) || defined(__GNUC__) if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { ! #else ! if ((Private->PixelCount -= LineLen) > 0xffff0000) { ! #endif /* __MSDOS__ */ ! _GifError = D_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { if (Private->PixelCount == 0) { ! /* We probably would not be called any more, so lets clean ! * everything before we return: need to flush out all rest of ! * image until empty block (size 0) detected. We use GetCodeNext. */ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) return GIF_ERROR; while (Dummy != NULL) ; } --- 450,493 ---- GifFile->ImageCount++; Private->PixelCount = (long)GifFile->Image.Width * (long)GifFile->Image.Height; ! /* Reset decompress algorithm parameters. */ ! return DGifSetupDecompress(GifFile); } /****************************************************************************** ! Get one full scanned line (Line) of length LineLen from GIF file. ! ******************************************************************************/ int ! DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) ! { GifByteType *Dummy; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (!LineLen) LineLen = GifFile->Image.Width; if ((Private->PixelCount -= LineLen) > 0xffff0000UL) { ! GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) { if (Private->PixelCount == 0) { ! /* We probably won't be called any more, so let's clean up ! * everything before we return: need to flush out all the ! * rest of image until an empty block (size 0) ! * detected. We use GetCodeNext. ! */ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) return GIF_ERROR; while (Dummy != NULL) ; }
*** 486,524 **** } else return GIF_ERROR; } /****************************************************************************** ! * Put one pixel (Pixel) into GIF file. ! *****************************************************************************/ int ! DGifGetPixel(GifFileType * GifFile, ! GifPixelType Pixel) { ! GifByteType *Dummy; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } - #if defined(__MSDOS__) || defined(__GNUC__) if (--Private->PixelCount > 0xffff0000UL) - #else - if (--Private->PixelCount > 0xffff0000) - #endif /* __MSDOS__ */ { ! _GifError = D_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { if (Private->PixelCount == 0) { ! /* We probably would not be called any more, so lets clean ! * everything before we return: need to flush out all rest of ! * image until empty block (size 0) detected. We use GetCodeNext. */ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) return GIF_ERROR; while (Dummy != NULL) ; } --- 495,530 ---- } else return GIF_ERROR; } /****************************************************************************** ! Put one pixel (Pixel) into GIF file. ! ******************************************************************************/ int ! DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) ! { GifByteType *Dummy; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (--Private->PixelCount > 0xffff0000UL) { ! GifFile->Error = D_GIF_ERR_DATA_TOO_BIG; return GIF_ERROR; } if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) { if (Private->PixelCount == 0) { ! /* We probably won't be called any more, so let's clean up ! * everything before we return: need to flush out all the ! * rest of image until an empty block (size 0) ! * detected. We use GetCodeNext. ! */ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR) return GIF_ERROR; while (Dummy != NULL) ; }
*** 526,709 **** } else return GIF_ERROR; } /****************************************************************************** ! * Get an extension block (see GIF manual) from gif file. This routine only ! * returns the first data block, and DGifGetExtensionNext should be called ! * after this one until NULL extension is returned. ! * The Extension should NOT be freed by the user (not dynamically allocated). ! * Note it is assumed the Extension desc. header ('!') has been read. ! *****************************************************************************/ int ! DGifGetExtension(GifFileType * GifFile, ! int *ExtCode, ! GifByteType ** Extension) { ! GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (READ(GifFile, &Buf, 1) != 1) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *ExtCode = Buf; return DGifGetExtensionNext(GifFile, Extension); } /****************************************************************************** ! * Get a following extension block (see GIF manual) from gif file. This ! * routine should be called until NULL Extension is returned. ! * The Extension should NOT be freed by the user (not dynamically allocated). ! *****************************************************************************/ int ! DGifGetExtensionNext(GifFileType * GifFile, ! GifByteType ** Extension) { ! GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (READ(GifFile, &Buf, 1) != 1) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } if (Buf > 0) { *Extension = Private->Buf; /* Use private unused buffer. */ (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else *Extension = NULL; return GIF_OK; } /****************************************************************************** ! * This routine should be called last, to close the GIF file. ! *****************************************************************************/ ! int ! DGifCloseFile(GifFileType * GifFile) { ! GifFilePrivateType *Private; ! FILE *File; ! ! if (GifFile == NULL) return GIF_ERROR; ! Private = (GifFilePrivateType *) GifFile->Private; ! if (!IS_READABLE(Private)) { ! /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } ! File = Private->File; if (GifFile->Image.ColorMap) { ! FreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } if (GifFile->SColorMap) { ! FreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; } - if (Private) { - free((char *)Private); - Private = NULL; - } - if (GifFile->SavedImages) { ! FreeSavedImages(GifFile); GifFile->SavedImages = NULL; } free(GifFile); ! if (File && (fclose(File) != 0)) { ! _GifError = D_GIF_ERR_CLOSE_FAILED; return GIF_ERROR; } return GIF_OK; } /****************************************************************************** ! * Get 2 bytes (word) from the given file: ! *****************************************************************************/ static int ! DGifGetWord(GifFileType * GifFile, ! int *Word) { ! unsigned char c[2]; if (READ(GifFile, c, 2) != 2) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } ! *Word = (((unsigned int)c[1]) << 8) + c[0]; return GIF_OK; } /****************************************************************************** ! * Get the image code in compressed form. This routine can be called if the ! * information needed to be piped out as is. Obviously this is much faster ! * than decoding and encoding again. This routine should be followed by calls ! * to DGifGetCodeNext, until NULL block is returned. ! * The block should NOT be freed by the user (not dynamically allocated). ! *****************************************************************************/ int ! DGifGetCode(GifFileType * GifFile, ! int *CodeSize, ! GifByteType ** CodeBlock) { ! GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } *CodeSize = Private->BitsPerPixel; return DGifGetCodeNext(GifFile, CodeBlock); } /****************************************************************************** ! * Continue to get the image code in compressed form. This routine should be ! * called until NULL block is returned. ! * The block should NOT be freed by the user (not dynamically allocated). ! *****************************************************************************/ int ! DGifGetCodeNext(GifFileType * GifFile, ! GifByteType ** CodeBlock) { ! GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (READ(GifFile, &Buf, 1) != 1) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } if (Buf > 0) { *CodeBlock = Private->Buf; /* Use private unused buffer. */ (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else { *CodeBlock = NULL; Private->Buf[0] = 0; /* Make sure the buffer is empty! */ --- 532,767 ---- } else return GIF_ERROR; } /****************************************************************************** ! Get an extension block (see GIF manual) from GIF file. This routine only ! returns the first data block, and DGifGetExtensionNext should be called ! after this one until NULL extension is returned. ! The Extension should NOT be freed by the user (not dynamically allocated). ! Note it is assumed the Extension description header has been read. ! ******************************************************************************/ int ! DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension) ! { GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } + /* coverity[check_return] */ if (READ(GifFile, &Buf, 1) != 1) { ! GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *ExtCode = Buf; return DGifGetExtensionNext(GifFile, Extension); } /****************************************************************************** ! Get a following extension block (see GIF manual) from GIF file. This ! routine should be called until NULL Extension is returned. ! The Extension should NOT be freed by the user (not dynamically allocated). ! ******************************************************************************/ int ! DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension) ! { GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (READ(GifFile, &Buf, 1) != 1) { ! GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } if (Buf > 0) { *Extension = Private->Buf; /* Use private unused buffer. */ (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data,check_return] */ if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) { ! GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else *Extension = NULL; return GIF_OK; } /****************************************************************************** ! Extract a Graphics Control Block from raw extension data ! ******************************************************************************/ ! int DGifExtensionToGCB(const size_t GifExtensionLength, ! const GifByteType *GifExtension, ! GraphicsControlBlock *GCB) ! { ! if (GifExtensionLength != 4) { return GIF_ERROR; + } ! GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07; ! GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0; ! GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]); ! if (GifExtension[0] & 0x01) ! GCB->TransparentColor = (int)GifExtension[3]; ! else ! GCB->TransparentColor = NO_TRANSPARENT_COLOR; ! return GIF_OK; ! } ! ! /****************************************************************************** ! Extract the Graphics Control Block for a saved image, if it exists. ! ******************************************************************************/ ! ! int DGifSavedExtensionToGCB(GifFileType *GifFile, ! int ImageIndex, GraphicsControlBlock *GCB) ! { ! int i; ! ! if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) return GIF_ERROR; + + GCB->DisposalMode = DISPOSAL_UNSPECIFIED; + GCB->UserInputFlag = false; + GCB->DelayTime = 0; + GCB->TransparentColor = NO_TRANSPARENT_COLOR; + + for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) { + ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i]; + if (ep->Function == GRAPHICS_EXT_FUNC_CODE) + return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB); } ! return GIF_ERROR; ! } ! ! /****************************************************************************** ! This routine should be called last, to close the GIF file. ! ******************************************************************************/ ! int ! DGifCloseFile(GifFileType *GifFile, int *ErrorCode) ! { ! GifFilePrivateType *Private; ! ! if (GifFile == NULL || GifFile->Private == NULL) ! return GIF_ERROR; if (GifFile->Image.ColorMap) { ! GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } if (GifFile->SColorMap) { ! GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; } if (GifFile->SavedImages) { ! GifFreeSavedImages(GifFile); GifFile->SavedImages = NULL; } + GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks); + + Private = (GifFilePrivateType *) GifFile->Private; + + if (!IS_READABLE(Private)) { + /* This file was NOT open for reading: */ + 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)) { ! if (ErrorCode != NULL) ! *ErrorCode = D_GIF_ERR_CLOSE_FAILED; ! free((char *)GifFile->Private); ! free(GifFile); return GIF_ERROR; } + + free((char *)GifFile->Private); + free(GifFile); + if (ErrorCode != NULL) + *ErrorCode = D_GIF_SUCCEEDED; return GIF_OK; } /****************************************************************************** ! Get 2 bytes (word) from the given file: ! ******************************************************************************/ static int ! 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; } ! *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]); return GIF_OK; } /****************************************************************************** ! Get the image code in compressed form. This routine can be called if the ! information needed to be piped out as is. Obviously this is much faster ! than decoding and encoding again. This routine should be followed by calls ! to DGifGetCodeNext, until NULL block is returned. ! The block should NOT be freed by the user (not dynamically allocated). ! ******************************************************************************/ int ! DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) ! { GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } *CodeSize = Private->BitsPerPixel; return DGifGetCodeNext(GifFile, CodeBlock); } /****************************************************************************** ! Continue to get the image code in compressed form. This routine should be ! called until NULL block is returned. ! The block should NOT be freed by the user (not dynamically allocated). ! ******************************************************************************/ int ! DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) ! { GifByteType Buf; 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; } + /* coverity[lower_bounds] */ if (Buf > 0) { *CodeBlock = Private->Buf; /* Use private unused buffer. */ (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */ + /* coverity[tainted_data] */ if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) { ! GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else { *CodeBlock = NULL; Private->Buf[0] = 0; /* Make sure the buffer is empty! */
*** 712,735 **** return GIF_OK; } /****************************************************************************** ! * Setup the LZ decompression for this image: ! *****************************************************************************/ static int ! DGifSetupDecompress(GifFileType * GifFile) { ! int i, BitsPerPixel; GifByteType CodeSize; ! unsigned int *Prefix; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; ! READ(GifFile, &CodeSize, 1); /* Read Code size from file. */ ! if (CodeSize >= 12) { ! /* Invalid initial code size: report failure */ ! return GIF_ERROR; } BitsPerPixel = CodeSize; Private->Buf[0] = 0; /* Input Buffer empty. */ Private->BitsPerPixel = BitsPerPixel; --- 770,792 ---- return GIF_OK; } /****************************************************************************** ! Setup the LZ decompression for this image: ! ******************************************************************************/ static int ! DGifSetupDecompress(GifFileType *GifFile) ! { int i, BitsPerPixel; GifByteType CodeSize; ! GifPrefixType *Prefix; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; ! /* coverity[check_return] */ ! if (READ(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */ ! return GIF_ERROR; /* Failed to read Code size. */ } BitsPerPixel = CodeSize; Private->Buf[0] = 0; /* Input Buffer empty. */ Private->BitsPerPixel = BitsPerPixel;
*** 749,784 **** return GIF_OK; } /****************************************************************************** ! * The LZ decompression routine: ! * This version decompress the given gif file into Line of length LineLen. ! * This routine can be called few times (one per scan line, for example), in ! * order the complete the whole image. ! *****************************************************************************/ static int ! DGifDecompressLine(GifFileType * GifFile, ! GifPixelType * Line, ! int LineLen) { ! int i = 0; int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; GifByteType *Stack, *Suffix; ! unsigned int *Prefix; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; StackPtr = Private->StackPtr; Prefix = Private->Prefix; Suffix = Private->Suffix; Stack = Private->Stack; EOFCode = Private->EOFCode; ClearCode = Private->ClearCode; LastCode = Private->LastCode; if (StackPtr != 0) { ! /* Let pop the stack off before continueing to read the gif file: */ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } while (i < LineLen) { /* Decode LineLen items. */ --- 806,843 ---- return GIF_OK; } /****************************************************************************** ! The LZ decompression routine: ! This version decompress the given GIF file into Line of length LineLen. ! This routine can be called few times (one per scan line, for example), in ! order the complete the whole image. ! ******************************************************************************/ static int ! DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) ! { int i = 0; int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; GifByteType *Stack, *Suffix; ! GifPrefixType *Prefix; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; StackPtr = Private->StackPtr; Prefix = Private->Prefix; Suffix = Private->Suffix; Stack = Private->Stack; EOFCode = Private->EOFCode; ClearCode = Private->ClearCode; LastCode = Private->LastCode; + if (StackPtr > LZ_MAX_CODE) { + return GIF_ERROR; + } + if (StackPtr != 0) { ! /* Let pop the stack off before continueing to read the GIF file: */ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } while (i < LineLen) { /* Decode LineLen items. */
*** 787,801 **** if (CrntCode == EOFCode) { /* Note however that usually we will not be here as we will stop * decoding as soon as we got all the pixel, or EOF code will * not be read at all, and DGifGetLine/Pixel clean everything. */ ! if (i != LineLen - 1 || Private->PixelCount != 0) { ! _GifError = D_GIF_ERR_EOF_TOO_SOON; return GIF_ERROR; - } - i++; } else if (CrntCode == ClearCode) { /* We need to start over again: */ for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE; Private->RunningCode = Private->EOFCode + 1; --- 846,857 ---- if (CrntCode == EOFCode) { /* Note however that usually we will not be here as we will stop * decoding as soon as we got all the pixel, or EOF code will * not be read at all, and DGifGetLine/Pixel clean everything. */ ! GifFile->Error = D_GIF_ERR_EOF_TOO_SOON; return GIF_ERROR; } else if (CrntCode == ClearCode) { /* We need to start over again: */ for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE; Private->RunningCode = Private->EOFCode + 1;
*** 813,862 **** /* Its a code to needed to be traced: trace the linked list * until the prefix is a pixel, while pushing the suffix * 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) { /* 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 { ! _GifError = D_GIF_ERR_IMAGE_DEFECT; ! return GIF_ERROR; } } else CrntPrefix = CrntCode; ! /* Now (if image is O.K.) we should not get an NO_SUCH_CODE ! * During the trace. As we might loop forever, in case of ! * defective image, we count the number of loops we trace ! * and stop if we got LZ_MAX_CODE. obviously we can not ! * loop more than that. */ ! j = 0; ! while (j++ <= LZ_MAX_CODE && CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) { Stack[StackPtr++] = Suffix[CrntPrefix]; CrntPrefix = Prefix[CrntPrefix]; } ! if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { ! _GifError = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } /* Push the last character on stack: */ Stack[StackPtr++] = CrntPrefix; /* Now lets pop all the stack into output: */ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } ! if (LastCode != NO_SUCH_CODE) { Prefix[Private->RunningCode - 2] = LastCode; if (CrntCode == Private->RunningCode - 2) { /* Only allowed if CrntCode is exactly the running code: * In that case CrntCode = XXXCode, CrntCode or the --- 869,919 ---- /* Its a code to needed to be traced: trace the linked list * until the prefix is a pixel, while pushing the suffix * 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) { Suffix[Private->RunningCode - 2] = Stack[StackPtr++] = DGifGetPrefixChar(Prefix, LastCode, ClearCode); } else { ! Suffix[Private->RunningCode - 2] = ! Stack[StackPtr++] = DGifGetPrefixChar(Prefix, ! CrntCode, ! ClearCode); } } else CrntPrefix = CrntCode; ! /* Now (if image is O.K.) we should not get a NO_SUCH_CODE ! * during the trace. As we might loop forever, in case of ! * defective image, we use StackPtr as loop counter and stop ! * before overflowing Stack[]. */ ! while (StackPtr < LZ_MAX_CODE && CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) { Stack[StackPtr++] = Suffix[CrntPrefix]; CrntPrefix = Prefix[CrntPrefix]; } ! if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { ! GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; return GIF_ERROR; } /* Push the last character on stack: */ Stack[StackPtr++] = CrntPrefix; /* Now lets pop all the stack into output: */ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } ! if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { Prefix[Private->RunningCode - 2] = LastCode; if (CrntCode == Private->RunningCode - 2) { /* Only allowed if CrntCode is exactly the running code: * In that case CrntCode = XXXCode, CrntCode or the
*** 878,918 **** return GIF_OK; } /****************************************************************************** ! * Routine to trace the Prefixes linked list until we get a prefix which is ! * not code, but a pixel value (less than ClearCode). Returns that pixel value. ! * If image is defective, we might loop here forever, so we limit the loops to ! * the maximum possible if image O.k. - LZ_MAX_CODE times. ! *****************************************************************************/ static int ! DGifGetPrefixChar(unsigned int *Prefix, ! int Code, ! int ClearCode) { ! int i = 0; ! while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code]; return Code; } /****************************************************************************** ! * Interface for accessing the LZ codes directly. Set Code to the real code ! * (12bits), or to -1 if EOF code is returned. ! *****************************************************************************/ int ! DGifGetLZCodes(GifFileType * GifFile, ! int *Code) { ! GifByteType *CodeBlock; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! _GifError = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) return GIF_ERROR; --- 935,976 ---- return GIF_OK; } /****************************************************************************** ! Routine to trace the Prefixes linked list until we get a prefix which is ! not code, but a pixel value (less than ClearCode). Returns that pixel value. ! If image is defective, we might loop here forever, so we limit the loops to ! the maximum possible if image O.k. - LZ_MAX_CODE times. ! ******************************************************************************/ static int ! DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode) ! { int i = 0; ! while (Code > ClearCode && i++ <= LZ_MAX_CODE) { ! if (Code > LZ_MAX_CODE) { ! return NO_SUCH_CODE; ! } Code = Prefix[Code]; + } return Code; } /****************************************************************************** ! Interface for accessing the LZ codes directly. Set Code to the real code ! (12bits), or to -1 if EOF code is returned. ! ******************************************************************************/ int ! DGifGetLZCodes(GifFileType *GifFile, int *Code) ! { GifByteType *CodeBlock; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (!IS_READABLE(Private)) { /* This file was NOT open for reading: */ ! GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) return GIF_ERROR;
*** 934,962 **** return GIF_OK; } /****************************************************************************** ! * The LZ decompression input routine: ! * This routine is responsable for the decompression of the bit stream from ! * 8 bits (bytes) packets, into the real codes. ! * Returns GIF_OK if read succesfully. ! *****************************************************************************/ static int ! DGifDecompressInput(GifFileType * GifFile, ! int *Code) { ! ! GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; ! ! GifByteType NextByte; ! static unsigned int CodeMasks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff }; while (Private->CrntShiftState < Private->RunningBits) { /* Needs to get more bytes from input stream for next code: */ if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) { return GIF_ERROR; } --- 992,1026 ---- return GIF_OK; } /****************************************************************************** ! The LZ decompression input routine: ! This routine is responsable for the decompression of the bit stream from ! 8 bits (bytes) packets, into the real codes. ! Returns GIF_OK if read successfully. ! ******************************************************************************/ static int ! DGifDecompressInput(GifFileType *GifFile, int *Code) ! { ! static const unsigned short CodeMasks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff }; + GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; + + GifByteType NextByte; + + /* The image can't contain more than LZ_BITS per code. */ + if (Private->RunningBits > LZ_BITS) { + GifFile->Error = D_GIF_ERR_IMAGE_DEFECT; + return GIF_ERROR; + } + while (Private->CrntShiftState < Private->RunningBits) { /* Needs to get more bytes from input stream for next code: */ if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) { return GIF_ERROR; }
*** 968,1008 **** Private->CrntShiftDWord >>= Private->RunningBits; Private->CrntShiftState -= Private->RunningBits; /* If code cannot fit into RunningBits bits, must raise its size. Note ! * however that codes above 4095 are used for special signaling. */ ! if (++Private->RunningCode > Private->MaxCode1) { ! if (Private->RunningBits < LZ_BITS) { Private->MaxCode1 <<= 1; Private->RunningBits++; - } else { - Private->RunningCode = Private->MaxCode1; - } } return GIF_OK; } /****************************************************************************** ! * This routines read one gif data block at a time and buffers it internally ! * so that the decompression routine could access it. ! * The routine returns the next byte from its internal buffer (or read next ! * block in if buffer empty) and returns GIF_OK if succesful. ! *****************************************************************************/ static int ! DGifBufferedInput(GifFileType * GifFile, ! GifByteType * Buf, ! GifByteType * NextByte) { ! if (Buf[0] == 0) { /* Needs to read the next buffer - this one is empty: */ if (READ(GifFile, Buf, 1) != 1) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) { ! _GifError = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *NextByte = Buf[1]; Buf[1] = 2; /* We use now the second place as last char read! */ Buf[0]--; --- 1032,1080 ---- Private->CrntShiftDWord >>= Private->RunningBits; Private->CrntShiftState -= Private->RunningBits; /* If code cannot fit into RunningBits bits, must raise its size. Note ! * however that codes above 4095 are used for special signaling. ! * If we're using LZ_BITS bits already and we're at the max code, just ! * keep using the table as it is, don't increment Private->RunningCode. ! */ ! if (Private->RunningCode < LZ_MAX_CODE + 2 && ! ++Private->RunningCode > Private->MaxCode1 && ! Private->RunningBits < LZ_BITS) { Private->MaxCode1 <<= 1; Private->RunningBits++; } return GIF_OK; } /****************************************************************************** ! This routines read one GIF data block at a time and buffers it internally ! so that the decompression routine could access it. ! The routine returns the next byte from its internal buffer (or read next ! block in if buffer empty) and returns GIF_OK if succesful. ! ******************************************************************************/ static int ! 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; ! } ! /* 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; } *NextByte = Buf[1]; Buf[1] = 2; /* We use now the second place as last char read! */ Buf[0]--;
*** 1013,1037 **** return GIF_OK; } /****************************************************************************** ! * This routine reads an entire GIF into core, hanging all its state info off ! * the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() ! * first to initialize I/O. Its inverse is EGifSpew(). ! ******************************************************************************/ int ! DGifSlurp(GifFileType * GifFile) { ! ! int ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; ! SavedImage temp_save; ! temp_save.ExtensionBlocks = NULL; ! temp_save.ExtensionBlockCount = 0; do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) return (GIF_ERROR); --- 1085,1109 ---- return GIF_OK; } /****************************************************************************** ! This routine reads an entire GIF into core, hanging all its state info off ! the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() ! first to initialize I/O. Its inverse is EGifSpew(). ! *******************************************************************************/ int ! DGifSlurp(GifFileType *GifFile) ! { ! size_t ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; ! int ExtFunction; ! GifFile->ExtensionBlocks = NULL; ! GifFile->ExtensionBlockCount = 0; do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) return (GIF_ERROR);
*** 1039,1086 **** case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) return (GIF_ERROR); sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; sp->RasterBits = (unsigned char *)malloc(ImageSize * sizeof(GifPixelType)); if (sp->RasterBits == NULL) { return GIF_ERROR; } ! if (DGifGetLine(GifFile, sp->RasterBits, ImageSize) == ! GIF_ERROR) return (GIF_ERROR); ! if (temp_save.ExtensionBlocks) { ! sp->ExtensionBlocks = temp_save.ExtensionBlocks; ! sp->ExtensionBlockCount = temp_save.ExtensionBlockCount; ! ! temp_save.ExtensionBlocks = NULL; ! temp_save.ExtensionBlockCount = 0; ! ! /* FIXME: The following is wrong. It is left in only for ! * backwards compatibility. Someday it should go away. Use ! * the sp->ExtensionBlocks->Function variable instead. */ ! sp->Function = sp->ExtensionBlocks[0].Function; } break; case EXTENSION_RECORD_TYPE: ! if (DGifGetExtension(GifFile, &temp_save.Function, &ExtData) == ! GIF_ERROR) return (GIF_ERROR); - while (ExtData != NULL) { - /* Create an extension block with our data */ ! if (AddExtensionBlock(&temp_save, ExtData[0], &ExtData[1]) == GIF_ERROR) return (GIF_ERROR); ! if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return (GIF_ERROR); ! temp_save.Function = 0; } break; case TERMINATE_RECORD_TYPE: break; --- 1111,1191 ---- case IMAGE_DESC_RECORD_TYPE: if (DGifGetImageDesc(GifFile) == GIF_ERROR) return (GIF_ERROR); sp = &GifFile->SavedImages[GifFile->ImageCount - 1]; + /* Allocate memory for the image */ + if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 && + sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) { + return GIF_ERROR; + } ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height; + if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) { + return GIF_ERROR; + } sp->RasterBits = (unsigned char *)malloc(ImageSize * sizeof(GifPixelType)); + if (sp->RasterBits == NULL) { return GIF_ERROR; } ! ! if (sp->ImageDesc.Interlace) { ! int i, j; ! /* ! * The way an interlaced image should be read - ! * offsets and jumps... ! */ ! int InterlacedOffset[] = { 0, 4, 2, 1 }; ! int InterlacedJumps[] = { 8, 8, 4, 2 }; ! /* Need to perform 4 passes on the image */ ! for (i = 0; i < 4; i++) ! for (j = InterlacedOffset[i]; ! j < sp->ImageDesc.Height; ! j += InterlacedJumps[i]) { ! if (DGifGetLine(GifFile, ! sp->RasterBits+j*sp->ImageDesc.Width, ! sp->ImageDesc.Width) == GIF_ERROR) ! return GIF_ERROR; ! } ! } ! else { ! if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR) return (GIF_ERROR); ! } ! ! if (GifFile->ExtensionBlocks) { ! sp->ExtensionBlocks = GifFile->ExtensionBlocks; ! sp->ExtensionBlockCount = GifFile->ExtensionBlockCount; ! ! GifFile->ExtensionBlocks = NULL; ! GifFile->ExtensionBlockCount = 0; } break; case EXTENSION_RECORD_TYPE: ! if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR) 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); ! } ! while (ExtData != NULL) { if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR) return (GIF_ERROR); ! /* Continue the extension block */ ! if (ExtData != NULL) ! if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount, ! &GifFile->ExtensionBlocks, ! CONTINUE_EXT_FUNC_CODE, ! ExtData[0], &ExtData[1]) == GIF_ERROR) ! return (GIF_ERROR); } break; case TERMINATE_RECORD_TYPE: break;
*** 1088,1101 **** default: /* Should be trapped by DGifGetRecordType */ break; } } while (RecordType != TERMINATE_RECORD_TYPE); ! /* Just in case the Gif has an extension block without an associated ! * image... (Should we save this into a savefile structure with no image ! * instead? Have to check if the present writing code can handle that as ! * well.... */ ! if (temp_save.ExtensionBlocks) ! FreeExtension(&temp_save); return (GIF_OK); } --- 1193,1207 ---- default: /* Should be trapped by DGifGetRecordType */ break; } } 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); } + + /* end */
< prev index next >