blob: 66a1d6a4149f48c749dcfc9f46e52761e69cb412 [file] [log] [blame]
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001/******************************************************************************
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08002
Chris Craik9aef3ea2013-06-24 19:34:25 -07003dgif_lib.c - GIF decoding
4
5The functions here and in egif_lib.c are partitioned carefully so that
6if you only require one of read and write capability, only one of these
7two modules will be linked. Preserve this property!
8
9*****************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080010
11#include <stdlib.h>
Chris Craik9aef3ea2013-06-24 19:34:25 -070012#include <limits.h>
13#include <stdint.h>
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080014#include <fcntl.h>
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080015#include <unistd.h>
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080016#include <stdio.h>
17#include <string.h>
Chris Craik9aef3ea2013-06-24 19:34:25 -070018
19#ifdef _WIN32
20#include <io.h>
21#endif /* _WIN32 */
22
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080023#include "gif_lib.h"
24#include "gif_lib_private.h"
25
Chris Craik9aef3ea2013-06-24 19:34:25 -070026/* compose unsigned little endian value */
27#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080028
29/* avoid extra function call in case we use fread (TVT) */
30#define READ(_gif,_buf,_len) \
31 (((GifFilePrivateType*)_gif->Private)->Read ? \
32 ((GifFilePrivateType*)_gif->Private)->Read(_gif,_buf,_len) : \
33 fread(_buf,1,_len,((GifFilePrivateType*)_gif->Private)->File))
34
35static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
36static int DGifSetupDecompress(GifFileType *GifFile);
37static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
38 int LineLen);
39static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
40static int DGifDecompressInput(GifFileType *GifFile, int *Code);
41static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
42 GifByteType *NextByte);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080043
44/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -070045 Open a new GIF file for read, given by its name.
46 Returns dynamically allocated GifFileType pointer which serves as the GIF
47 info record.
48******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080049GifFileType *
Chris Craik9aef3ea2013-06-24 19:34:25 -070050DGifOpenFileName(const char *FileName, int *Error)
51{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080052 int FileHandle;
53 GifFileType *GifFile;
54
Chris Craik9aef3ea2013-06-24 19:34:25 -070055 if ((FileHandle = open(FileName, O_RDONLY)) == -1) {
56 if (Error != NULL)
57 *Error = D_GIF_ERR_OPEN_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080058 return NULL;
59 }
60
Chris Craik9aef3ea2013-06-24 19:34:25 -070061 GifFile = DGifOpenFileHandle(FileHandle, Error);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080062 return GifFile;
63}
64
65/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -070066 Update a new GIF file, given its file handle.
67 Returns dynamically allocated GifFileType pointer which serves as the GIF
68 info record.
69******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080070GifFileType *
Chris Craik9aef3ea2013-06-24 19:34:25 -070071DGifOpenFileHandle(int FileHandle, int *Error)
72{
73 char Buf[GIF_STAMP_LEN + 1];
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080074 GifFileType *GifFile;
75 GifFilePrivateType *Private;
76 FILE *f;
77
78 GifFile = (GifFileType *)malloc(sizeof(GifFileType));
79 if (GifFile == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -070080 if (Error != NULL)
81 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
82 (void)close(FileHandle);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080083 return NULL;
84 }
85
Chris Craik9aef3ea2013-06-24 19:34:25 -070086 /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType));
87
88 /* Belt and suspenders, in case the null pointer isn't zero */
89 GifFile->SavedImages = NULL;
90 GifFile->SColorMap = NULL;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080091
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -040092 Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080093 if (Private == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -070094 if (Error != NULL)
95 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
96 (void)close(FileHandle);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -080097 free((char *)GifFile);
98 return NULL;
99 }
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400100
101 /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
102
Chris Craik9aef3ea2013-06-24 19:34:25 -0700103#ifdef _WIN32
104 _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
105#endif /* _WIN32 */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800106
107 f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
108
Chris Craik9aef3ea2013-06-24 19:34:25 -0700109 /*@-mustfreeonly@*/
110 GifFile->Private = (void *)Private;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800111 Private->FileHandle = FileHandle;
112 Private->File = f;
113 Private->FileState = FILE_STATE_READ;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700114 Private->Read = NULL; /* don't use alternate input method (TVT) */
115 GifFile->UserData = NULL; /* TVT */
116 /*@=mustfreeonly@*/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800117
Chris Craik9aef3ea2013-06-24 19:34:25 -0700118 /* Let's see if this is a GIF file: */
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400119 /* coverity[check_return] */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700120 if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
121 if (Error != NULL)
122 *Error = D_GIF_ERR_READ_FAILED;
123 (void)fclose(f);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800124 free((char *)Private);
125 free((char *)GifFile);
126 return NULL;
127 }
128
Chris Craik9aef3ea2013-06-24 19:34:25 -0700129 /* Check for GIF prefix at start of file */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800130 Buf[GIF_STAMP_LEN] = 0;
131 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700132 if (Error != NULL)
133 *Error = D_GIF_ERR_NOT_GIF_FILE;
134 (void)fclose(f);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800135 free((char *)Private);
136 free((char *)GifFile);
137 return NULL;
138 }
139
140 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700141 (void)fclose(f);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800142 free((char *)Private);
143 free((char *)GifFile);
144 return NULL;
145 }
146
Chris Craik9aef3ea2013-06-24 19:34:25 -0700147 GifFile->Error = 0;
148
149 /* What version of GIF? */
150 Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800151
152 return GifFile;
153}
154
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800155/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700156 GifFileType constructor with user supplied input function (TVT)
157******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800158GifFileType *
Chris Craik9aef3ea2013-06-24 19:34:25 -0700159DGifOpen(void *userData, InputFunc readFunc, int *Error)
160{
161 char Buf[GIF_STAMP_LEN + 1];
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800162 GifFileType *GifFile;
163 GifFilePrivateType *Private;
164
165 GifFile = (GifFileType *)malloc(sizeof(GifFileType));
166 if (GifFile == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700167 if (Error != NULL)
168 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800169 return NULL;
170 }
171
172 memset(GifFile, '\0', sizeof(GifFileType));
173
Chris Craik9aef3ea2013-06-24 19:34:25 -0700174 /* Belt and suspenders, in case the null pointer isn't zero */
175 GifFile->SavedImages = NULL;
176 GifFile->SColorMap = NULL;
177
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400178 Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800179 if (!Private) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700180 if (Error != NULL)
181 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800182 free((char *)GifFile);
183 return NULL;
184 }
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400185 /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800186
Chris Craik9aef3ea2013-06-24 19:34:25 -0700187 GifFile->Private = (void *)Private;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800188 Private->FileHandle = 0;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700189 Private->File = NULL;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800190 Private->FileState = FILE_STATE_READ;
191
192 Private->Read = readFunc; /* TVT */
193 GifFile->UserData = userData; /* TVT */
194
195 /* Lets see if this is a GIF file: */
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400196 /* coverity[check_return] */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700197 if (READ(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
198 if (Error != NULL)
199 *Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800200 free((char *)Private);
201 free((char *)GifFile);
202 return NULL;
203 }
204
Chris Craik9aef3ea2013-06-24 19:34:25 -0700205 /* Check for GIF prefix at start of file */
206 Buf[GIF_STAMP_LEN] = '\0';
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800207 if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700208 if (Error != NULL)
209 *Error = D_GIF_ERR_NOT_GIF_FILE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800210 free((char *)Private);
211 free((char *)GifFile);
212 return NULL;
213 }
214
215 if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
216 free((char *)Private);
217 free((char *)GifFile);
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400218 if (Error != NULL)
219 *Error = D_GIF_ERR_NO_SCRN_DSCR;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800220 return NULL;
221 }
222
Chris Craik9aef3ea2013-06-24 19:34:25 -0700223 GifFile->Error = 0;
224
225 /* What version of GIF? */
226 Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800227
228 return GifFile;
229}
230
231/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700232 This routine should be called before any other DGif calls. Note that
233 this routine is called automatically from DGif file open routines.
234******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800235int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700236DGifGetScreenDesc(GifFileType *GifFile)
237{
238 int BitsPerPixel;
239 bool SortFlag;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800240 GifByteType Buf[3];
241 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
242
243 if (!IS_READABLE(Private)) {
244 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700245 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800246 return GIF_ERROR;
247 }
248
249 /* Put the screen descriptor into the file: */
250 if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
251 DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
252 return GIF_ERROR;
253
254 if (READ(GifFile, Buf, 3) != 3) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700255 GifFile->Error = D_GIF_ERR_READ_FAILED;
256 GifFreeMapObject(GifFile->SColorMap);
257 GifFile->SColorMap = NULL;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800258 return GIF_ERROR;
259 }
260 GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700261 SortFlag = (Buf[0] & 0x08) != 0;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800262 BitsPerPixel = (Buf[0] & 0x07) + 1;
263 GifFile->SBackGroundColor = Buf[1];
Chris Craik9aef3ea2013-06-24 19:34:25 -0700264 GifFile->AspectByte = Buf[2];
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800265 if (Buf[0] & 0x80) { /* Do we have global color map? */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700266 int i;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800267
Chris Craik9aef3ea2013-06-24 19:34:25 -0700268 GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800269 if (GifFile->SColorMap == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700270 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800271 return GIF_ERROR;
272 }
273
274 /* Get the global color map: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700275 GifFile->SColorMap->SortFlag = SortFlag;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800276 for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400277 /* coverity[check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800278 if (READ(GifFile, Buf, 3) != 3) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700279 GifFreeMapObject(GifFile->SColorMap);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800280 GifFile->SColorMap = NULL;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700281 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800282 return GIF_ERROR;
283 }
284 GifFile->SColorMap->Colors[i].Red = Buf[0];
285 GifFile->SColorMap->Colors[i].Green = Buf[1];
286 GifFile->SColorMap->Colors[i].Blue = Buf[2];
287 }
288 } else {
289 GifFile->SColorMap = NULL;
290 }
291
292 return GIF_OK;
293}
294
295/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700296 This routine should be called before any attempt to read an image.
297******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800298int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700299DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
300{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800301 GifByteType Buf;
302 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
303
304 if (!IS_READABLE(Private)) {
305 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700306 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800307 return GIF_ERROR;
308 }
309
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400310 /* coverity[check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800311 if (READ(GifFile, &Buf, 1) != 1) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700312 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800313 return GIF_ERROR;
314 }
315
316 switch (Buf) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700317 case DESCRIPTOR_INTRODUCER:
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800318 *Type = IMAGE_DESC_RECORD_TYPE;
319 break;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700320 case EXTENSION_INTRODUCER:
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800321 *Type = EXTENSION_RECORD_TYPE;
322 break;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700323 case TERMINATOR_INTRODUCER:
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800324 *Type = TERMINATE_RECORD_TYPE;
325 break;
326 default:
327 *Type = UNDEFINED_RECORD_TYPE;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700328 GifFile->Error = D_GIF_ERR_WRONG_RECORD;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800329 return GIF_ERROR;
330 }
331
332 return GIF_OK;
333}
334
335/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700336 This routine should be called before any attempt to read an image.
337 Note it is assumed the Image desc. header has been read.
338******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800339int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700340DGifGetImageDesc(GifFileType *GifFile)
341{
342 unsigned int BitsPerPixel;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800343 GifByteType Buf[3];
344 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
345 SavedImage *sp;
346
347 if (!IS_READABLE(Private)) {
348 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700349 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800350 return GIF_ERROR;
351 }
352
353 if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
354 DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
355 DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
356 DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
357 return GIF_ERROR;
358 if (READ(GifFile, Buf, 1) != 1) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700359 GifFile->Error = D_GIF_ERR_READ_FAILED;
360 GifFreeMapObject(GifFile->Image.ColorMap);
361 GifFile->Image.ColorMap = NULL;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800362 return GIF_ERROR;
363 }
364 BitsPerPixel = (Buf[0] & 0x07) + 1;
Chris Craik9aef3ea2013-06-24 19:34:25 -0700365 GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800366
Chris Craik9aef3ea2013-06-24 19:34:25 -0700367 /* Setup the colormap */
368 if (GifFile->Image.ColorMap) {
369 GifFreeMapObject(GifFile->Image.ColorMap);
370 GifFile->Image.ColorMap = NULL;
371 }
372 /* Does this image have local color map? */
373 if (Buf[0] & 0x80) {
374 unsigned int i;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800375
Chris Craik9aef3ea2013-06-24 19:34:25 -0700376 GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800377 if (GifFile->Image.ColorMap == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700378 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800379 return GIF_ERROR;
380 }
381
382 /* Get the image local color map: */
383 for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400384 /* coverity[check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800385 if (READ(GifFile, Buf, 3) != 3) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700386 GifFreeMapObject(GifFile->Image.ColorMap);
387 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800388 GifFile->Image.ColorMap = NULL;
389 return GIF_ERROR;
390 }
391 GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
392 GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
393 GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
394 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800395 }
396
397 if (GifFile->SavedImages) {
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400398 SavedImage* new_saved_images =
399 (SavedImage *)reallocarray(GifFile->SavedImages,
400 (GifFile->ImageCount + 1), sizeof(SavedImage));
401 if (new_saved_images == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700402 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800403 return GIF_ERROR;
404 }
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400405 GifFile->SavedImages = new_saved_images;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800406 } else {
407 if ((GifFile->SavedImages =
408 (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700409 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800410 return GIF_ERROR;
411 }
412 }
413
414 sp = &GifFile->SavedImages[GifFile->ImageCount];
415 memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
416 if (GifFile->Image.ColorMap != NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700417 sp->ImageDesc.ColorMap = GifMakeMapObject(
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800418 GifFile->Image.ColorMap->ColorCount,
419 GifFile->Image.ColorMap->Colors);
420 if (sp->ImageDesc.ColorMap == NULL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700421 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800422 return GIF_ERROR;
423 }
424 }
425 sp->RasterBits = (unsigned char *)NULL;
426 sp->ExtensionBlockCount = 0;
427 sp->ExtensionBlocks = (ExtensionBlock *) NULL;
428
429 GifFile->ImageCount++;
430
431 Private->PixelCount = (long)GifFile->Image.Width *
432 (long)GifFile->Image.Height;
433
Chris Craik9aef3ea2013-06-24 19:34:25 -0700434 /* Reset decompress algorithm parameters. */
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400435 return DGifSetupDecompress(GifFile);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800436}
437
438/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700439 Get one full scanned line (Line) of length LineLen from GIF file.
440******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800441int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700442DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
443{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800444 GifByteType *Dummy;
445 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
446
447 if (!IS_READABLE(Private)) {
448 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700449 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800450 return GIF_ERROR;
451 }
452
453 if (!LineLen)
454 LineLen = GifFile->Image.Width;
455
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800456 if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700457 GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800458 return GIF_ERROR;
459 }
460
461 if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
462 if (Private->PixelCount == 0) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700463 /* We probably won't be called any more, so let's clean up
464 * everything before we return: need to flush out all the
465 * rest of image until an empty block (size 0)
466 * detected. We use GetCodeNext.
467 */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800468 do
469 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
470 return GIF_ERROR;
471 while (Dummy != NULL) ;
472 }
473 return GIF_OK;
474 } else
475 return GIF_ERROR;
476}
477
478/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700479 Put one pixel (Pixel) into GIF file.
480******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800481int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700482DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
483{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800484 GifByteType *Dummy;
485 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
486
487 if (!IS_READABLE(Private)) {
488 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700489 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800490 return GIF_ERROR;
491 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800492 if (--Private->PixelCount > 0xffff0000UL)
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800493 {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700494 GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800495 return GIF_ERROR;
496 }
497
498 if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
499 if (Private->PixelCount == 0) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700500 /* We probably won't be called any more, so let's clean up
501 * everything before we return: need to flush out all the
502 * rest of image until an empty block (size 0)
503 * detected. We use GetCodeNext.
504 */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800505 do
506 if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
507 return GIF_ERROR;
508 while (Dummy != NULL) ;
509 }
510 return GIF_OK;
511 } else
512 return GIF_ERROR;
513}
514
515/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700516 Get an extension block (see GIF manual) from GIF file. This routine only
517 returns the first data block, and DGifGetExtensionNext should be called
518 after this one until NULL extension is returned.
519 The Extension should NOT be freed by the user (not dynamically allocated).
520 Note it is assumed the Extension description header has been read.
521******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800522int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700523DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
524{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800525 GifByteType Buf;
526 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
527
528 if (!IS_READABLE(Private)) {
529 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700530 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800531 return GIF_ERROR;
532 }
533
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400534 /* coverity[check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800535 if (READ(GifFile, &Buf, 1) != 1) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700536 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800537 return GIF_ERROR;
538 }
539 *ExtCode = Buf;
540
541 return DGifGetExtensionNext(GifFile, Extension);
542}
543
544/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700545 Get a following extension block (see GIF manual) from GIF file. This
546 routine should be called until NULL Extension is returned.
547 The Extension should NOT be freed by the user (not dynamically allocated).
548******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800549int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700550DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
551{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800552 GifByteType Buf;
553 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
554
555 if (READ(GifFile, &Buf, 1) != 1) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700556 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800557 return GIF_ERROR;
558 }
559 if (Buf > 0) {
560 *Extension = Private->Buf; /* Use private unused buffer. */
561 (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400562 /* coverity[tainted_data,check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800563 if (READ(GifFile, &((*Extension)[1]), Buf) != Buf) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700564 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800565 return GIF_ERROR;
566 }
567 } else
568 *Extension = NULL;
569
570 return GIF_OK;
571}
572
573/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700574 Extract a Graphics Control Block from raw extension data
575******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800576
Chris Craik9aef3ea2013-06-24 19:34:25 -0700577int DGifExtensionToGCB(const size_t GifExtensionLength,
578 const GifByteType *GifExtension,
579 GraphicsControlBlock *GCB)
580{
581 if (GifExtensionLength != 4) {
582 return GIF_ERROR;
583 }
584
585 GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
586 GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
587 GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
588 if (GifExtension[0] & 0x01)
589 GCB->TransparentColor = (int)GifExtension[3];
590 else
591 GCB->TransparentColor = NO_TRANSPARENT_COLOR;
592
593 return GIF_OK;
594}
595
596/******************************************************************************
597 Extract the Graphics Control Block for a saved image, if it exists.
598******************************************************************************/
599
600int DGifSavedExtensionToGCB(GifFileType *GifFile,
601 int ImageIndex, GraphicsControlBlock *GCB)
602{
603 int i;
604
605 if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
606 return GIF_ERROR;
607
608 GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
609 GCB->UserInputFlag = false;
610 GCB->DelayTime = 0;
611 GCB->TransparentColor = NO_TRANSPARENT_COLOR;
612
613 for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
614 ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
615 if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
616 return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
617 }
618
619 return GIF_ERROR;
620}
621
622/******************************************************************************
623 This routine should be called last, to close the GIF file.
624******************************************************************************/
625int
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400626DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
Chris Craik9aef3ea2013-06-24 19:34:25 -0700627{
628 GifFilePrivateType *Private;
629
630 if (GifFile == NULL || GifFile->Private == NULL)
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800631 return GIF_ERROR;
632
Chris Craik9aef3ea2013-06-24 19:34:25 -0700633 if (GifFile->Image.ColorMap) {
634 GifFreeMapObject(GifFile->Image.ColorMap);
635 GifFile->Image.ColorMap = NULL;
636 }
637
638 if (GifFile->SColorMap) {
639 GifFreeMapObject(GifFile->SColorMap);
640 GifFile->SColorMap = NULL;
641 }
642
643 if (GifFile->SavedImages) {
644 GifFreeSavedImages(GifFile);
645 GifFile->SavedImages = NULL;
646 }
647
648 GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
649
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800650 Private = (GifFilePrivateType *) GifFile->Private;
651
652 if (!IS_READABLE(Private)) {
653 /* This file was NOT open for reading: */
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400654 if (ErrorCode != NULL)
655 *ErrorCode = D_GIF_ERR_NOT_READABLE;
656 free((char *)GifFile->Private);
657 free(GifFile);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800658 return GIF_ERROR;
659 }
660
Chris Craik9aef3ea2013-06-24 19:34:25 -0700661 if (Private->File && (fclose(Private->File) != 0)) {
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400662 if (ErrorCode != NULL)
663 *ErrorCode = D_GIF_ERR_CLOSE_FAILED;
664 free((char *)GifFile->Private);
665 free(GifFile);
Chris Craik9aef3ea2013-06-24 19:34:25 -0700666 return GIF_ERROR;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800667 }
668
Chris Craik9aef3ea2013-06-24 19:34:25 -0700669 free((char *)GifFile->Private);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800670 free(GifFile);
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400671 if (ErrorCode != NULL)
672 *ErrorCode = D_GIF_SUCCEEDED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800673 return GIF_OK;
674}
675
676/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700677 Get 2 bytes (word) from the given file:
678******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800679static int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700680DGifGetWord(GifFileType *GifFile, GifWord *Word)
681{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800682 unsigned char c[2];
683
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400684 /* coverity[check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800685 if (READ(GifFile, c, 2) != 2) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700686 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800687 return GIF_ERROR;
688 }
689
Chris Craik9aef3ea2013-06-24 19:34:25 -0700690 *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800691 return GIF_OK;
692}
693
694/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700695 Get the image code in compressed form. This routine can be called if the
696 information needed to be piped out as is. Obviously this is much faster
697 than decoding and encoding again. This routine should be followed by calls
698 to DGifGetCodeNext, until NULL block is returned.
699 The block should NOT be freed by the user (not dynamically allocated).
700******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800701int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700702DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
703{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800704 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
705
706 if (!IS_READABLE(Private)) {
707 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700708 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800709 return GIF_ERROR;
710 }
711
712 *CodeSize = Private->BitsPerPixel;
713
714 return DGifGetCodeNext(GifFile, CodeBlock);
715}
716
717/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700718 Continue to get the image code in compressed form. This routine should be
719 called until NULL block is returned.
720 The block should NOT be freed by the user (not dynamically allocated).
721******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800722int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700723DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
724{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800725 GifByteType Buf;
726 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
727
Chris Craik9aef3ea2013-06-24 19:34:25 -0700728 /* coverity[tainted_data_argument] */
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400729 /* coverity[check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800730 if (READ(GifFile, &Buf, 1) != 1) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700731 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800732 return GIF_ERROR;
733 }
734
Chris Craik9aef3ea2013-06-24 19:34:25 -0700735 /* coverity[lower_bounds] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800736 if (Buf > 0) {
737 *CodeBlock = Private->Buf; /* Use private unused buffer. */
738 (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700739 /* coverity[tainted_data] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800740 if (READ(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700741 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800742 return GIF_ERROR;
743 }
744 } else {
745 *CodeBlock = NULL;
746 Private->Buf[0] = 0; /* Make sure the buffer is empty! */
747 Private->PixelCount = 0; /* And local info. indicate image read. */
748 }
749
750 return GIF_OK;
751}
752
753/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700754 Setup the LZ decompression for this image:
755******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800756static int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700757DGifSetupDecompress(GifFileType *GifFile)
758{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800759 int i, BitsPerPixel;
760 GifByteType CodeSize;
761 GifPrefixType *Prefix;
762 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
763
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400764 /* coverity[check_return] */
765 if (READ(GifFile, &CodeSize, 1) < 1) { /* Read Code size from file. */
766 return GIF_ERROR; /* Failed to read Code size. */
767 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800768 BitsPerPixel = CodeSize;
769
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400770 /* this can only happen on a severely malformed GIF */
771 if (BitsPerPixel > 8) {
772 GifFile->Error = D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
773 return GIF_ERROR; /* Failed to read Code size. */
774 }
775
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800776 Private->Buf[0] = 0; /* Input Buffer empty. */
777 Private->BitsPerPixel = BitsPerPixel;
778 Private->ClearCode = (1 << BitsPerPixel);
779 Private->EOFCode = Private->ClearCode + 1;
780 Private->RunningCode = Private->EOFCode + 1;
781 Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
782 Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
783 Private->StackPtr = 0; /* No pixels on the pixel stack. */
784 Private->LastCode = NO_SUCH_CODE;
785 Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
786 Private->CrntShiftDWord = 0;
787
788 Prefix = Private->Prefix;
789 for (i = 0; i <= LZ_MAX_CODE; i++)
790 Prefix[i] = NO_SUCH_CODE;
791
792 return GIF_OK;
793}
794
795/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700796 The LZ decompression routine:
797 This version decompress the given GIF file into Line of length LineLen.
798 This routine can be called few times (one per scan line, for example), in
799 order the complete the whole image.
800******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800801static int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700802DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
803{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800804 int i = 0;
805 int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
806 GifByteType *Stack, *Suffix;
807 GifPrefixType *Prefix;
808 GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
809
810 StackPtr = Private->StackPtr;
811 Prefix = Private->Prefix;
812 Suffix = Private->Suffix;
813 Stack = Private->Stack;
814 EOFCode = Private->EOFCode;
815 ClearCode = Private->ClearCode;
816 LastCode = Private->LastCode;
817
818 if (StackPtr > LZ_MAX_CODE) {
819 return GIF_ERROR;
820 }
821
822 if (StackPtr != 0) {
Chris Craik9aef3ea2013-06-24 19:34:25 -0700823 /* Let pop the stack off before continueing to read the GIF file: */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800824 while (StackPtr != 0 && i < LineLen)
825 Line[i++] = Stack[--StackPtr];
826 }
827
828 while (i < LineLen) { /* Decode LineLen items. */
829 if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
830 return GIF_ERROR;
831
832 if (CrntCode == EOFCode) {
833 /* Note however that usually we will not be here as we will stop
834 * decoding as soon as we got all the pixel, or EOF code will
835 * not be read at all, and DGifGetLine/Pixel clean everything. */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700836 GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
837 return GIF_ERROR;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800838 } else if (CrntCode == ClearCode) {
839 /* We need to start over again: */
840 for (j = 0; j <= LZ_MAX_CODE; j++)
841 Prefix[j] = NO_SUCH_CODE;
842 Private->RunningCode = Private->EOFCode + 1;
843 Private->RunningBits = Private->BitsPerPixel + 1;
844 Private->MaxCode1 = 1 << Private->RunningBits;
845 LastCode = Private->LastCode = NO_SUCH_CODE;
846 } else {
847 /* Its regular code - if in pixel range simply add it to output
848 * stream, otherwise trace to codes linked list until the prefix
849 * is in pixel range: */
850 if (CrntCode < ClearCode) {
851 /* This is simple - its pixel scalar, so add it to output: */
852 Line[i++] = CrntCode;
853 } else {
854 /* Its a code to needed to be traced: trace the linked list
855 * until the prefix is a pixel, while pushing the suffix
856 * pixels on our stack. If we done, pop the stack in reverse
857 * (thats what stack is good for!) order to output. */
858 if (Prefix[CrntCode] == NO_SUCH_CODE) {
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400859 CrntPrefix = LastCode;
860
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800861 /* Only allowed if CrntCode is exactly the running code:
862 * In that case CrntCode = XXXCode, CrntCode or the
863 * prefix code is last code and the suffix char is
864 * exactly the prefix of last code! */
865 if (CrntCode == Private->RunningCode - 2) {
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800866 Suffix[Private->RunningCode - 2] =
867 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
868 LastCode,
869 ClearCode);
870 } else {
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -0400871 Suffix[Private->RunningCode - 2] =
872 Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
873 CrntCode,
874 ClearCode);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800875 }
876 } else
877 CrntPrefix = CrntCode;
878
Chris Craik9aef3ea2013-06-24 19:34:25 -0700879 /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
880 * during the trace. As we might loop forever, in case of
881 * defective image, we use StackPtr as loop counter and stop
882 * before overflowing Stack[]. */
883 while (StackPtr < LZ_MAX_CODE &&
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800884 CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
885 Stack[StackPtr++] = Suffix[CrntPrefix];
886 CrntPrefix = Prefix[CrntPrefix];
887 }
Chris Craik9aef3ea2013-06-24 19:34:25 -0700888 if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
889 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800890 return GIF_ERROR;
891 }
892 /* Push the last character on stack: */
893 Stack[StackPtr++] = CrntPrefix;
894
895 /* Now lets pop all the stack into output: */
896 while (StackPtr != 0 && i < LineLen)
897 Line[i++] = Stack[--StackPtr];
898 }
Chris Craik9aef3ea2013-06-24 19:34:25 -0700899 if (LastCode != NO_SUCH_CODE && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800900 Prefix[Private->RunningCode - 2] = LastCode;
901
902 if (CrntCode == Private->RunningCode - 2) {
903 /* Only allowed if CrntCode is exactly the running code:
904 * In that case CrntCode = XXXCode, CrntCode or the
905 * prefix code is last code and the suffix char is
906 * exactly the prefix of last code! */
907 Suffix[Private->RunningCode - 2] =
908 DGifGetPrefixChar(Prefix, LastCode, ClearCode);
909 } else {
910 Suffix[Private->RunningCode - 2] =
911 DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
912 }
913 }
914 LastCode = CrntCode;
915 }
916 }
917
918 Private->LastCode = LastCode;
919 Private->StackPtr = StackPtr;
920
921 return GIF_OK;
922}
923
924/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700925 Routine to trace the Prefixes linked list until we get a prefix which is
926 not code, but a pixel value (less than ClearCode). Returns that pixel value.
927 If image is defective, we might loop here forever, so we limit the loops to
928 the maximum possible if image O.k. - LZ_MAX_CODE times.
929******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800930static int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700931DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
932{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800933 int i = 0;
934
935 while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
936 if (Code > LZ_MAX_CODE) {
937 return NO_SUCH_CODE;
938 }
939 Code = Prefix[Code];
940 }
941 return Code;
942}
943
944/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700945 Interface for accessing the LZ codes directly. Set Code to the real code
946 (12bits), or to -1 if EOF code is returned.
947******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800948int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700949DGifGetLZCodes(GifFileType *GifFile, int *Code)
950{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800951 GifByteType *CodeBlock;
952 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
953
954 if (!IS_READABLE(Private)) {
955 /* This file was NOT open for reading: */
Chris Craik9aef3ea2013-06-24 19:34:25 -0700956 GifFile->Error = D_GIF_ERR_NOT_READABLE;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800957 return GIF_ERROR;
958 }
959
960 if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
961 return GIF_ERROR;
962
963 if (*Code == Private->EOFCode) {
964 /* Skip rest of codes (hopefully only NULL terminating block): */
965 do {
966 if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
967 return GIF_ERROR;
968 } while (CodeBlock != NULL) ;
969
970 *Code = -1;
971 } else if (*Code == Private->ClearCode) {
972 /* We need to start over again: */
973 Private->RunningCode = Private->EOFCode + 1;
974 Private->RunningBits = Private->BitsPerPixel + 1;
975 Private->MaxCode1 = 1 << Private->RunningBits;
976 }
977
978 return GIF_OK;
979}
980
981/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -0700982 The LZ decompression input routine:
983 This routine is responsable for the decompression of the bit stream from
984 8 bits (bytes) packets, into the real codes.
985 Returns GIF_OK if read successfully.
986******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800987static int
Chris Craik9aef3ea2013-06-24 19:34:25 -0700988DGifDecompressInput(GifFileType *GifFile, int *Code)
989{
990 static const unsigned short CodeMasks[] = {
991 0x0000, 0x0001, 0x0003, 0x0007,
992 0x000f, 0x001f, 0x003f, 0x007f,
993 0x00ff, 0x01ff, 0x03ff, 0x07ff,
994 0x0fff
995 };
996
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -0800997 GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
998
999 GifByteType NextByte;
Chris Craik9aef3ea2013-06-24 19:34:25 -07001000
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001001 /* The image can't contain more than LZ_BITS per code. */
1002 if (Private->RunningBits > LZ_BITS) {
Chris Craik9aef3ea2013-06-24 19:34:25 -07001003 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001004 return GIF_ERROR;
1005 }
1006
1007 while (Private->CrntShiftState < Private->RunningBits) {
1008 /* Needs to get more bytes from input stream for next code: */
1009 if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
1010 return GIF_ERROR;
1011 }
1012 Private->CrntShiftDWord |=
Chris Craik9aef3ea2013-06-24 19:34:25 -07001013 ((unsigned long)NextByte) << Private->CrntShiftState;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001014 Private->CrntShiftState += 8;
1015 }
1016 *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1017
1018 Private->CrntShiftDWord >>= Private->RunningBits;
1019 Private->CrntShiftState -= Private->RunningBits;
1020
1021 /* If code cannot fit into RunningBits bits, must raise its size. Note
1022 * however that codes above 4095 are used for special signaling.
1023 * If we're using LZ_BITS bits already and we're at the max code, just
1024 * keep using the table as it is, don't increment Private->RunningCode.
1025 */
1026 if (Private->RunningCode < LZ_MAX_CODE + 2 &&
Chris Craik9aef3ea2013-06-24 19:34:25 -07001027 ++Private->RunningCode > Private->MaxCode1 &&
1028 Private->RunningBits < LZ_BITS) {
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001029 Private->MaxCode1 <<= 1;
1030 Private->RunningBits++;
1031 }
1032 return GIF_OK;
1033}
1034
1035/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -07001036 This routines read one GIF data block at a time and buffers it internally
1037 so that the decompression routine could access it.
1038 The routine returns the next byte from its internal buffer (or read next
1039 block in if buffer empty) and returns GIF_OK if succesful.
1040******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001041static int
Chris Craik9aef3ea2013-06-24 19:34:25 -07001042DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
1043{
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001044 if (Buf[0] == 0) {
1045 /* Needs to read the next buffer - this one is empty: */
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -04001046 /* coverity[check_return] */
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001047 if (READ(GifFile, Buf, 1) != 1) {
Chris Craik9aef3ea2013-06-24 19:34:25 -07001048 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001049 return GIF_ERROR;
1050 }
1051 /* There shouldn't be any empty data blocks here as the LZW spec
1052 * says the LZW termination code should come first. Therefore we
1053 * shouldn't be inside this routine at that point.
1054 */
1055 if (Buf[0] == 0) {
Chris Craik9aef3ea2013-06-24 19:34:25 -07001056 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1057 return GIF_ERROR;
1058 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001059 if (READ(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
Chris Craik9aef3ea2013-06-24 19:34:25 -07001060 GifFile->Error = D_GIF_ERR_READ_FAILED;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001061 return GIF_ERROR;
1062 }
1063 *NextByte = Buf[1];
1064 Buf[1] = 2; /* We use now the second place as last char read! */
1065 Buf[0]--;
1066 } else {
1067 *NextByte = Buf[Buf[1]++];
1068 Buf[0]--;
1069 }
1070
1071 return GIF_OK;
1072}
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001073
1074/******************************************************************************
Chris Craik9aef3ea2013-06-24 19:34:25 -07001075 This routine reads an entire GIF into core, hanging all its state info off
1076 the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle()
1077 first to initialize I/O. Its inverse is EGifSpew().
1078*******************************************************************************/
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001079int
Chris Craik9aef3ea2013-06-24 19:34:25 -07001080DGifSlurp(GifFileType *GifFile)
1081{
1082 size_t ImageSize;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001083 GifRecordType RecordType;
1084 SavedImage *sp;
1085 GifByteType *ExtData;
Chris Craik9aef3ea2013-06-24 19:34:25 -07001086 int ExtFunction;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001087
Chris Craik9aef3ea2013-06-24 19:34:25 -07001088 GifFile->ExtensionBlocks = NULL;
1089 GifFile->ExtensionBlockCount = 0;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001090
1091 do {
1092 if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1093 return (GIF_ERROR);
1094
1095 switch (RecordType) {
1096 case IMAGE_DESC_RECORD_TYPE:
1097 if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1098 return (GIF_ERROR);
1099
1100 sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
Chris Craik9aef3ea2013-06-24 19:34:25 -07001101 /* Allocate memory for the image */
1102 if (sp->ImageDesc.Width < 0 && sp->ImageDesc.Height < 0 &&
1103 sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
1104 return GIF_ERROR;
1105 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001106 ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1107
Chris Craik9aef3ea2013-06-24 19:34:25 -07001108 if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1109 return GIF_ERROR;
1110 }
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -04001111 sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
Chris Craik9aef3ea2013-06-24 19:34:25 -07001112 sizeof(GifPixelType));
1113
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001114 if (sp->RasterBits == NULL) {
1115 return GIF_ERROR;
1116 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001117
Chris Craik9aef3ea2013-06-24 19:34:25 -07001118 if (sp->ImageDesc.Interlace) {
1119 int i, j;
1120 /*
1121 * The way an interlaced image should be read -
1122 * offsets and jumps...
1123 */
1124 int InterlacedOffset[] = { 0, 4, 2, 1 };
1125 int InterlacedJumps[] = { 8, 8, 4, 2 };
1126 /* Need to perform 4 passes on the image */
1127 for (i = 0; i < 4; i++)
1128 for (j = InterlacedOffset[i];
1129 j < sp->ImageDesc.Height;
1130 j += InterlacedJumps[i]) {
1131 if (DGifGetLine(GifFile,
1132 sp->RasterBits+j*sp->ImageDesc.Width,
1133 sp->ImageDesc.Width) == GIF_ERROR)
1134 return GIF_ERROR;
1135 }
1136 }
1137 else {
1138 if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
1139 return (GIF_ERROR);
1140 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001141
Chris Craik9aef3ea2013-06-24 19:34:25 -07001142 if (GifFile->ExtensionBlocks) {
1143 sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1144 sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
1145
1146 GifFile->ExtensionBlocks = NULL;
1147 GifFile->ExtensionBlockCount = 0;
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001148 }
1149 break;
1150
1151 case EXTENSION_RECORD_TYPE:
Chris Craik9aef3ea2013-06-24 19:34:25 -07001152 if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001153 return (GIF_ERROR);
Chris Craik9aef3ea2013-06-24 19:34:25 -07001154 /* Create an extension block with our data */
Joey Panb5a8e442014-06-12 09:08:26 +08001155 if (ExtData != NULL) {
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -04001156 if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1157 &GifFile->ExtensionBlocks,
1158 ExtFunction, ExtData[0], &ExtData[1])
1159 == GIF_ERROR)
1160 return (GIF_ERROR);
1161 }
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001162 while (ExtData != NULL) {
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001163 if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1164 return (GIF_ERROR);
Chris Craik9aef3ea2013-06-24 19:34:25 -07001165 /* Continue the extension block */
1166 if (ExtData != NULL)
1167 if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1168 &GifFile->ExtensionBlocks,
1169 CONTINUE_EXT_FUNC_CODE,
1170 ExtData[0], &ExtData[1]) == GIF_ERROR)
1171 return (GIF_ERROR);
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001172 }
1173 break;
1174
1175 case TERMINATE_RECORD_TYPE:
1176 break;
1177
1178 default: /* Should be trapped by DGifGetRecordType */
1179 break;
1180 }
1181 } while (RecordType != TERMINATE_RECORD_TYPE);
1182
Leon Scroggins IIIdf596d32017-03-13 14:03:21 -04001183 /* Sanity check for corrupted file */
1184 if (GifFile->ImageCount == 0) {
1185 GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1186 return(GIF_ERROR);
1187 }
1188
The Android Open Source Projectc2eacae2009-03-03 19:29:32 -08001189 return (GIF_OK);
1190}
Chris Craik9aef3ea2013-06-24 19:34:25 -07001191
1192/* end */