Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Commit bbca6f0

Browse files
authored
Merge pull request #79 from livecode/develop-8.1
Merge develop-8.1 into develop
2 parents b65670a + bfbd50a commit bbca6f0

10 files changed

Lines changed: 252 additions & 113 deletions

File tree

libgif/ORIGIN.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
Files in this folder are based on giflib-5.0.0
1+
Files in this folder are based on giflib-5.1.4
22

3-
Original source archives are available from <http://giflib.sourceforge.net/>
3+
Original source archives are available from <http://giflib.sourceforge.net/>

libgif/include/gif_lib.h

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ extern "C" {
1212
#endif /* __cplusplus */
1313

1414
#define GIFLIB_MAJOR 5
15-
#define GIFLIB_MINOR 0
16-
#define GIFLIB_RELEASE 0
15+
#define GIFLIB_MINOR 1
16+
#define GIFLIB_RELEASE 4
1717

1818
#define GIF_ERROR 0
1919
#define GIF_OK 1
2020

21+
#include <stddef.h>
2122
#ifndef _WIN32
2223
#include <stdbool.h>
2324
#else
@@ -135,9 +136,10 @@ GifFileType *EGifOpenFileName(const char *GifFileName,
135136
GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error);
136137
GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error);
137138
int EGifSpew(GifFileType * GifFile);
138-
char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */
139-
int EGifCloseFile(GifFileType * GifFile);
139+
const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */
140+
int EGifCloseFile(GifFileType *GifFile, int *ErrorCode);
140141

142+
#define E_GIF_SUCCEEDED 0
141143
#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */
142144
#define E_GIF_ERR_WRITE_FAILED 2
143145
#define E_GIF_ERR_HAS_SCRN_DSCR 3
@@ -160,6 +162,7 @@ int EGifPutImageDesc(GifFileType *GifFile,
160162
const int GifWidth, const int GifHeight,
161163
const bool GifInterlace,
162164
const ColorMapObject *GifColorMap);
165+
void EGifSetGifVersion(GifFileType *GifFile, const bool gif89);
163166
int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine,
164167
int GifLineLen);
165168
int EGifPutPixel(GifFileType *GifFile, const GifPixelType GifPixel);
@@ -185,8 +188,9 @@ GifFileType *DGifOpenFileName(const char *GifFileName, int *Error);
185188
GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error);
186189
int DGifSlurp(GifFileType * GifFile);
187190
GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error); /* new one (TVT) */
188-
int DGifCloseFile(GifFileType * GifFile);
191+
int DGifCloseFile(GifFileType * GifFile, int *ErrorCode);
189192

193+
#define D_GIF_SUCCEEDED 0
190194
#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */
191195
#define D_GIF_ERR_READ_FAILED 102
192196
#define D_GIF_ERR_NOT_GIF_FILE 103
@@ -229,7 +233,7 @@ int GifQuantizeBuffer(unsigned int Width, unsigned int Height,
229233
/******************************************************************************
230234
Error handling and reporting.
231235
******************************************************************************/
232-
extern char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */
236+
extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */
233237

234238
/*****************************************************************************
235239
Everything below this point is new after version 1.2, supporting `slurp
@@ -248,6 +252,9 @@ extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1,
248252
GifPixelType ColorTransIn2[]);
249253
extern int GifBitSize(int n);
250254

255+
extern void *
256+
reallocarray(void *optr, size_t nmemb, size_t size);
257+
251258
/******************************************************************************
252259
Support for the in-core structures allocation (slurp mode).
253260
******************************************************************************/

libgif/libgif.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
'src/gif_font.c',
4141
'src/gif_hash.c',
4242
'src/gifalloc.c',
43+
'src/openbsd-reallocarray.c',
4344
'src/quantize.c',
4445
],
4546

libgif/src/dgif_lib.c

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ DGifOpenFileName(const char *FileName, int *Error)
6262
}
6363

6464
GifFile = DGifOpenFileHandle(FileHandle, Error);
65-
// cppcheck-suppress resourceLeak
6665
return GifFile;
6766
}
6867

@@ -93,14 +92,17 @@ DGifOpenFileHandle(int FileHandle, int *Error)
9392
GifFile->SavedImages = NULL;
9493
GifFile->SColorMap = NULL;
9594

96-
Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
95+
Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
9796
if (Private == NULL) {
9897
if (Error != NULL)
9998
*Error = D_GIF_ERR_NOT_ENOUGH_MEM;
10099
(void)close(FileHandle);
101100
free((char *)GifFile);
102101
return NULL;
103102
}
103+
104+
/*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
105+
104106
#ifdef _WIN32
105107
_setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
106108
#endif /* _WIN32 */
@@ -117,6 +119,7 @@ DGifOpenFileHandle(int FileHandle, int *Error)
117119
/*@=mustfreeonly@*/
118120

119121
/* Let's see if this is a GIF file: */
122+
/* coverity[check_return] */
120123
if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
121124
if (Error != NULL)
122125
*Error = D_GIF_ERR_READ_FAILED;
@@ -175,13 +178,14 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
175178
GifFile->SavedImages = NULL;
176179
GifFile->SColorMap = NULL;
177180

178-
Private = (GifFilePrivateType *)malloc(sizeof(GifFilePrivateType));
181+
Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
179182
if (!Private) {
180183
if (Error != NULL)
181184
*Error = D_GIF_ERR_NOT_ENOUGH_MEM;
182185
free((char *)GifFile);
183186
return NULL;
184187
}
188+
/*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
185189

186190
GifFile->Private = (void *)Private;
187191
Private->FileHandle = 0;
@@ -192,6 +196,7 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
192196
GifFile->UserData = userData; /* TVT */
193197

194198
/* Lets see if this is a GIF file: */
199+
/* coverity[check_return] */
195200
if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
196201
if (Error != NULL)
197202
*Error = D_GIF_ERR_READ_FAILED;
@@ -213,6 +218,8 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
213218
if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
214219
free((char *)Private);
215220
free((char *)GifFile);
221+
if (Error != NULL)
222+
*Error = D_GIF_ERR_NO_SCRN_DSCR;
216223
return NULL;
217224
}
218225

@@ -270,6 +277,7 @@ DGifGetScreenDesc(GifFileType *GifFile)
270277
/* Get the global color map: */
271278
GifFile->SColorMap->SortFlag = SortFlag;
272279
for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
280+
/* coverity[check_return] */
273281
if (READ(GifFile, Buf, 3) != 3) {
274282
GifFreeMapObject(GifFile->SColorMap);
275283
GifFile->SColorMap = NULL;
@@ -302,6 +310,7 @@ DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
302310
return GIF_ERROR;
303311
}
304312

313+
/* coverity[check_return] */
305314
if (READ(GifFile, &Buf, 1) != 1) {
306315
GifFile->Error = D_GIF_ERR_READ_FAILED;
307316
return GIF_ERROR;
@@ -375,6 +384,7 @@ DGifGetImageDesc(GifFileType *GifFile)
375384

376385
/* Get the image local color map: */
377386
for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
387+
/* coverity[check_return] */
378388
if (READ(GifFile, Buf, 3) != 3) {
379389
GifFreeMapObject(GifFile->Image.ColorMap);
380390
GifFile->Error = D_GIF_ERR_READ_FAILED;
@@ -388,12 +398,14 @@ DGifGetImageDesc(GifFileType *GifFile)
388398
}
389399

390400
if (GifFile->SavedImages) {
391-
if ((GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
392-
sizeof(SavedImage) *
393-
(GifFile->ImageCount + 1))) == NULL) {
401+
SavedImage* new_saved_images =
402+
(SavedImage *)reallocarray(GifFile->SavedImages,
403+
(GifFile->ImageCount + 1), sizeof(SavedImage));
404+
if (new_saved_images == NULL) {
394405
GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
395406
return GIF_ERROR;
396407
}
408+
GifFile->SavedImages = new_saved_images;
397409
} else {
398410
if ((GifFile->SavedImages =
399411
(SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
@@ -423,9 +435,7 @@ DGifGetImageDesc(GifFileType *GifFile)
423435
(long)GifFile->Image.Height;
424436

425437
/* Reset decompress algorithm parameters. */
426-
(void)DGifSetupDecompress(GifFile);
427-
428-
return GIF_OK;
438+
return DGifSetupDecompress(GifFile);
429439
}
430440

431441
/******************************************************************************
@@ -524,6 +534,7 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
524534
return GIF_ERROR;
525535
}
526536

537+
/* coverity[check_return] */
527538
if (READ(GifFile, &Buf, 1) != 1) {
528539
GifFile->Error = D_GIF_ERR_READ_FAILED;
529540
return GIF_ERROR;
@@ -551,7 +562,7 @@ DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
551562
if (Buf > 0) {
552563
*Extension = Private->Buf; /* Use private unused buffer. */
553564
(*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
554-
/* coverity[tainted_data] */
565+
/* coverity[tainted_data,check_return] */
555566
if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
556567
GifFile->Error = D_GIF_ERR_READ_FAILED;
557568
return GIF_ERROR;
@@ -615,7 +626,7 @@ int DGifSavedExtensionToGCB(GifFileType *GifFile,
615626
This routine should be called last, to close the GIF file.
616627
******************************************************************************/
617628
int
618-
DGifCloseFile(GifFileType *GifFile)
629+
DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
619630
{
620631
GifFilePrivateType *Private;
621632

@@ -643,25 +654,25 @@ DGifCloseFile(GifFileType *GifFile)
643654

644655
if (!IS_READABLE(Private)) {
645656
/* This file was NOT open for reading: */
646-
GifFile->Error = D_GIF_ERR_NOT_READABLE;
657+
if (ErrorCode != NULL)
658+
*ErrorCode = D_GIF_ERR_NOT_READABLE;
659+
free((char *)GifFile->Private);
660+
free(GifFile);
647661
return GIF_ERROR;
648662
}
649663

650664
if (Private->File && (fclose(Private->File) != 0)) {
651-
GifFile->Error = D_GIF_ERR_CLOSE_FAILED;
665+
if (ErrorCode != NULL)
666+
*ErrorCode = D_GIF_ERR_CLOSE_FAILED;
667+
free((char *)GifFile->Private);
668+
free(GifFile);
652669
return GIF_ERROR;
653670
}
654671

655672
free((char *)GifFile->Private);
656-
657-
/*
658-
* Without the #ifndef, we get spurious warnings because Coverity mistakenly
659-
* thinks the GIF structure is freed on an error return.
660-
*/
661-
#ifndef __COVERITY__
662673
free(GifFile);
663-
#endif /* __COVERITY__ */
664-
674+
if (ErrorCode != NULL)
675+
*ErrorCode = D_GIF_SUCCEEDED;
665676
return GIF_OK;
666677
}
667678

@@ -673,6 +684,7 @@ DGifGetWord(GifFileType *GifFile, GifWord *Word)
673684
{
674685
unsigned char c[2];
675686

687+
/* coverity[check_return] */
676688
if (READ(GifFile, c, 2) != 2) {
677689
GifFile->Error = D_GIF_ERR_READ_FAILED;
678690
return GIF_ERROR;
@@ -717,6 +729,7 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
717729
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
718730

719731
/* coverity[tainted_data_argument] */
732+
/* coverity[check_return] */
720733
if (READ(GifFile, &Buf, 1) != 1) {
721734
GifFile->Error = D_GIF_ERR_READ_FAILED;
722735
return GIF_ERROR;
@@ -751,9 +764,18 @@ DGifSetupDecompress(GifFileType *GifFile)
751764
GifPrefixType *Prefix;
752765
GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
753766

754-
READ(GifFile, &CodeSize, 1); /* Read Code size from file. */
767+
/* coverity[check_return] */
768+
if (READ(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */
769+
return GIF_ERROR; /* Failed to read Code size. */
770+
}
755771
BitsPerPixel = CodeSize;
756772

773+
/* this can only happen on a severely malformed GIF */
774+
if (BitsPerPixel > 8) {
775+
GifFile->Error = D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
776+
return GIF_ERROR; /* Failed to read Code size. */
777+
}
778+
757779
Private->Buf[0] = 0; /* Input Buffer empty. */
758780
Private->BitsPerPixel = BitsPerPixel;
759781
Private->ClearCode = (1 << BitsPerPixel);
@@ -837,19 +859,22 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
837859
* pixels on our stack. If we done, pop the stack in reverse
838860
* (thats what stack is good for!) order to output. */
839861
if (Prefix[CrntCode] == NO_SUCH_CODE) {
862+
CrntPrefix = LastCode;
863+
840864
/* Only allowed if CrntCode is exactly the running code:
841865
* In that case CrntCode = XXXCode, CrntCode or the
842866
* prefix code is last code and the suffix char is
843867
* exactly the prefix of last code! */
844868
if (CrntCode == Private->RunningCode - 2) {
845-
CrntPrefix = LastCode;
846869
Suffix[Private->RunningCode - 2] =
847870
Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
848871
LastCode,
849872
ClearCode);
850873
} else {
851-
GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
852-
return GIF_ERROR;
874+
Suffix[Private->RunningCode - 2] =
875+
Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
876+
CrntCode,
877+
ClearCode);
853878
}
854879
} else
855880
CrntPrefix = CrntCode;
@@ -874,7 +899,7 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
874899
while (StackPtr != 0 && i < LineLen)
875900
Line[i++] = Stack[--StackPtr];
876901
}
877-
if (LastCode != NO_SUCH_CODE) {
902+
if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
878903
Prefix[Private->RunningCode - 2] = LastCode;
879904

880905
if (CrntCode == Private->RunningCode - 2) {
@@ -1021,6 +1046,7 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
10211046
{
10221047
if (Buf[0] == 0) {
10231048
/* Needs to read the next buffer - this one is empty: */
1049+
/* coverity[check_return] */
10241050
if (READ(GifFile, Buf, 1) != 1) {
10251051
GifFile->Error = D_GIF_ERR_READ_FAILED;
10261052
return GIF_ERROR;
@@ -1033,14 +1059,6 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
10331059
GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
10341060
return GIF_ERROR;
10351061
}
1036-
/* There shouldn't be any empty data blocks here as the LZW spec
1037-
* says the LZW termination code should come first. Therefore we
1038-
* shouldn't be inside this routine at that point.
1039-
*/
1040-
if (Buf[0] == 0) {
1041-
GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1042-
return GIF_ERROR;
1043-
}
10441062
if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
10451063
GifFile->Error = D_GIF_ERR_READ_FAILED;
10461064
return GIF_ERROR;
@@ -1093,7 +1111,7 @@ DGifSlurp(GifFileType *GifFile)
10931111
if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
10941112
return GIF_ERROR;
10951113
}
1096-
sp->RasterBits = (unsigned char *)malloc(ImageSize *
1114+
sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
10971115
sizeof(GifPixelType));
10981116

10991117
if (sp->RasterBits == NULL) {
@@ -1137,11 +1155,13 @@ DGifSlurp(GifFileType *GifFile)
11371155
if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
11381156
return (GIF_ERROR);
11391157
/* Create an extension block with our data */
1140-
if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1141-
&GifFile->ExtensionBlocks,
1142-
ExtFunction, ExtData[0], &ExtData[1])
1143-
== GIF_ERROR)
1144-
return (GIF_ERROR);
1158+
if (ExtData != NULL) {
1159+
if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1160+
&GifFile->ExtensionBlocks,
1161+
ExtFunction, ExtData[0], &ExtData[1])
1162+
== GIF_ERROR)
1163+
return (GIF_ERROR);
1164+
}
11451165
while (ExtData != NULL) {
11461166
if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
11471167
return (GIF_ERROR);
@@ -1163,6 +1183,12 @@ DGifSlurp(GifFileType *GifFile)
11631183
}
11641184
} while (RecordType != TERMINATE_RECORD_TYPE);
11651185

1186+
/* Sanity check for corrupted file */
1187+
if (GifFile->ImageCount == 0) {
1188+
GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1189+
return(GIF_ERROR);
1190+
}
1191+
11661192
return (GIF_OK);
11671193
}
11681194

0 commit comments

Comments
 (0)