--- old/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c 2015-04-17 18:02:59.052353463 +0300 +++ new/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c 2015-04-17 18:02:58.932353460 +0300 @@ -23,219 +23,211 @@ */ /****************************************************************************** - * "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 -#endif + +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 -#if defined (__MSDOS__) && !defined(__DJGPP__) && !defined(__GNUC__) -#include -#include -#include -#else -#include -#include -#endif /* __MSDOS__ */ +#include +#include +#include +#include +#include #ifdef _WIN32 #include -#define _OPEN_BINARY #else #include -#endif +#endif /* _WIN32 */ -#include - -#include -#include #include "gif_lib.h" #include "gif_lib_private.h" -#define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for - comment. */ +/* 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 ? \ - (size_t)((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \ + ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \ fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File)) -static int DGifGetWord(GifFileType *GifFile, int *Word); +static int DGifGetWord(GifFileType *GifFile, GifWord *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 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 GifFileType pointer dynamically allocated which serves as the gif - * info record. _GifError is cleared if succesfull. - *****************************************************************************/ + 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) { +DGifOpenFileName(const char *FileName, int *Error) +{ 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; + if ((FileHandle = open(FileName, O_RDONLY)) == -1) { + if (Error != NULL) + *Error = D_GIF_ERR_OPEN_FAILED; return NULL; } - GifFile = DGifOpenFileHandle(FileHandle); - if (GifFile == (GifFileType *)NULL) - close(FileHandle); + GifFile = DGifOpenFileHandle(FileHandle, Error); 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. - *****************************************************************************/ + 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) { - - unsigned char Buf[GIF_STAMP_LEN + 1]; +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) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + if (Error != NULL) + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + (void)close(FileHandle); return NULL; } - memset(GifFile, '\0', sizeof(GifFileType)); + /*@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) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + if (Error != NULL) + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; + (void)close(FileHandle); free((char *)GifFile); return NULL; } -#ifdef __MSDOS__ - setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ -#endif /* __MSDOS__ */ +#ifdef _WIN32 + _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */ +#endif /* _WIN32 */ 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; + /*@-mustfreeonly@*/ + GifFile->Private = (void *)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); + 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; } - /* The GIF Version number is ignored at this time. Maybe we should do - * something more useful with it. */ + /* Check for GIF prefix at start of file */ 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); + 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) { - fclose(f); + (void)fclose(f); free((char *)Private); free((char *)GifFile); return NULL; } - _GifError = 0; + 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 constructor with user supplied input function (TVT) +******************************************************************************/ GifFileType * -DGifOpen(void *userData, - InputFunc readFunc) { - - unsigned char Buf[GIF_STAMP_LEN + 1]; +DGifOpen(void *userData, InputFunc readFunc, int *Error) +{ + 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; + 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) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + if (Error != NULL) + *Error = D_GIF_ERR_NOT_ENOUGH_MEM; free((char *)GifFile); return NULL; } - GifFile->Private = (VoidPtr)Private; + GifFile->Private = (void *)Private; Private->FileHandle = 0; - Private->File = 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: */ - if (READ(GifFile, Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) { - _GifError = D_GIF_ERR_READ_FAILED; + /* 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; } - /* 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; + /* 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; @@ -244,28 +236,34 @@ if (DGifGetScreenDesc(GifFile) == GIF_ERROR) { free((char *)Private); free((char *)GifFile); + if (Error != NULL) + *Error = D_GIF_ERR_NO_SCRN_DSCR; return NULL; } - _GifError = 0; + 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. - *****************************************************************************/ + 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; +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: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -275,25 +273,33 @@ return GIF_ERROR; if (READ(GifFile, Buf, 3) != 3) { - _GifError = D_GIF_ERR_READ_FAILED; + 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 = MakeMapObject(1 << BitsPerPixel, NULL); + GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->SColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + 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) { - FreeMapObject(GifFile->SColorMap); - _GifError = D_GIF_ERR_READ_FAILED; + GifFreeMapObject(GifFile->SColorMap); + GifFile->SColorMap = NULL; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } GifFile->SColorMap->Colors[i].Red = Buf[0]; @@ -308,39 +314,39 @@ } /****************************************************************************** - * This routine should be called before any attempt to read an image. - *****************************************************************************/ + This routine should be called before any attempt to read an image. +******************************************************************************/ int -DGifGetRecordType(GifFileType * GifFile, - GifRecordType * Type) { - +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; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } + /* coverity[check_return] */ if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } switch (Buf) { - case ',': + case DESCRIPTOR_INTRODUCER: *Type = IMAGE_DESC_RECORD_TYPE; break; - case '!': + case EXTENSION_INTRODUCER: *Type = EXTENSION_RECORD_TYPE; break; - case ';': + case TERMINATOR_INTRODUCER: *Type = TERMINATE_RECORD_TYPE; break; default: *Type = UNDEFINED_RECORD_TYPE; - _GifError = D_GIF_ERR_WRONG_RECORD; + GifFile->Error = D_GIF_ERR_WRONG_RECORD; return GIF_ERROR; } @@ -348,20 +354,20 @@ } /****************************************************************************** - * This routine should be called before any attempt to read an image. - * Note it is assumed the Image desc. header (',') has been read. - *****************************************************************************/ + 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; +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: */ - _GifError = D_GIF_ERR_NOT_READABLE; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -371,51 +377,57 @@ DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) return GIF_ERROR; if (READ(GifFile, Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + 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); - if (Buf[0] & 0x80) { /* Does this image have local color map? */ + GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false; - /*** 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); + /* 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 = MakeMapObject(1 << BitsPerPixel, NULL); + GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL); if (GifFile->Image.ColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + 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) { - FreeMapObject(GifFile->Image.ColorMap); - _GifError = D_GIF_ERR_READ_FAILED; + 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]; } - } 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; + 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) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } @@ -423,11 +435,11 @@ sp = &GifFile->SavedImages[GifFile->ImageCount]; memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc)); if (GifFile->Image.ColorMap != NULL) { - sp->ImageDesc.ColorMap = MakeMapObject( + sp->ImageDesc.ColorMap = GifMakeMapObject( GifFile->Image.ColorMap->ColorCount, GifFile->Image.ColorMap->Colors); if (sp->ImageDesc.ColorMap == NULL) { - _GifError = D_GIF_ERR_NOT_ENOUGH_MEM; + GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; } } @@ -440,43 +452,40 @@ Private->PixelCount = (long)GifFile->Image.Width * (long)GifFile->Image.Height; - return DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */ + /* Reset decompress algorithm parameters. */ + return DGifSetupDecompress(GifFile); } /****************************************************************************** - * Get one full scanned line (Line) of length LineLen from GIF file. - *****************************************************************************/ + Get one full scanned line (Line) of length LineLen from GIF file. +******************************************************************************/ int -DGifGetLine(GifFileType * GifFile, - GifPixelType * Line, - int LineLen) { - +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; + GifFile->Error = 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; + GifFile->Error = 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. */ + /* 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; @@ -488,35 +497,32 @@ } /****************************************************************************** - * Put one pixel (Pixel) into GIF file. - *****************************************************************************/ + Put one pixel (Pixel) into GIF file. +******************************************************************************/ int -DGifGetPixel(GifFileType * GifFile, - GifPixelType Pixel) { - +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; + GifFile->Error = 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; + GifFile->Error = 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. */ + /* 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; @@ -528,28 +534,27 @@ } /****************************************************************************** - * 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. - *****************************************************************************/ + 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) { - +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; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } + /* coverity[check_return] */ if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *ExtCode = Buf; @@ -558,26 +563,26 @@ } /****************************************************************************** - * 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). - *****************************************************************************/ + 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) { - +DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension) +{ GifByteType Buf; GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private; if (READ(GifFile, &Buf, 1) != 1) { - _GifError = D_GIF_ERR_READ_FAILED; + 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) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else @@ -587,91 +592,141 @@ } /****************************************************************************** - * This routine should be called last, to close the GIF file. - *****************************************************************************/ -int -DGifCloseFile(GifFileType * GifFile) { + Extract a Graphics Control Block from raw extension data +******************************************************************************/ - GifFilePrivateType *Private; - FILE *File; +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; - if (GifFile == NULL) - return GIF_ERROR; + return GIF_OK; +} - Private = (GifFilePrivateType *) GifFile->Private; +/****************************************************************************** + Extract the Graphics Control Block for a saved image, if it exists. +******************************************************************************/ - if (!IS_READABLE(Private)) { - /* This file was NOT open for reading: */ - _GifError = D_GIF_ERR_NOT_READABLE; - return GIF_ERROR; +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); } - File = Private->File; + 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) { - FreeMapObject(GifFile->Image.ColorMap); + GifFreeMapObject(GifFile->Image.ColorMap); GifFile->Image.ColorMap = NULL; } if (GifFile->SColorMap) { - FreeMapObject(GifFile->SColorMap); + GifFreeMapObject(GifFile->SColorMap); GifFile->SColorMap = NULL; } - if (Private) { - free((char *)Private); - Private = NULL; - } - if (GifFile->SavedImages) { - FreeSavedImages(GifFile); + GifFreeSavedImages(GifFile); GifFile->SavedImages = NULL; } - free(GifFile); + GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks); - if (File && (fclose(File) != 0)) { - _GifError = D_GIF_ERR_CLOSE_FAILED; + 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: - *****************************************************************************/ + Get 2 bytes (word) from the given file: +******************************************************************************/ static int -DGifGetWord(GifFileType * GifFile, - int *Word) { - +DGifGetWord(GifFileType *GifFile, GifWord *Word) +{ unsigned char c[2]; + /* coverity[check_return] */ if (READ(GifFile, c, 2) != 2) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } - *Word = (((unsigned int)c[1]) << 8) + c[0]; + *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). - *****************************************************************************/ + 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) { - +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; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -681,27 +736,30 @@ } /****************************************************************************** - * 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). - *****************************************************************************/ + 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) { - +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) { - _GifError = D_GIF_ERR_READ_FAILED; + 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) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } } else { @@ -714,20 +772,19 @@ } /****************************************************************************** - * Setup the LZ decompression for this image: - *****************************************************************************/ + Setup the LZ decompression for this image: +******************************************************************************/ static int -DGifSetupDecompress(GifFileType * GifFile) { - +DGifSetupDecompress(GifFileType *GifFile) +{ int i, BitsPerPixel; GifByteType CodeSize; - unsigned int *Prefix; + GifPrefixType *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; + /* coverity[check_return] */ + if (READ(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */ + return GIF_ERROR; /* Failed to read Code size. */ } BitsPerPixel = CodeSize; @@ -751,20 +808,18 @@ } /****************************************************************************** - * 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. - *****************************************************************************/ + 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) { - +DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) +{ int i = 0; int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr; GifByteType *Stack, *Suffix; - unsigned int *Prefix; + GifPrefixType *Prefix; GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private; StackPtr = Private->StackPtr; @@ -775,8 +830,12 @@ 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: */ + /* Let pop the stack off before continueing to read the GIF file: */ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } @@ -789,11 +848,8 @@ /* 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++; + 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++) @@ -815,36 +871,37 @@ * 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 { - _GifError = D_GIF_ERR_IMAGE_DEFECT; - return GIF_ERROR; + Suffix[Private->RunningCode - 2] = + Stack[StackPtr++] = DGifGetPrefixChar(Prefix, + CrntCode, + ClearCode); } } 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 && + /* 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 (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) { - _GifError = D_GIF_ERR_IMAGE_DEFECT; + 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: */ @@ -854,7 +911,7 @@ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr]; } - if (LastCode != NO_SUCH_CODE) { + if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) { Prefix[Private->RunningCode - 2] = LastCode; if (CrntCode == Private->RunningCode - 2) { @@ -880,37 +937,38 @@ } /****************************************************************************** - * 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. - *****************************************************************************/ + 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) { - +DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode) +{ int i = 0; - while (Code > ClearCode && i++ <= LZ_MAX_CODE) + 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. - *****************************************************************************/ + 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) { - +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; + GifFile->Error = D_GIF_ERR_NOT_READABLE; return GIF_ERROR; } @@ -936,32 +994,38 @@ } /****************************************************************************** - * 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. - *****************************************************************************/ + 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) { +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; - static unsigned int CodeMasks[] = { - 0x0000, 0x0001, 0x0003, 0x0007, - 0x000f, 0x001f, 0x003f, 0x007f, - 0x00ff, 0x01ff, 0x03ff, 0x07ff, - 0x0fff - }; + /* 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; } Private->CrntShiftDWord |= - ((unsigned long)NextByte) << Private->CrntShiftState; + ((unsigned long)NextByte) << Private->CrntShiftState; Private->CrntShiftState += 8; } *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits]; @@ -970,37 +1034,45 @@ 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; - } + * 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. - *****************************************************************************/ + 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) { - +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) { - _GifError = D_GIF_ERR_READ_FAILED; + 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]) { - _GifError = D_GIF_ERR_READ_FAILED; + GifFile->Error = D_GIF_ERR_READ_FAILED; return GIF_ERROR; } *NextByte = Buf[1]; @@ -1015,21 +1087,21 @@ } /****************************************************************************** - * 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(). - ******************************************************************************/ + 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; +DGifSlurp(GifFileType *GifFile) +{ + size_t ImageSize; GifRecordType RecordType; SavedImage *sp; GifByteType *ExtData; - SavedImage temp_save; + int ExtFunction; - temp_save.ExtensionBlocks = NULL; - temp_save.ExtensionBlockCount = 0; + GifFile->ExtensionBlocks = NULL; + GifFile->ExtensionBlockCount = 0; do { if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) @@ -1041,44 +1113,77 @@ 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)); + 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; + + 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, &temp_save.Function, &ExtData) == - GIF_ERROR) + 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) { - - /* 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; + /* 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; @@ -1090,12 +1195,13 @@ } } 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); + /* Sanity check for corrupted file */ + if (GifFile->ImageCount == 0) { + GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR; + return(GIF_ERROR); + } return (GIF_OK); } + +/* end */