xref: /aosp_15_r20/external/giflib/dgif_lib.c (revision 324bb76b8d05e2a05aa88511fff61cf3f9ca5892)
1*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
2*324bb76bSAndroid Build Coastguard Worker 
3*324bb76bSAndroid Build Coastguard Worker dgif_lib.c - GIF decoding
4*324bb76bSAndroid Build Coastguard Worker 
5*324bb76bSAndroid Build Coastguard Worker The functions here and in egif_lib.c are partitioned carefully so that
6*324bb76bSAndroid Build Coastguard Worker if you only require one of read and write capability, only one of these
7*324bb76bSAndroid Build Coastguard Worker two modules will be linked.  Preserve this property!
8*324bb76bSAndroid Build Coastguard Worker 
9*324bb76bSAndroid Build Coastguard Worker SPDX-License-Identifier: MIT
10*324bb76bSAndroid Build Coastguard Worker 
11*324bb76bSAndroid Build Coastguard Worker *****************************************************************************/
12*324bb76bSAndroid Build Coastguard Worker 
13*324bb76bSAndroid Build Coastguard Worker #include <fcntl.h>
14*324bb76bSAndroid Build Coastguard Worker #include <limits.h>
15*324bb76bSAndroid Build Coastguard Worker #include <stdint.h>
16*324bb76bSAndroid Build Coastguard Worker #include <stdio.h>
17*324bb76bSAndroid Build Coastguard Worker #include <stdlib.h>
18*324bb76bSAndroid Build Coastguard Worker #include <string.h>
19*324bb76bSAndroid Build Coastguard Worker 
20*324bb76bSAndroid Build Coastguard Worker #ifdef _WIN32
21*324bb76bSAndroid Build Coastguard Worker #include <io.h>
22*324bb76bSAndroid Build Coastguard Worker #else
23*324bb76bSAndroid Build Coastguard Worker #include <unistd.h>
24*324bb76bSAndroid Build Coastguard Worker #endif /* _WIN32 */
25*324bb76bSAndroid Build Coastguard Worker 
26*324bb76bSAndroid Build Coastguard Worker #include "gif_lib.h"
27*324bb76bSAndroid Build Coastguard Worker #include "gif_lib_private.h"
28*324bb76bSAndroid Build Coastguard Worker 
29*324bb76bSAndroid Build Coastguard Worker /* compose unsigned little endian value */
30*324bb76bSAndroid Build Coastguard Worker #define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
31*324bb76bSAndroid Build Coastguard Worker 
32*324bb76bSAndroid Build Coastguard Worker /* avoid extra function call in case we use fread (TVT) */
InternalRead(GifFileType * gif,GifByteType * buf,int len)33*324bb76bSAndroid Build Coastguard Worker static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
34*324bb76bSAndroid Build Coastguard Worker 	// fprintf(stderr, "### Read: %d\n", len);
35*324bb76bSAndroid Build Coastguard Worker 	return (((GifFilePrivateType *)gif->Private)->Read
36*324bb76bSAndroid Build Coastguard Worker 	            ? ((GifFilePrivateType *)gif->Private)->Read(gif, buf, len)
37*324bb76bSAndroid Build Coastguard Worker 	            : fread(buf, 1, len,
38*324bb76bSAndroid Build Coastguard Worker 	                    ((GifFilePrivateType *)gif->Private)->File));
39*324bb76bSAndroid Build Coastguard Worker }
40*324bb76bSAndroid Build Coastguard Worker 
41*324bb76bSAndroid Build Coastguard Worker static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
42*324bb76bSAndroid Build Coastguard Worker static int DGifSetupDecompress(GifFileType *GifFile);
43*324bb76bSAndroid Build Coastguard Worker static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
44*324bb76bSAndroid Build Coastguard Worker                               int LineLen);
45*324bb76bSAndroid Build Coastguard Worker static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code,
46*324bb76bSAndroid Build Coastguard Worker                              int ClearCode);
47*324bb76bSAndroid Build Coastguard Worker static int DGifDecompressInput(GifFileType *GifFile, int *Code);
48*324bb76bSAndroid Build Coastguard Worker static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
49*324bb76bSAndroid Build Coastguard Worker                              GifByteType *NextByte);
50*324bb76bSAndroid Build Coastguard Worker 
51*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
52*324bb76bSAndroid Build Coastguard Worker  Open a new GIF file for read, given by its name.
53*324bb76bSAndroid Build Coastguard Worker  Returns dynamically allocated GifFileType pointer which serves as the GIF
54*324bb76bSAndroid Build Coastguard Worker  info record.
55*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifOpenFileName(const char * FileName,int * Error)56*324bb76bSAndroid Build Coastguard Worker GifFileType *DGifOpenFileName(const char *FileName, int *Error) {
57*324bb76bSAndroid Build Coastguard Worker 	int FileHandle;
58*324bb76bSAndroid Build Coastguard Worker 	GifFileType *GifFile;
59*324bb76bSAndroid Build Coastguard Worker 
60*324bb76bSAndroid Build Coastguard Worker 	if ((FileHandle = open(FileName, O_RDONLY)) == -1) {
61*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
62*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_OPEN_FAILED;
63*324bb76bSAndroid Build Coastguard Worker 		}
64*324bb76bSAndroid Build Coastguard Worker 		return NULL;
65*324bb76bSAndroid Build Coastguard Worker 	}
66*324bb76bSAndroid Build Coastguard Worker 
67*324bb76bSAndroid Build Coastguard Worker 	GifFile = DGifOpenFileHandle(FileHandle, Error);
68*324bb76bSAndroid Build Coastguard Worker 	return GifFile;
69*324bb76bSAndroid Build Coastguard Worker }
70*324bb76bSAndroid Build Coastguard Worker 
71*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
72*324bb76bSAndroid Build Coastguard Worker  Update a new GIF file, given its file handle.
73*324bb76bSAndroid Build Coastguard Worker  Returns dynamically allocated GifFileType pointer which serves as the GIF
74*324bb76bSAndroid Build Coastguard Worker  info record.
75*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifOpenFileHandle(int FileHandle,int * Error)76*324bb76bSAndroid Build Coastguard Worker GifFileType *DGifOpenFileHandle(int FileHandle, int *Error) {
77*324bb76bSAndroid Build Coastguard Worker 	char Buf[GIF_STAMP_LEN + 1];
78*324bb76bSAndroid Build Coastguard Worker 	GifFileType *GifFile;
79*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private;
80*324bb76bSAndroid Build Coastguard Worker 	FILE *f;
81*324bb76bSAndroid Build Coastguard Worker 
82*324bb76bSAndroid Build Coastguard Worker 	GifFile = (GifFileType *)malloc(sizeof(GifFileType));
83*324bb76bSAndroid Build Coastguard Worker 	if (GifFile == NULL) {
84*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
85*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_NOT_ENOUGH_MEM;
86*324bb76bSAndroid Build Coastguard Worker 		}
87*324bb76bSAndroid Build Coastguard Worker 		(void)close(FileHandle);
88*324bb76bSAndroid Build Coastguard Worker 		return NULL;
89*324bb76bSAndroid Build Coastguard Worker 	}
90*324bb76bSAndroid Build Coastguard Worker 
91*324bb76bSAndroid Build Coastguard Worker 	/*@i1@*/ memset(GifFile, '\0', sizeof(GifFileType));
92*324bb76bSAndroid Build Coastguard Worker 
93*324bb76bSAndroid Build Coastguard Worker 	/* Belt and suspenders, in case the null pointer isn't zero */
94*324bb76bSAndroid Build Coastguard Worker 	GifFile->SavedImages = NULL;
95*324bb76bSAndroid Build Coastguard Worker 	GifFile->SColorMap = NULL;
96*324bb76bSAndroid Build Coastguard Worker 
97*324bb76bSAndroid Build Coastguard Worker 	Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
98*324bb76bSAndroid Build Coastguard Worker 	if (Private == NULL) {
99*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
100*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_NOT_ENOUGH_MEM;
101*324bb76bSAndroid Build Coastguard Worker 		}
102*324bb76bSAndroid Build Coastguard Worker 		(void)close(FileHandle);
103*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
104*324bb76bSAndroid Build Coastguard Worker 		return NULL;
105*324bb76bSAndroid Build Coastguard Worker 	}
106*324bb76bSAndroid Build Coastguard Worker 
107*324bb76bSAndroid Build Coastguard Worker 	/*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType));
108*324bb76bSAndroid Build Coastguard Worker 
109*324bb76bSAndroid Build Coastguard Worker #ifdef _WIN32
110*324bb76bSAndroid Build Coastguard Worker 	_setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
111*324bb76bSAndroid Build Coastguard Worker #endif                                  /* _WIN32 */
112*324bb76bSAndroid Build Coastguard Worker 
113*324bb76bSAndroid Build Coastguard Worker 	f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
114*324bb76bSAndroid Build Coastguard Worker 
115*324bb76bSAndroid Build Coastguard Worker 	/*@-mustfreeonly@*/
116*324bb76bSAndroid Build Coastguard Worker 	GifFile->Private = (void *)Private;
117*324bb76bSAndroid Build Coastguard Worker 	Private->FileHandle = FileHandle;
118*324bb76bSAndroid Build Coastguard Worker 	Private->File = f;
119*324bb76bSAndroid Build Coastguard Worker 	Private->FileState = FILE_STATE_READ;
120*324bb76bSAndroid Build Coastguard Worker 	Private->Read = NULL;     /* don't use alternate input method (TVT) */
121*324bb76bSAndroid Build Coastguard Worker 	GifFile->UserData = NULL; /* TVT */
122*324bb76bSAndroid Build Coastguard Worker 	/*@=mustfreeonly@*/
123*324bb76bSAndroid Build Coastguard Worker 
124*324bb76bSAndroid Build Coastguard Worker 	/* Let's see if this is a GIF file: */
125*324bb76bSAndroid Build Coastguard Worker 	/* coverity[check_return] */
126*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) !=
127*324bb76bSAndroid Build Coastguard Worker 	    GIF_STAMP_LEN) {
128*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
129*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_READ_FAILED;
130*324bb76bSAndroid Build Coastguard Worker 		}
131*324bb76bSAndroid Build Coastguard Worker 		(void)fclose(f);
132*324bb76bSAndroid Build Coastguard Worker 		free((char *)Private);
133*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
134*324bb76bSAndroid Build Coastguard Worker 		return NULL;
135*324bb76bSAndroid Build Coastguard Worker 	}
136*324bb76bSAndroid Build Coastguard Worker 
137*324bb76bSAndroid Build Coastguard Worker 	/* Check for GIF prefix at start of file */
138*324bb76bSAndroid Build Coastguard Worker 	Buf[GIF_STAMP_LEN] = 0;
139*324bb76bSAndroid Build Coastguard Worker 	if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
140*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
141*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_NOT_GIF_FILE;
142*324bb76bSAndroid Build Coastguard Worker 		}
143*324bb76bSAndroid Build Coastguard Worker 		(void)fclose(f);
144*324bb76bSAndroid Build Coastguard Worker 		free((char *)Private);
145*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
146*324bb76bSAndroid Build Coastguard Worker 		return NULL;
147*324bb76bSAndroid Build Coastguard Worker 	}
148*324bb76bSAndroid Build Coastguard Worker 
149*324bb76bSAndroid Build Coastguard Worker 	if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
150*324bb76bSAndroid Build Coastguard Worker 		(void)fclose(f);
151*324bb76bSAndroid Build Coastguard Worker 		free((char *)Private);
152*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
153*324bb76bSAndroid Build Coastguard Worker 		return NULL;
154*324bb76bSAndroid Build Coastguard Worker 	}
155*324bb76bSAndroid Build Coastguard Worker 
156*324bb76bSAndroid Build Coastguard Worker 	GifFile->Error = 0;
157*324bb76bSAndroid Build Coastguard Worker 
158*324bb76bSAndroid Build Coastguard Worker 	/* What version of GIF? */
159*324bb76bSAndroid Build Coastguard Worker 	Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9');
160*324bb76bSAndroid Build Coastguard Worker 
161*324bb76bSAndroid Build Coastguard Worker 	return GifFile;
162*324bb76bSAndroid Build Coastguard Worker }
163*324bb76bSAndroid Build Coastguard Worker 
164*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
165*324bb76bSAndroid Build Coastguard Worker  GifFileType constructor with user supplied input function (TVT)
166*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifOpen(void * userData,InputFunc readFunc,int * Error)167*324bb76bSAndroid Build Coastguard Worker GifFileType *DGifOpen(void *userData, InputFunc readFunc, int *Error) {
168*324bb76bSAndroid Build Coastguard Worker 	char Buf[GIF_STAMP_LEN + 1];
169*324bb76bSAndroid Build Coastguard Worker 	GifFileType *GifFile;
170*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private;
171*324bb76bSAndroid Build Coastguard Worker 
172*324bb76bSAndroid Build Coastguard Worker 	GifFile = (GifFileType *)malloc(sizeof(GifFileType));
173*324bb76bSAndroid Build Coastguard Worker 	if (GifFile == NULL) {
174*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
175*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_NOT_ENOUGH_MEM;
176*324bb76bSAndroid Build Coastguard Worker 		}
177*324bb76bSAndroid Build Coastguard Worker 		return NULL;
178*324bb76bSAndroid Build Coastguard Worker 	}
179*324bb76bSAndroid Build Coastguard Worker 
180*324bb76bSAndroid Build Coastguard Worker 	memset(GifFile, '\0', sizeof(GifFileType));
181*324bb76bSAndroid Build Coastguard Worker 
182*324bb76bSAndroid Build Coastguard Worker 	/* Belt and suspenders, in case the null pointer isn't zero */
183*324bb76bSAndroid Build Coastguard Worker 	GifFile->SavedImages = NULL;
184*324bb76bSAndroid Build Coastguard Worker 	GifFile->SColorMap = NULL;
185*324bb76bSAndroid Build Coastguard Worker 
186*324bb76bSAndroid Build Coastguard Worker 	Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
187*324bb76bSAndroid Build Coastguard Worker 	if (!Private) {
188*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
189*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_NOT_ENOUGH_MEM;
190*324bb76bSAndroid Build Coastguard Worker 		}
191*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
192*324bb76bSAndroid Build Coastguard Worker 		return NULL;
193*324bb76bSAndroid Build Coastguard Worker 	}
194*324bb76bSAndroid Build Coastguard Worker 	/*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType));
195*324bb76bSAndroid Build Coastguard Worker 
196*324bb76bSAndroid Build Coastguard Worker 	GifFile->Private = (void *)Private;
197*324bb76bSAndroid Build Coastguard Worker 	Private->FileHandle = 0;
198*324bb76bSAndroid Build Coastguard Worker 	Private->File = NULL;
199*324bb76bSAndroid Build Coastguard Worker 	Private->FileState = FILE_STATE_READ;
200*324bb76bSAndroid Build Coastguard Worker 
201*324bb76bSAndroid Build Coastguard Worker 	Private->Read = readFunc;     /* TVT */
202*324bb76bSAndroid Build Coastguard Worker 	GifFile->UserData = userData; /* TVT */
203*324bb76bSAndroid Build Coastguard Worker 
204*324bb76bSAndroid Build Coastguard Worker 	/* Lets see if this is a GIF file: */
205*324bb76bSAndroid Build Coastguard Worker 	/* coverity[check_return] */
206*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) !=
207*324bb76bSAndroid Build Coastguard Worker 	    GIF_STAMP_LEN) {
208*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
209*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_READ_FAILED;
210*324bb76bSAndroid Build Coastguard Worker 		}
211*324bb76bSAndroid Build Coastguard Worker 		free((char *)Private);
212*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
213*324bb76bSAndroid Build Coastguard Worker 		return NULL;
214*324bb76bSAndroid Build Coastguard Worker 	}
215*324bb76bSAndroid Build Coastguard Worker 
216*324bb76bSAndroid Build Coastguard Worker 	/* Check for GIF prefix at start of file */
217*324bb76bSAndroid Build Coastguard Worker 	Buf[GIF_STAMP_LEN] = '\0';
218*324bb76bSAndroid Build Coastguard Worker 	if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
219*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
220*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_NOT_GIF_FILE;
221*324bb76bSAndroid Build Coastguard Worker 		}
222*324bb76bSAndroid Build Coastguard Worker 		free((char *)Private);
223*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
224*324bb76bSAndroid Build Coastguard Worker 		return NULL;
225*324bb76bSAndroid Build Coastguard Worker 	}
226*324bb76bSAndroid Build Coastguard Worker 
227*324bb76bSAndroid Build Coastguard Worker 	if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
228*324bb76bSAndroid Build Coastguard Worker 		free((char *)Private);
229*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile);
230*324bb76bSAndroid Build Coastguard Worker 		if (Error != NULL) {
231*324bb76bSAndroid Build Coastguard Worker 			*Error = D_GIF_ERR_NO_SCRN_DSCR;
232*324bb76bSAndroid Build Coastguard Worker 		}
233*324bb76bSAndroid Build Coastguard Worker 		return NULL;
234*324bb76bSAndroid Build Coastguard Worker 	}
235*324bb76bSAndroid Build Coastguard Worker 
236*324bb76bSAndroid Build Coastguard Worker 	GifFile->Error = 0;
237*324bb76bSAndroid Build Coastguard Worker 
238*324bb76bSAndroid Build Coastguard Worker 	/* What version of GIF? */
239*324bb76bSAndroid Build Coastguard Worker 	Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9');
240*324bb76bSAndroid Build Coastguard Worker 
241*324bb76bSAndroid Build Coastguard Worker 	return GifFile;
242*324bb76bSAndroid Build Coastguard Worker }
243*324bb76bSAndroid Build Coastguard Worker 
244*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
245*324bb76bSAndroid Build Coastguard Worker  This routine should be called before any other DGif calls. Note that
246*324bb76bSAndroid Build Coastguard Worker  this routine is called automatically from DGif file open routines.
247*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetScreenDesc(GifFileType * GifFile)248*324bb76bSAndroid Build Coastguard Worker int DGifGetScreenDesc(GifFileType *GifFile) {
249*324bb76bSAndroid Build Coastguard Worker 	int BitsPerPixel;
250*324bb76bSAndroid Build Coastguard Worker 	bool SortFlag;
251*324bb76bSAndroid Build Coastguard Worker 	GifByteType Buf[3];
252*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
253*324bb76bSAndroid Build Coastguard Worker 
254*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
255*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
256*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
257*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
258*324bb76bSAndroid Build Coastguard Worker 	}
259*324bb76bSAndroid Build Coastguard Worker 
260*324bb76bSAndroid Build Coastguard Worker 	/* Put the screen descriptor into the file: */
261*324bb76bSAndroid Build Coastguard Worker 	if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
262*324bb76bSAndroid Build Coastguard Worker 	    DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) {
263*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
264*324bb76bSAndroid Build Coastguard Worker 	}
265*324bb76bSAndroid Build Coastguard Worker 
266*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, Buf, 3) != 3) {
267*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
268*324bb76bSAndroid Build Coastguard Worker 		GifFreeMapObject(GifFile->SColorMap);
269*324bb76bSAndroid Build Coastguard Worker 		GifFile->SColorMap = NULL;
270*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
271*324bb76bSAndroid Build Coastguard Worker 	}
272*324bb76bSAndroid Build Coastguard Worker 	GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
273*324bb76bSAndroid Build Coastguard Worker 	SortFlag = (Buf[0] & 0x08) != 0;
274*324bb76bSAndroid Build Coastguard Worker 	BitsPerPixel = (Buf[0] & 0x07) + 1;
275*324bb76bSAndroid Build Coastguard Worker 	GifFile->SBackGroundColor = Buf[1];
276*324bb76bSAndroid Build Coastguard Worker 	GifFile->AspectByte = Buf[2];
277*324bb76bSAndroid Build Coastguard Worker 	if (Buf[0] & 0x80) { /* Do we have global color map? */
278*324bb76bSAndroid Build Coastguard Worker 		int i;
279*324bb76bSAndroid Build Coastguard Worker 
280*324bb76bSAndroid Build Coastguard Worker 		GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
281*324bb76bSAndroid Build Coastguard Worker 		if (GifFile->SColorMap == NULL) {
282*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
283*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
284*324bb76bSAndroid Build Coastguard Worker 		}
285*324bb76bSAndroid Build Coastguard Worker 
286*324bb76bSAndroid Build Coastguard Worker 		/* Get the global color map: */
287*324bb76bSAndroid Build Coastguard Worker 		GifFile->SColorMap->SortFlag = SortFlag;
288*324bb76bSAndroid Build Coastguard Worker 		for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
289*324bb76bSAndroid Build Coastguard Worker 			/* coverity[check_return] */
290*324bb76bSAndroid Build Coastguard Worker 			if (InternalRead(GifFile, Buf, 3) != 3) {
291*324bb76bSAndroid Build Coastguard Worker 				GifFreeMapObject(GifFile->SColorMap);
292*324bb76bSAndroid Build Coastguard Worker 				GifFile->SColorMap = NULL;
293*324bb76bSAndroid Build Coastguard Worker 				GifFile->Error = D_GIF_ERR_READ_FAILED;
294*324bb76bSAndroid Build Coastguard Worker 				return GIF_ERROR;
295*324bb76bSAndroid Build Coastguard Worker 			}
296*324bb76bSAndroid Build Coastguard Worker 			GifFile->SColorMap->Colors[i].Red = Buf[0];
297*324bb76bSAndroid Build Coastguard Worker 			GifFile->SColorMap->Colors[i].Green = Buf[1];
298*324bb76bSAndroid Build Coastguard Worker 			GifFile->SColorMap->Colors[i].Blue = Buf[2];
299*324bb76bSAndroid Build Coastguard Worker 		}
300*324bb76bSAndroid Build Coastguard Worker 	} else {
301*324bb76bSAndroid Build Coastguard Worker 		GifFile->SColorMap = NULL;
302*324bb76bSAndroid Build Coastguard Worker 	}
303*324bb76bSAndroid Build Coastguard Worker 
304*324bb76bSAndroid Build Coastguard Worker 	/*
305*324bb76bSAndroid Build Coastguard Worker 	 * No check here for whether the background color is in range for the
306*324bb76bSAndroid Build Coastguard Worker 	 * screen color map.  Possibly there should be.
307*324bb76bSAndroid Build Coastguard Worker 	 */
308*324bb76bSAndroid Build Coastguard Worker 
309*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
310*324bb76bSAndroid Build Coastguard Worker }
311*324bb76bSAndroid Build Coastguard Worker 
DGifGetGifVersion(GifFileType * GifFile)312*324bb76bSAndroid Build Coastguard Worker const char *DGifGetGifVersion(GifFileType *GifFile) {
313*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
314*324bb76bSAndroid Build Coastguard Worker 
315*324bb76bSAndroid Build Coastguard Worker 	if (Private->gif89) {
316*324bb76bSAndroid Build Coastguard Worker 		return GIF89_STAMP;
317*324bb76bSAndroid Build Coastguard Worker 	} else {
318*324bb76bSAndroid Build Coastguard Worker 		return GIF87_STAMP;
319*324bb76bSAndroid Build Coastguard Worker 	}
320*324bb76bSAndroid Build Coastguard Worker }
321*324bb76bSAndroid Build Coastguard Worker 
322*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
323*324bb76bSAndroid Build Coastguard Worker  This routine should be called before any attempt to read an image.
324*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetRecordType(GifFileType * GifFile,GifRecordType * Type)325*324bb76bSAndroid Build Coastguard Worker int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type) {
326*324bb76bSAndroid Build Coastguard Worker 	GifByteType Buf;
327*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
328*324bb76bSAndroid Build Coastguard Worker 
329*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
330*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
331*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
332*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
333*324bb76bSAndroid Build Coastguard Worker 	}
334*324bb76bSAndroid Build Coastguard Worker 
335*324bb76bSAndroid Build Coastguard Worker 	/* coverity[check_return] */
336*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, &Buf, 1) != 1) {
337*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
338*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
339*324bb76bSAndroid Build Coastguard Worker 	}
340*324bb76bSAndroid Build Coastguard Worker 
341*324bb76bSAndroid Build Coastguard Worker 	// fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
342*324bb76bSAndroid Build Coastguard Worker 	switch (Buf) {
343*324bb76bSAndroid Build Coastguard Worker 	case DESCRIPTOR_INTRODUCER:
344*324bb76bSAndroid Build Coastguard Worker 		*Type = IMAGE_DESC_RECORD_TYPE;
345*324bb76bSAndroid Build Coastguard Worker 		break;
346*324bb76bSAndroid Build Coastguard Worker 	case EXTENSION_INTRODUCER:
347*324bb76bSAndroid Build Coastguard Worker 		*Type = EXTENSION_RECORD_TYPE;
348*324bb76bSAndroid Build Coastguard Worker 		break;
349*324bb76bSAndroid Build Coastguard Worker 	case TERMINATOR_INTRODUCER:
350*324bb76bSAndroid Build Coastguard Worker 		*Type = TERMINATE_RECORD_TYPE;
351*324bb76bSAndroid Build Coastguard Worker 		break;
352*324bb76bSAndroid Build Coastguard Worker 	default:
353*324bb76bSAndroid Build Coastguard Worker 		*Type = UNDEFINED_RECORD_TYPE;
354*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_WRONG_RECORD;
355*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
356*324bb76bSAndroid Build Coastguard Worker 	}
357*324bb76bSAndroid Build Coastguard Worker 
358*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
359*324bb76bSAndroid Build Coastguard Worker }
360*324bb76bSAndroid Build Coastguard Worker 
DGifGetImageHeader(GifFileType * GifFile)361*324bb76bSAndroid Build Coastguard Worker int DGifGetImageHeader(GifFileType *GifFile) {
362*324bb76bSAndroid Build Coastguard Worker 	unsigned int BitsPerPixel;
363*324bb76bSAndroid Build Coastguard Worker 	GifByteType Buf[3];
364*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
365*324bb76bSAndroid Build Coastguard Worker 
366*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
367*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
368*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
369*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
370*324bb76bSAndroid Build Coastguard Worker 	}
371*324bb76bSAndroid Build Coastguard Worker 
372*324bb76bSAndroid Build Coastguard Worker 	if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
373*324bb76bSAndroid Build Coastguard Worker 	    DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
374*324bb76bSAndroid Build Coastguard Worker 	    DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
375*324bb76bSAndroid Build Coastguard Worker 	    DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) {
376*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
377*324bb76bSAndroid Build Coastguard Worker 	}
378*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, Buf, 1) != 1) {
379*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
380*324bb76bSAndroid Build Coastguard Worker 		GifFreeMapObject(GifFile->Image.ColorMap);
381*324bb76bSAndroid Build Coastguard Worker 		GifFile->Image.ColorMap = NULL;
382*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
383*324bb76bSAndroid Build Coastguard Worker 	}
384*324bb76bSAndroid Build Coastguard Worker 	BitsPerPixel = (Buf[0] & 0x07) + 1;
385*324bb76bSAndroid Build Coastguard Worker 	GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
386*324bb76bSAndroid Build Coastguard Worker 
387*324bb76bSAndroid Build Coastguard Worker 	/* Setup the colormap */
388*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->Image.ColorMap) {
389*324bb76bSAndroid Build Coastguard Worker 		GifFreeMapObject(GifFile->Image.ColorMap);
390*324bb76bSAndroid Build Coastguard Worker 		GifFile->Image.ColorMap = NULL;
391*324bb76bSAndroid Build Coastguard Worker 	}
392*324bb76bSAndroid Build Coastguard Worker 	/* Does this image have local color map? */
393*324bb76bSAndroid Build Coastguard Worker 	if (Buf[0] & 0x80) {
394*324bb76bSAndroid Build Coastguard Worker 		unsigned int i;
395*324bb76bSAndroid Build Coastguard Worker 
396*324bb76bSAndroid Build Coastguard Worker 		GifFile->Image.ColorMap =
397*324bb76bSAndroid Build Coastguard Worker 		    GifMakeMapObject(1 << BitsPerPixel, NULL);
398*324bb76bSAndroid Build Coastguard Worker 		if (GifFile->Image.ColorMap == NULL) {
399*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
400*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
401*324bb76bSAndroid Build Coastguard Worker 		}
402*324bb76bSAndroid Build Coastguard Worker 
403*324bb76bSAndroid Build Coastguard Worker 		/* Get the image local color map: */
404*324bb76bSAndroid Build Coastguard Worker 		for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
405*324bb76bSAndroid Build Coastguard Worker 			/* coverity[check_return] */
406*324bb76bSAndroid Build Coastguard Worker 			if (InternalRead(GifFile, Buf, 3) != 3) {
407*324bb76bSAndroid Build Coastguard Worker 				GifFreeMapObject(GifFile->Image.ColorMap);
408*324bb76bSAndroid Build Coastguard Worker 				GifFile->Error = D_GIF_ERR_READ_FAILED;
409*324bb76bSAndroid Build Coastguard Worker 				GifFile->Image.ColorMap = NULL;
410*324bb76bSAndroid Build Coastguard Worker 				return GIF_ERROR;
411*324bb76bSAndroid Build Coastguard Worker 			}
412*324bb76bSAndroid Build Coastguard Worker 			GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
413*324bb76bSAndroid Build Coastguard Worker 			GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
414*324bb76bSAndroid Build Coastguard Worker 			GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
415*324bb76bSAndroid Build Coastguard Worker 		}
416*324bb76bSAndroid Build Coastguard Worker 	}
417*324bb76bSAndroid Build Coastguard Worker 
418*324bb76bSAndroid Build Coastguard Worker 	Private->PixelCount =
419*324bb76bSAndroid Build Coastguard Worker 	    (long)GifFile->Image.Width * (long)GifFile->Image.Height;
420*324bb76bSAndroid Build Coastguard Worker 
421*324bb76bSAndroid Build Coastguard Worker 	/* Reset decompress algorithm parameters. */
422*324bb76bSAndroid Build Coastguard Worker 	return DGifSetupDecompress(GifFile);
423*324bb76bSAndroid Build Coastguard Worker }
424*324bb76bSAndroid Build Coastguard Worker 
425*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
426*324bb76bSAndroid Build Coastguard Worker  This routine should be called before any attempt to read an image.
427*324bb76bSAndroid Build Coastguard Worker  Note it is assumed the Image desc. header has been read.
428*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetImageDesc(GifFileType * GifFile)429*324bb76bSAndroid Build Coastguard Worker int DGifGetImageDesc(GifFileType *GifFile) {
430*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
431*324bb76bSAndroid Build Coastguard Worker 	SavedImage *sp;
432*324bb76bSAndroid Build Coastguard Worker 
433*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
434*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
435*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
436*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
437*324bb76bSAndroid Build Coastguard Worker 	}
438*324bb76bSAndroid Build Coastguard Worker 
439*324bb76bSAndroid Build Coastguard Worker 	if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
440*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
441*324bb76bSAndroid Build Coastguard Worker 	}
442*324bb76bSAndroid Build Coastguard Worker 
443*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->SavedImages) {
444*324bb76bSAndroid Build Coastguard Worker 		SavedImage *new_saved_images = (SavedImage *)reallocarray(
445*324bb76bSAndroid Build Coastguard Worker 		    GifFile->SavedImages, (GifFile->ImageCount + 1),
446*324bb76bSAndroid Build Coastguard Worker 		    sizeof(SavedImage));
447*324bb76bSAndroid Build Coastguard Worker 		if (new_saved_images == NULL) {
448*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
449*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
450*324bb76bSAndroid Build Coastguard Worker 		}
451*324bb76bSAndroid Build Coastguard Worker 		GifFile->SavedImages = new_saved_images;
452*324bb76bSAndroid Build Coastguard Worker 	} else {
453*324bb76bSAndroid Build Coastguard Worker 		if ((GifFile->SavedImages =
454*324bb76bSAndroid Build Coastguard Worker 		         (SavedImage *)malloc(sizeof(SavedImage))) == NULL) {
455*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
456*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
457*324bb76bSAndroid Build Coastguard Worker 		}
458*324bb76bSAndroid Build Coastguard Worker 	}
459*324bb76bSAndroid Build Coastguard Worker 
460*324bb76bSAndroid Build Coastguard Worker 	sp = &GifFile->SavedImages[GifFile->ImageCount];
461*324bb76bSAndroid Build Coastguard Worker 	memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
462*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->Image.ColorMap != NULL) {
463*324bb76bSAndroid Build Coastguard Worker 		sp->ImageDesc.ColorMap =
464*324bb76bSAndroid Build Coastguard Worker 		    GifMakeMapObject(GifFile->Image.ColorMap->ColorCount,
465*324bb76bSAndroid Build Coastguard Worker 		                     GifFile->Image.ColorMap->Colors);
466*324bb76bSAndroid Build Coastguard Worker 		if (sp->ImageDesc.ColorMap == NULL) {
467*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
468*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
469*324bb76bSAndroid Build Coastguard Worker 		}
470*324bb76bSAndroid Build Coastguard Worker 	}
471*324bb76bSAndroid Build Coastguard Worker 	sp->RasterBits = (unsigned char *)NULL;
472*324bb76bSAndroid Build Coastguard Worker 	sp->ExtensionBlockCount = 0;
473*324bb76bSAndroid Build Coastguard Worker 	sp->ExtensionBlocks = (ExtensionBlock *)NULL;
474*324bb76bSAndroid Build Coastguard Worker 
475*324bb76bSAndroid Build Coastguard Worker 	GifFile->ImageCount++;
476*324bb76bSAndroid Build Coastguard Worker 
477*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
478*324bb76bSAndroid Build Coastguard Worker }
479*324bb76bSAndroid Build Coastguard Worker 
480*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
481*324bb76bSAndroid Build Coastguard Worker  Get one full scanned line (Line) of length LineLen from GIF file.
482*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetLine(GifFileType * GifFile,GifPixelType * Line,int LineLen)483*324bb76bSAndroid Build Coastguard Worker int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) {
484*324bb76bSAndroid Build Coastguard Worker 	GifByteType *Dummy;
485*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
486*324bb76bSAndroid Build Coastguard Worker 
487*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
488*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
489*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
490*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
491*324bb76bSAndroid Build Coastguard Worker 	}
492*324bb76bSAndroid Build Coastguard Worker 
493*324bb76bSAndroid Build Coastguard Worker 	if (!LineLen) {
494*324bb76bSAndroid Build Coastguard Worker 		LineLen = GifFile->Image.Width;
495*324bb76bSAndroid Build Coastguard Worker 	}
496*324bb76bSAndroid Build Coastguard Worker 
497*324bb76bSAndroid Build Coastguard Worker 	if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
498*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
499*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
500*324bb76bSAndroid Build Coastguard Worker 	}
501*324bb76bSAndroid Build Coastguard Worker 
502*324bb76bSAndroid Build Coastguard Worker 	if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
503*324bb76bSAndroid Build Coastguard Worker 		if (Private->PixelCount == 0) {
504*324bb76bSAndroid Build Coastguard Worker 			/* We probably won't be called any more, so let's clean
505*324bb76bSAndroid Build Coastguard Worker 			 * up everything before we return: need to flush out all
506*324bb76bSAndroid Build Coastguard Worker 			 * the rest of image until an empty block (size 0)
507*324bb76bSAndroid Build Coastguard Worker 			 * detected. We use GetCodeNext.
508*324bb76bSAndroid Build Coastguard Worker 			 */
509*324bb76bSAndroid Build Coastguard Worker 			do {
510*324bb76bSAndroid Build Coastguard Worker 				if (DGifGetCodeNext(GifFile, &Dummy) ==
511*324bb76bSAndroid Build Coastguard Worker 				    GIF_ERROR) {
512*324bb76bSAndroid Build Coastguard Worker 					return GIF_ERROR;
513*324bb76bSAndroid Build Coastguard Worker 				}
514*324bb76bSAndroid Build Coastguard Worker 			} while (Dummy != NULL);
515*324bb76bSAndroid Build Coastguard Worker 		}
516*324bb76bSAndroid Build Coastguard Worker 		return GIF_OK;
517*324bb76bSAndroid Build Coastguard Worker 	} else {
518*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
519*324bb76bSAndroid Build Coastguard Worker 	}
520*324bb76bSAndroid Build Coastguard Worker }
521*324bb76bSAndroid Build Coastguard Worker 
522*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
523*324bb76bSAndroid Build Coastguard Worker  Put one pixel (Pixel) into GIF file.
524*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetPixel(GifFileType * GifFile,GifPixelType Pixel)525*324bb76bSAndroid Build Coastguard Worker int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) {
526*324bb76bSAndroid Build Coastguard Worker 	GifByteType *Dummy;
527*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
528*324bb76bSAndroid Build Coastguard Worker 
529*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
530*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
531*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
532*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
533*324bb76bSAndroid Build Coastguard Worker 	}
534*324bb76bSAndroid Build Coastguard Worker 	if (--Private->PixelCount > 0xffff0000UL) {
535*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
536*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
537*324bb76bSAndroid Build Coastguard Worker 	}
538*324bb76bSAndroid Build Coastguard Worker 
539*324bb76bSAndroid Build Coastguard Worker 	if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
540*324bb76bSAndroid Build Coastguard Worker 		if (Private->PixelCount == 0) {
541*324bb76bSAndroid Build Coastguard Worker 			/* We probably won't be called any more, so let's clean
542*324bb76bSAndroid Build Coastguard Worker 			 * up everything before we return: need to flush out all
543*324bb76bSAndroid Build Coastguard Worker 			 * the rest of image until an empty block (size 0)
544*324bb76bSAndroid Build Coastguard Worker 			 * detected. We use GetCodeNext.
545*324bb76bSAndroid Build Coastguard Worker 			 */
546*324bb76bSAndroid Build Coastguard Worker 			do {
547*324bb76bSAndroid Build Coastguard Worker 				if (DGifGetCodeNext(GifFile, &Dummy) ==
548*324bb76bSAndroid Build Coastguard Worker 				    GIF_ERROR) {
549*324bb76bSAndroid Build Coastguard Worker 					return GIF_ERROR;
550*324bb76bSAndroid Build Coastguard Worker 				}
551*324bb76bSAndroid Build Coastguard Worker 			} while (Dummy != NULL);
552*324bb76bSAndroid Build Coastguard Worker 		}
553*324bb76bSAndroid Build Coastguard Worker 		return GIF_OK;
554*324bb76bSAndroid Build Coastguard Worker 	} else {
555*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
556*324bb76bSAndroid Build Coastguard Worker 	}
557*324bb76bSAndroid Build Coastguard Worker }
558*324bb76bSAndroid Build Coastguard Worker 
559*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
560*324bb76bSAndroid Build Coastguard Worker  Get an extension block (see GIF manual) from GIF file. This routine only
561*324bb76bSAndroid Build Coastguard Worker  returns the first data block, and DGifGetExtensionNext should be called
562*324bb76bSAndroid Build Coastguard Worker  after this one until NULL extension is returned.
563*324bb76bSAndroid Build Coastguard Worker  The Extension should NOT be freed by the user (not dynamically allocated).
564*324bb76bSAndroid Build Coastguard Worker  Note it is assumed the Extension description header has been read.
565*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetExtension(GifFileType * GifFile,int * ExtCode,GifByteType ** Extension)566*324bb76bSAndroid Build Coastguard Worker int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
567*324bb76bSAndroid Build Coastguard Worker                      GifByteType **Extension) {
568*324bb76bSAndroid Build Coastguard Worker 	GifByteType Buf;
569*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
570*324bb76bSAndroid Build Coastguard Worker 
571*324bb76bSAndroid Build Coastguard Worker 	// fprintf(stderr, "### -> DGifGetExtension:\n");
572*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
573*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
574*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
575*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
576*324bb76bSAndroid Build Coastguard Worker 	}
577*324bb76bSAndroid Build Coastguard Worker 
578*324bb76bSAndroid Build Coastguard Worker 	/* coverity[check_return] */
579*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, &Buf, 1) != 1) {
580*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
581*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
582*324bb76bSAndroid Build Coastguard Worker 	}
583*324bb76bSAndroid Build Coastguard Worker 	*ExtCode = Buf;
584*324bb76bSAndroid Build Coastguard Worker 	// fprintf(stderr, "### <- DGifGetExtension: %02x, about to call
585*324bb76bSAndroid Build Coastguard Worker 	// next\n", Buf);
586*324bb76bSAndroid Build Coastguard Worker 
587*324bb76bSAndroid Build Coastguard Worker 	return DGifGetExtensionNext(GifFile, Extension);
588*324bb76bSAndroid Build Coastguard Worker }
589*324bb76bSAndroid Build Coastguard Worker 
590*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
591*324bb76bSAndroid Build Coastguard Worker  Get a following extension block (see GIF manual) from GIF file. This
592*324bb76bSAndroid Build Coastguard Worker  routine should be called until NULL Extension is returned.
593*324bb76bSAndroid Build Coastguard Worker  The Extension should NOT be freed by the user (not dynamically allocated).
594*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetExtensionNext(GifFileType * GifFile,GifByteType ** Extension)595*324bb76bSAndroid Build Coastguard Worker int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) {
596*324bb76bSAndroid Build Coastguard Worker 	GifByteType Buf;
597*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
598*324bb76bSAndroid Build Coastguard Worker 
599*324bb76bSAndroid Build Coastguard Worker 	// fprintf(stderr, "### -> DGifGetExtensionNext\n");
600*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, &Buf, 1) != 1) {
601*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
602*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
603*324bb76bSAndroid Build Coastguard Worker 	}
604*324bb76bSAndroid Build Coastguard Worker 	// fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
605*324bb76bSAndroid Build Coastguard Worker 
606*324bb76bSAndroid Build Coastguard Worker 	if (Buf > 0) {
607*324bb76bSAndroid Build Coastguard Worker 		*Extension = Private->Buf; /* Use private unused buffer. */
608*324bb76bSAndroid Build Coastguard Worker 		(*Extension)[0] =
609*324bb76bSAndroid Build Coastguard Worker 		    Buf; /* Pascal strings notation (pos. 0 is len.). */
610*324bb76bSAndroid Build Coastguard Worker 		         /* coverity[tainted_data,check_return] */
611*324bb76bSAndroid Build Coastguard Worker 		if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
612*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_READ_FAILED;
613*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
614*324bb76bSAndroid Build Coastguard Worker 		}
615*324bb76bSAndroid Build Coastguard Worker 	} else {
616*324bb76bSAndroid Build Coastguard Worker 		*Extension = NULL;
617*324bb76bSAndroid Build Coastguard Worker 	}
618*324bb76bSAndroid Build Coastguard Worker 	// fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
619*324bb76bSAndroid Build Coastguard Worker 
620*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
621*324bb76bSAndroid Build Coastguard Worker }
622*324bb76bSAndroid Build Coastguard Worker 
623*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
624*324bb76bSAndroid Build Coastguard Worker  Extract a Graphics Control Block from raw extension data
625*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
626*324bb76bSAndroid Build Coastguard Worker 
DGifExtensionToGCB(const size_t GifExtensionLength,const GifByteType * GifExtension,GraphicsControlBlock * GCB)627*324bb76bSAndroid Build Coastguard Worker int DGifExtensionToGCB(const size_t GifExtensionLength,
628*324bb76bSAndroid Build Coastguard Worker                        const GifByteType *GifExtension,
629*324bb76bSAndroid Build Coastguard Worker                        GraphicsControlBlock *GCB) {
630*324bb76bSAndroid Build Coastguard Worker 	if (GifExtensionLength != 4) {
631*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
632*324bb76bSAndroid Build Coastguard Worker 	}
633*324bb76bSAndroid Build Coastguard Worker 
634*324bb76bSAndroid Build Coastguard Worker 	GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
635*324bb76bSAndroid Build Coastguard Worker 	GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
636*324bb76bSAndroid Build Coastguard Worker 	GCB->DelayTime =
637*324bb76bSAndroid Build Coastguard Worker 	    UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
638*324bb76bSAndroid Build Coastguard Worker 	if (GifExtension[0] & 0x01) {
639*324bb76bSAndroid Build Coastguard Worker 		GCB->TransparentColor = (int)GifExtension[3];
640*324bb76bSAndroid Build Coastguard Worker 	} else {
641*324bb76bSAndroid Build Coastguard Worker 		GCB->TransparentColor = NO_TRANSPARENT_COLOR;
642*324bb76bSAndroid Build Coastguard Worker 	}
643*324bb76bSAndroid Build Coastguard Worker 
644*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
645*324bb76bSAndroid Build Coastguard Worker }
646*324bb76bSAndroid Build Coastguard Worker 
647*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
648*324bb76bSAndroid Build Coastguard Worker  Extract the Graphics Control Block for a saved image, if it exists.
649*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
650*324bb76bSAndroid Build Coastguard Worker 
DGifSavedExtensionToGCB(GifFileType * GifFile,int ImageIndex,GraphicsControlBlock * GCB)651*324bb76bSAndroid Build Coastguard Worker int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex,
652*324bb76bSAndroid Build Coastguard Worker                             GraphicsControlBlock *GCB) {
653*324bb76bSAndroid Build Coastguard Worker 	int i;
654*324bb76bSAndroid Build Coastguard Worker 
655*324bb76bSAndroid Build Coastguard Worker 	if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) {
656*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
657*324bb76bSAndroid Build Coastguard Worker 	}
658*324bb76bSAndroid Build Coastguard Worker 
659*324bb76bSAndroid Build Coastguard Worker 	GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
660*324bb76bSAndroid Build Coastguard Worker 	GCB->UserInputFlag = false;
661*324bb76bSAndroid Build Coastguard Worker 	GCB->DelayTime = 0;
662*324bb76bSAndroid Build Coastguard Worker 	GCB->TransparentColor = NO_TRANSPARENT_COLOR;
663*324bb76bSAndroid Build Coastguard Worker 
664*324bb76bSAndroid Build Coastguard Worker 	for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount;
665*324bb76bSAndroid Build Coastguard Worker 	     i++) {
666*324bb76bSAndroid Build Coastguard Worker 		ExtensionBlock *ep =
667*324bb76bSAndroid Build Coastguard Worker 		    &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
668*324bb76bSAndroid Build Coastguard Worker 		if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
669*324bb76bSAndroid Build Coastguard Worker 			return DGifExtensionToGCB(ep->ByteCount, ep->Bytes,
670*324bb76bSAndroid Build Coastguard Worker 			                          GCB);
671*324bb76bSAndroid Build Coastguard Worker 		}
672*324bb76bSAndroid Build Coastguard Worker 	}
673*324bb76bSAndroid Build Coastguard Worker 
674*324bb76bSAndroid Build Coastguard Worker 	return GIF_ERROR;
675*324bb76bSAndroid Build Coastguard Worker }
676*324bb76bSAndroid Build Coastguard Worker 
677*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
678*324bb76bSAndroid Build Coastguard Worker  This routine should be called last, to close the GIF file.
679*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifCloseFile(GifFileType * GifFile,int * ErrorCode)680*324bb76bSAndroid Build Coastguard Worker int DGifCloseFile(GifFileType *GifFile, int *ErrorCode) {
681*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private;
682*324bb76bSAndroid Build Coastguard Worker 
683*324bb76bSAndroid Build Coastguard Worker 	if (GifFile == NULL || GifFile->Private == NULL) {
684*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
685*324bb76bSAndroid Build Coastguard Worker 	}
686*324bb76bSAndroid Build Coastguard Worker 
687*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->Image.ColorMap) {
688*324bb76bSAndroid Build Coastguard Worker 		GifFreeMapObject(GifFile->Image.ColorMap);
689*324bb76bSAndroid Build Coastguard Worker 		GifFile->Image.ColorMap = NULL;
690*324bb76bSAndroid Build Coastguard Worker 	}
691*324bb76bSAndroid Build Coastguard Worker 
692*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->SColorMap) {
693*324bb76bSAndroid Build Coastguard Worker 		GifFreeMapObject(GifFile->SColorMap);
694*324bb76bSAndroid Build Coastguard Worker 		GifFile->SColorMap = NULL;
695*324bb76bSAndroid Build Coastguard Worker 	}
696*324bb76bSAndroid Build Coastguard Worker 
697*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->SavedImages) {
698*324bb76bSAndroid Build Coastguard Worker 		GifFreeSavedImages(GifFile);
699*324bb76bSAndroid Build Coastguard Worker 		GifFile->SavedImages = NULL;
700*324bb76bSAndroid Build Coastguard Worker 	}
701*324bb76bSAndroid Build Coastguard Worker 
702*324bb76bSAndroid Build Coastguard Worker 	GifFreeExtensions(&GifFile->ExtensionBlockCount,
703*324bb76bSAndroid Build Coastguard Worker 	                  &GifFile->ExtensionBlocks);
704*324bb76bSAndroid Build Coastguard Worker 
705*324bb76bSAndroid Build Coastguard Worker 	Private = (GifFilePrivateType *)GifFile->Private;
706*324bb76bSAndroid Build Coastguard Worker 
707*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
708*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
709*324bb76bSAndroid Build Coastguard Worker 		if (ErrorCode != NULL) {
710*324bb76bSAndroid Build Coastguard Worker 			*ErrorCode = D_GIF_ERR_NOT_READABLE;
711*324bb76bSAndroid Build Coastguard Worker 		}
712*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile->Private);
713*324bb76bSAndroid Build Coastguard Worker 		free(GifFile);
714*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
715*324bb76bSAndroid Build Coastguard Worker 	}
716*324bb76bSAndroid Build Coastguard Worker 
717*324bb76bSAndroid Build Coastguard Worker 	if (Private->File && (fclose(Private->File) != 0)) {
718*324bb76bSAndroid Build Coastguard Worker 		if (ErrorCode != NULL) {
719*324bb76bSAndroid Build Coastguard Worker 			*ErrorCode = D_GIF_ERR_CLOSE_FAILED;
720*324bb76bSAndroid Build Coastguard Worker 		}
721*324bb76bSAndroid Build Coastguard Worker 		free((char *)GifFile->Private);
722*324bb76bSAndroid Build Coastguard Worker 		free(GifFile);
723*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
724*324bb76bSAndroid Build Coastguard Worker 	}
725*324bb76bSAndroid Build Coastguard Worker 
726*324bb76bSAndroid Build Coastguard Worker 	free((char *)GifFile->Private);
727*324bb76bSAndroid Build Coastguard Worker 	free(GifFile);
728*324bb76bSAndroid Build Coastguard Worker 	if (ErrorCode != NULL) {
729*324bb76bSAndroid Build Coastguard Worker 		*ErrorCode = D_GIF_SUCCEEDED;
730*324bb76bSAndroid Build Coastguard Worker 	}
731*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
732*324bb76bSAndroid Build Coastguard Worker }
733*324bb76bSAndroid Build Coastguard Worker 
734*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
735*324bb76bSAndroid Build Coastguard Worker  Get 2 bytes (word) from the given file:
736*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetWord(GifFileType * GifFile,GifWord * Word)737*324bb76bSAndroid Build Coastguard Worker static int DGifGetWord(GifFileType *GifFile, GifWord *Word) {
738*324bb76bSAndroid Build Coastguard Worker 	unsigned char c[2];
739*324bb76bSAndroid Build Coastguard Worker 
740*324bb76bSAndroid Build Coastguard Worker 	/* coverity[check_return] */
741*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, c, 2) != 2) {
742*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
743*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
744*324bb76bSAndroid Build Coastguard Worker 	}
745*324bb76bSAndroid Build Coastguard Worker 
746*324bb76bSAndroid Build Coastguard Worker 	*Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
747*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
748*324bb76bSAndroid Build Coastguard Worker }
749*324bb76bSAndroid Build Coastguard Worker 
750*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
751*324bb76bSAndroid Build Coastguard Worker  Get the image code in compressed form.  This routine can be called if the
752*324bb76bSAndroid Build Coastguard Worker  information needed to be piped out as is. Obviously this is much faster
753*324bb76bSAndroid Build Coastguard Worker  than decoding and encoding again. This routine should be followed by calls
754*324bb76bSAndroid Build Coastguard Worker  to DGifGetCodeNext, until NULL block is returned.
755*324bb76bSAndroid Build Coastguard Worker  The block should NOT be freed by the user (not dynamically allocated).
756*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetCode(GifFileType * GifFile,int * CodeSize,GifByteType ** CodeBlock)757*324bb76bSAndroid Build Coastguard Worker int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) {
758*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
759*324bb76bSAndroid Build Coastguard Worker 
760*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
761*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
762*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
763*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
764*324bb76bSAndroid Build Coastguard Worker 	}
765*324bb76bSAndroid Build Coastguard Worker 
766*324bb76bSAndroid Build Coastguard Worker 	*CodeSize = Private->BitsPerPixel;
767*324bb76bSAndroid Build Coastguard Worker 
768*324bb76bSAndroid Build Coastguard Worker 	return DGifGetCodeNext(GifFile, CodeBlock);
769*324bb76bSAndroid Build Coastguard Worker }
770*324bb76bSAndroid Build Coastguard Worker 
771*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
772*324bb76bSAndroid Build Coastguard Worker  Continue to get the image code in compressed form. This routine should be
773*324bb76bSAndroid Build Coastguard Worker  called until NULL block is returned.
774*324bb76bSAndroid Build Coastguard Worker  The block should NOT be freed by the user (not dynamically allocated).
775*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetCodeNext(GifFileType * GifFile,GifByteType ** CodeBlock)776*324bb76bSAndroid Build Coastguard Worker int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) {
777*324bb76bSAndroid Build Coastguard Worker 	GifByteType Buf;
778*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
779*324bb76bSAndroid Build Coastguard Worker 
780*324bb76bSAndroid Build Coastguard Worker 	/* coverity[tainted_data_argument] */
781*324bb76bSAndroid Build Coastguard Worker 	/* coverity[check_return] */
782*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, &Buf, 1) != 1) {
783*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
784*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
785*324bb76bSAndroid Build Coastguard Worker 	}
786*324bb76bSAndroid Build Coastguard Worker 
787*324bb76bSAndroid Build Coastguard Worker 	/* coverity[lower_bounds] */
788*324bb76bSAndroid Build Coastguard Worker 	if (Buf > 0) {
789*324bb76bSAndroid Build Coastguard Worker 		*CodeBlock = Private->Buf; /* Use private unused buffer. */
790*324bb76bSAndroid Build Coastguard Worker 		(*CodeBlock)[0] =
791*324bb76bSAndroid Build Coastguard Worker 		    Buf; /* Pascal strings notation (pos. 0 is len.). */
792*324bb76bSAndroid Build Coastguard Worker 		         /* coverity[tainted_data] */
793*324bb76bSAndroid Build Coastguard Worker 		if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
794*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_READ_FAILED;
795*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
796*324bb76bSAndroid Build Coastguard Worker 		}
797*324bb76bSAndroid Build Coastguard Worker 	} else {
798*324bb76bSAndroid Build Coastguard Worker 		*CodeBlock = NULL;
799*324bb76bSAndroid Build Coastguard Worker 		Private->Buf[0] = 0; /* Make sure the buffer is empty! */
800*324bb76bSAndroid Build Coastguard Worker 		Private->PixelCount =
801*324bb76bSAndroid Build Coastguard Worker 		    0; /* And local info. indicate image read. */
802*324bb76bSAndroid Build Coastguard Worker 	}
803*324bb76bSAndroid Build Coastguard Worker 
804*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
805*324bb76bSAndroid Build Coastguard Worker }
806*324bb76bSAndroid Build Coastguard Worker 
807*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
808*324bb76bSAndroid Build Coastguard Worker  Setup the LZ decompression for this image:
809*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifSetupDecompress(GifFileType * GifFile)810*324bb76bSAndroid Build Coastguard Worker static int DGifSetupDecompress(GifFileType *GifFile) {
811*324bb76bSAndroid Build Coastguard Worker 	int i, BitsPerPixel;
812*324bb76bSAndroid Build Coastguard Worker 	GifByteType CodeSize;
813*324bb76bSAndroid Build Coastguard Worker 	GifPrefixType *Prefix;
814*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
815*324bb76bSAndroid Build Coastguard Worker 
816*324bb76bSAndroid Build Coastguard Worker 	/* coverity[check_return] */
817*324bb76bSAndroid Build Coastguard Worker 	if (InternalRead(GifFile, &CodeSize, 1) <
818*324bb76bSAndroid Build Coastguard Worker 	    1) { /* Read Code size from file. */
819*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_READ_FAILED;
820*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR; /* Failed to read Code size. */
821*324bb76bSAndroid Build Coastguard Worker 	}
822*324bb76bSAndroid Build Coastguard Worker 	BitsPerPixel = CodeSize;
823*324bb76bSAndroid Build Coastguard Worker 
824*324bb76bSAndroid Build Coastguard Worker 	/* this can only happen on a severely malformed GIF */
825*324bb76bSAndroid Build Coastguard Worker 	if (BitsPerPixel > 8) {
826*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error =
827*324bb76bSAndroid Build Coastguard Worker 		    D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
828*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;          /* Failed to read Code size. */
829*324bb76bSAndroid Build Coastguard Worker 	}
830*324bb76bSAndroid Build Coastguard Worker 
831*324bb76bSAndroid Build Coastguard Worker 	Private->Buf[0] = 0; /* Input Buffer empty. */
832*324bb76bSAndroid Build Coastguard Worker 	Private->BitsPerPixel = BitsPerPixel;
833*324bb76bSAndroid Build Coastguard Worker 	Private->ClearCode = (1 << BitsPerPixel);
834*324bb76bSAndroid Build Coastguard Worker 	Private->EOFCode = Private->ClearCode + 1;
835*324bb76bSAndroid Build Coastguard Worker 	Private->RunningCode = Private->EOFCode + 1;
836*324bb76bSAndroid Build Coastguard Worker 	Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
837*324bb76bSAndroid Build Coastguard Worker 	Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
838*324bb76bSAndroid Build Coastguard Worker 	Private->StackPtr = 0; /* No pixels on the pixel stack. */
839*324bb76bSAndroid Build Coastguard Worker 	Private->LastCode = NO_SUCH_CODE;
840*324bb76bSAndroid Build Coastguard Worker 	Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
841*324bb76bSAndroid Build Coastguard Worker 	Private->CrntShiftDWord = 0;
842*324bb76bSAndroid Build Coastguard Worker 
843*324bb76bSAndroid Build Coastguard Worker 	Prefix = Private->Prefix;
844*324bb76bSAndroid Build Coastguard Worker 	for (i = 0; i <= LZ_MAX_CODE; i++) {
845*324bb76bSAndroid Build Coastguard Worker 		Prefix[i] = NO_SUCH_CODE;
846*324bb76bSAndroid Build Coastguard Worker 	}
847*324bb76bSAndroid Build Coastguard Worker 
848*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
849*324bb76bSAndroid Build Coastguard Worker }
850*324bb76bSAndroid Build Coastguard Worker 
851*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
852*324bb76bSAndroid Build Coastguard Worker  The LZ decompression routine:
853*324bb76bSAndroid Build Coastguard Worker  This version decompress the given GIF file into Line of length LineLen.
854*324bb76bSAndroid Build Coastguard Worker  This routine can be called few times (one per scan line, for example), in
855*324bb76bSAndroid Build Coastguard Worker  order the complete the whole image.
856*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifDecompressLine(GifFileType * GifFile,GifPixelType * Line,int LineLen)857*324bb76bSAndroid Build Coastguard Worker static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
858*324bb76bSAndroid Build Coastguard Worker                               int LineLen) {
859*324bb76bSAndroid Build Coastguard Worker 	int i = 0;
860*324bb76bSAndroid Build Coastguard Worker 	int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
861*324bb76bSAndroid Build Coastguard Worker 	GifByteType *Stack, *Suffix;
862*324bb76bSAndroid Build Coastguard Worker 	GifPrefixType *Prefix;
863*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
864*324bb76bSAndroid Build Coastguard Worker 
865*324bb76bSAndroid Build Coastguard Worker 	StackPtr = Private->StackPtr;
866*324bb76bSAndroid Build Coastguard Worker 	Prefix = Private->Prefix;
867*324bb76bSAndroid Build Coastguard Worker 	Suffix = Private->Suffix;
868*324bb76bSAndroid Build Coastguard Worker 	Stack = Private->Stack;
869*324bb76bSAndroid Build Coastguard Worker 	EOFCode = Private->EOFCode;
870*324bb76bSAndroid Build Coastguard Worker 	ClearCode = Private->ClearCode;
871*324bb76bSAndroid Build Coastguard Worker 	LastCode = Private->LastCode;
872*324bb76bSAndroid Build Coastguard Worker 
873*324bb76bSAndroid Build Coastguard Worker 	if (StackPtr > LZ_MAX_CODE) {
874*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
875*324bb76bSAndroid Build Coastguard Worker 	}
876*324bb76bSAndroid Build Coastguard Worker 
877*324bb76bSAndroid Build Coastguard Worker 	if (StackPtr != 0) {
878*324bb76bSAndroid Build Coastguard Worker 		/* Let pop the stack off before continueing to read the GIF
879*324bb76bSAndroid Build Coastguard Worker 		 * file: */
880*324bb76bSAndroid Build Coastguard Worker 		while (StackPtr != 0 && i < LineLen) {
881*324bb76bSAndroid Build Coastguard Worker 			Line[i++] = Stack[--StackPtr];
882*324bb76bSAndroid Build Coastguard Worker 		}
883*324bb76bSAndroid Build Coastguard Worker 	}
884*324bb76bSAndroid Build Coastguard Worker 
885*324bb76bSAndroid Build Coastguard Worker 	while (i < LineLen) { /* Decode LineLen items. */
886*324bb76bSAndroid Build Coastguard Worker 		if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) {
887*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
888*324bb76bSAndroid Build Coastguard Worker 		}
889*324bb76bSAndroid Build Coastguard Worker 
890*324bb76bSAndroid Build Coastguard Worker 		if (CrntCode == EOFCode) {
891*324bb76bSAndroid Build Coastguard Worker 			/* Note however that usually we will not be here as we
892*324bb76bSAndroid Build Coastguard Worker 			 * will stop decoding as soon as we got all the pixel,
893*324bb76bSAndroid Build Coastguard Worker 			 * or EOF code will not be read at all, and
894*324bb76bSAndroid Build Coastguard Worker 			 * DGifGetLine/Pixel clean everything.  */
895*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
896*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
897*324bb76bSAndroid Build Coastguard Worker 		} else if (CrntCode == ClearCode) {
898*324bb76bSAndroid Build Coastguard Worker 			/* We need to start over again: */
899*324bb76bSAndroid Build Coastguard Worker 			for (j = 0; j <= LZ_MAX_CODE; j++) {
900*324bb76bSAndroid Build Coastguard Worker 				Prefix[j] = NO_SUCH_CODE;
901*324bb76bSAndroid Build Coastguard Worker 			}
902*324bb76bSAndroid Build Coastguard Worker 			Private->RunningCode = Private->EOFCode + 1;
903*324bb76bSAndroid Build Coastguard Worker 			Private->RunningBits = Private->BitsPerPixel + 1;
904*324bb76bSAndroid Build Coastguard Worker 			Private->MaxCode1 = 1 << Private->RunningBits;
905*324bb76bSAndroid Build Coastguard Worker 			LastCode = Private->LastCode = NO_SUCH_CODE;
906*324bb76bSAndroid Build Coastguard Worker 		} else {
907*324bb76bSAndroid Build Coastguard Worker 			/* Its regular code - if in pixel range simply add it to
908*324bb76bSAndroid Build Coastguard Worker 			 * output stream, otherwise trace to codes linked list
909*324bb76bSAndroid Build Coastguard Worker 			 * until the prefix is in pixel range: */
910*324bb76bSAndroid Build Coastguard Worker 			if (CrntCode < ClearCode) {
911*324bb76bSAndroid Build Coastguard Worker 				/* This is simple - its pixel scalar, so add it
912*324bb76bSAndroid Build Coastguard Worker 				 * to output: */
913*324bb76bSAndroid Build Coastguard Worker 				Line[i++] = CrntCode;
914*324bb76bSAndroid Build Coastguard Worker 			} else {
915*324bb76bSAndroid Build Coastguard Worker 				/* Its a code to needed to be traced: trace the
916*324bb76bSAndroid Build Coastguard Worker 				 * linked list until the prefix is a pixel,
917*324bb76bSAndroid Build Coastguard Worker 				 * while pushing the suffix pixels on our stack.
918*324bb76bSAndroid Build Coastguard Worker 				 * If we done, pop the stack in reverse (thats
919*324bb76bSAndroid Build Coastguard Worker 				 * what stack is good for!) order to output.  */
920*324bb76bSAndroid Build Coastguard Worker 				if (Prefix[CrntCode] == NO_SUCH_CODE) {
921*324bb76bSAndroid Build Coastguard Worker 					CrntPrefix = LastCode;
922*324bb76bSAndroid Build Coastguard Worker 
923*324bb76bSAndroid Build Coastguard Worker 					/* Only allowed if CrntCode is exactly
924*324bb76bSAndroid Build Coastguard Worker 					 * the running code: In that case
925*324bb76bSAndroid Build Coastguard Worker 					 * CrntCode = XXXCode, CrntCode or the
926*324bb76bSAndroid Build Coastguard Worker 					 * prefix code is last code and the
927*324bb76bSAndroid Build Coastguard Worker 					 * suffix char is exactly the prefix of
928*324bb76bSAndroid Build Coastguard Worker 					 * last code! */
929*324bb76bSAndroid Build Coastguard Worker 					if (CrntCode ==
930*324bb76bSAndroid Build Coastguard Worker 					    Private->RunningCode - 2) {
931*324bb76bSAndroid Build Coastguard Worker 						Suffix[Private->RunningCode -
932*324bb76bSAndroid Build Coastguard Worker 						       2] = Stack[StackPtr++] =
933*324bb76bSAndroid Build Coastguard Worker 						    DGifGetPrefixChar(
934*324bb76bSAndroid Build Coastguard Worker 						        Prefix, LastCode,
935*324bb76bSAndroid Build Coastguard Worker 						        ClearCode);
936*324bb76bSAndroid Build Coastguard Worker 					} else {
937*324bb76bSAndroid Build Coastguard Worker 						Suffix[Private->RunningCode -
938*324bb76bSAndroid Build Coastguard Worker 						       2] = Stack[StackPtr++] =
939*324bb76bSAndroid Build Coastguard Worker 						    DGifGetPrefixChar(
940*324bb76bSAndroid Build Coastguard Worker 						        Prefix, CrntCode,
941*324bb76bSAndroid Build Coastguard Worker 						        ClearCode);
942*324bb76bSAndroid Build Coastguard Worker 					}
943*324bb76bSAndroid Build Coastguard Worker 				} else {
944*324bb76bSAndroid Build Coastguard Worker 					CrntPrefix = CrntCode;
945*324bb76bSAndroid Build Coastguard Worker 				}
946*324bb76bSAndroid Build Coastguard Worker 
947*324bb76bSAndroid Build Coastguard Worker 				/* Now (if image is O.K.) we should not get a
948*324bb76bSAndroid Build Coastguard Worker 				 * NO_SUCH_CODE during the trace. As we might
949*324bb76bSAndroid Build Coastguard Worker 				 * loop forever, in case of defective image, we
950*324bb76bSAndroid Build Coastguard Worker 				 * use StackPtr as loop counter and stop before
951*324bb76bSAndroid Build Coastguard Worker 				 * overflowing Stack[]. */
952*324bb76bSAndroid Build Coastguard Worker 				while (StackPtr < LZ_MAX_CODE &&
953*324bb76bSAndroid Build Coastguard Worker 				       CrntPrefix > ClearCode &&
954*324bb76bSAndroid Build Coastguard Worker 				       CrntPrefix <= LZ_MAX_CODE) {
955*324bb76bSAndroid Build Coastguard Worker 					Stack[StackPtr++] = Suffix[CrntPrefix];
956*324bb76bSAndroid Build Coastguard Worker 					CrntPrefix = Prefix[CrntPrefix];
957*324bb76bSAndroid Build Coastguard Worker 				}
958*324bb76bSAndroid Build Coastguard Worker 				if (StackPtr >= LZ_MAX_CODE ||
959*324bb76bSAndroid Build Coastguard Worker 				    CrntPrefix > LZ_MAX_CODE) {
960*324bb76bSAndroid Build Coastguard Worker 					GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
961*324bb76bSAndroid Build Coastguard Worker 					return GIF_ERROR;
962*324bb76bSAndroid Build Coastguard Worker 				}
963*324bb76bSAndroid Build Coastguard Worker 				/* Push the last character on stack: */
964*324bb76bSAndroid Build Coastguard Worker 				Stack[StackPtr++] = CrntPrefix;
965*324bb76bSAndroid Build Coastguard Worker 
966*324bb76bSAndroid Build Coastguard Worker 				/* Now lets pop all the stack into output: */
967*324bb76bSAndroid Build Coastguard Worker 				while (StackPtr != 0 && i < LineLen) {
968*324bb76bSAndroid Build Coastguard Worker 					Line[i++] = Stack[--StackPtr];
969*324bb76bSAndroid Build Coastguard Worker 				}
970*324bb76bSAndroid Build Coastguard Worker 			}
971*324bb76bSAndroid Build Coastguard Worker 			if (LastCode != NO_SUCH_CODE &&
972*324bb76bSAndroid Build Coastguard Worker 			    Private->RunningCode - 2 < (LZ_MAX_CODE + 1) &&
973*324bb76bSAndroid Build Coastguard Worker 			    Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
974*324bb76bSAndroid Build Coastguard Worker 				Prefix[Private->RunningCode - 2] = LastCode;
975*324bb76bSAndroid Build Coastguard Worker 
976*324bb76bSAndroid Build Coastguard Worker 				if (CrntCode == Private->RunningCode - 2) {
977*324bb76bSAndroid Build Coastguard Worker 					/* Only allowed if CrntCode is exactly
978*324bb76bSAndroid Build Coastguard Worker 					 * the running code: In that case
979*324bb76bSAndroid Build Coastguard Worker 					 * CrntCode = XXXCode, CrntCode or the
980*324bb76bSAndroid Build Coastguard Worker 					 * prefix code is last code and the
981*324bb76bSAndroid Build Coastguard Worker 					 * suffix char is exactly the prefix of
982*324bb76bSAndroid Build Coastguard Worker 					 * last code! */
983*324bb76bSAndroid Build Coastguard Worker 					Suffix[Private->RunningCode - 2] =
984*324bb76bSAndroid Build Coastguard Worker 					    DGifGetPrefixChar(Prefix, LastCode,
985*324bb76bSAndroid Build Coastguard Worker 					                      ClearCode);
986*324bb76bSAndroid Build Coastguard Worker 				} else {
987*324bb76bSAndroid Build Coastguard Worker 					Suffix[Private->RunningCode - 2] =
988*324bb76bSAndroid Build Coastguard Worker 					    DGifGetPrefixChar(Prefix, CrntCode,
989*324bb76bSAndroid Build Coastguard Worker 					                      ClearCode);
990*324bb76bSAndroid Build Coastguard Worker 				}
991*324bb76bSAndroid Build Coastguard Worker 			}
992*324bb76bSAndroid Build Coastguard Worker 			LastCode = CrntCode;
993*324bb76bSAndroid Build Coastguard Worker 		}
994*324bb76bSAndroid Build Coastguard Worker 	}
995*324bb76bSAndroid Build Coastguard Worker 
996*324bb76bSAndroid Build Coastguard Worker 	Private->LastCode = LastCode;
997*324bb76bSAndroid Build Coastguard Worker 	Private->StackPtr = StackPtr;
998*324bb76bSAndroid Build Coastguard Worker 
999*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
1000*324bb76bSAndroid Build Coastguard Worker }
1001*324bb76bSAndroid Build Coastguard Worker 
1002*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
1003*324bb76bSAndroid Build Coastguard Worker  Routine to trace the Prefixes linked list until we get a prefix which is
1004*324bb76bSAndroid Build Coastguard Worker  not code, but a pixel value (less than ClearCode). Returns that pixel value.
1005*324bb76bSAndroid Build Coastguard Worker  If image is defective, we might loop here forever, so we limit the loops to
1006*324bb76bSAndroid Build Coastguard Worker  the maximum possible if image O.k. - LZ_MAX_CODE times.
1007*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetPrefixChar(const GifPrefixType * Prefix,int Code,int ClearCode)1008*324bb76bSAndroid Build Coastguard Worker static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code,
1009*324bb76bSAndroid Build Coastguard Worker                              int ClearCode) {
1010*324bb76bSAndroid Build Coastguard Worker 	int i = 0;
1011*324bb76bSAndroid Build Coastguard Worker 
1012*324bb76bSAndroid Build Coastguard Worker 	while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
1013*324bb76bSAndroid Build Coastguard Worker 		if (Code > LZ_MAX_CODE) {
1014*324bb76bSAndroid Build Coastguard Worker 			return NO_SUCH_CODE;
1015*324bb76bSAndroid Build Coastguard Worker 		}
1016*324bb76bSAndroid Build Coastguard Worker 		Code = Prefix[Code];
1017*324bb76bSAndroid Build Coastguard Worker 	}
1018*324bb76bSAndroid Build Coastguard Worker 	return Code;
1019*324bb76bSAndroid Build Coastguard Worker }
1020*324bb76bSAndroid Build Coastguard Worker 
1021*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
1022*324bb76bSAndroid Build Coastguard Worker  Interface for accessing the LZ codes directly. Set Code to the real code
1023*324bb76bSAndroid Build Coastguard Worker  (12bits), or to -1 if EOF code is returned.
1024*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifGetLZCodes(GifFileType * GifFile,int * Code)1025*324bb76bSAndroid Build Coastguard Worker int DGifGetLZCodes(GifFileType *GifFile, int *Code) {
1026*324bb76bSAndroid Build Coastguard Worker 	GifByteType *CodeBlock;
1027*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1028*324bb76bSAndroid Build Coastguard Worker 
1029*324bb76bSAndroid Build Coastguard Worker 	if (!IS_READABLE(Private)) {
1030*324bb76bSAndroid Build Coastguard Worker 		/* This file was NOT open for reading: */
1031*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NOT_READABLE;
1032*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
1033*324bb76bSAndroid Build Coastguard Worker 	}
1034*324bb76bSAndroid Build Coastguard Worker 
1035*324bb76bSAndroid Build Coastguard Worker 	if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) {
1036*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
1037*324bb76bSAndroid Build Coastguard Worker 	}
1038*324bb76bSAndroid Build Coastguard Worker 
1039*324bb76bSAndroid Build Coastguard Worker 	if (*Code == Private->EOFCode) {
1040*324bb76bSAndroid Build Coastguard Worker 		/* Skip rest of codes (hopefully only NULL terminating block):
1041*324bb76bSAndroid Build Coastguard Worker 		 */
1042*324bb76bSAndroid Build Coastguard Worker 		do {
1043*324bb76bSAndroid Build Coastguard Worker 			if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) {
1044*324bb76bSAndroid Build Coastguard Worker 				return GIF_ERROR;
1045*324bb76bSAndroid Build Coastguard Worker 			}
1046*324bb76bSAndroid Build Coastguard Worker 		} while (CodeBlock != NULL);
1047*324bb76bSAndroid Build Coastguard Worker 
1048*324bb76bSAndroid Build Coastguard Worker 		*Code = -1;
1049*324bb76bSAndroid Build Coastguard Worker 	} else if (*Code == Private->ClearCode) {
1050*324bb76bSAndroid Build Coastguard Worker 		/* We need to start over again: */
1051*324bb76bSAndroid Build Coastguard Worker 		Private->RunningCode = Private->EOFCode + 1;
1052*324bb76bSAndroid Build Coastguard Worker 		Private->RunningBits = Private->BitsPerPixel + 1;
1053*324bb76bSAndroid Build Coastguard Worker 		Private->MaxCode1 = 1 << Private->RunningBits;
1054*324bb76bSAndroid Build Coastguard Worker 	}
1055*324bb76bSAndroid Build Coastguard Worker 
1056*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
1057*324bb76bSAndroid Build Coastguard Worker }
1058*324bb76bSAndroid Build Coastguard Worker 
1059*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
1060*324bb76bSAndroid Build Coastguard Worker  The LZ decompression input routine:
1061*324bb76bSAndroid Build Coastguard Worker  This routine is responsable for the decompression of the bit stream from
1062*324bb76bSAndroid Build Coastguard Worker  8 bits (bytes) packets, into the real codes.
1063*324bb76bSAndroid Build Coastguard Worker  Returns GIF_OK if read successfully.
1064*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifDecompressInput(GifFileType * GifFile,int * Code)1065*324bb76bSAndroid Build Coastguard Worker static int DGifDecompressInput(GifFileType *GifFile, int *Code) {
1066*324bb76bSAndroid Build Coastguard Worker 	static const unsigned short CodeMasks[] = {
1067*324bb76bSAndroid Build Coastguard Worker 	    0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f,
1068*324bb76bSAndroid Build Coastguard Worker 	    0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff};
1069*324bb76bSAndroid Build Coastguard Worker 
1070*324bb76bSAndroid Build Coastguard Worker 	GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1071*324bb76bSAndroid Build Coastguard Worker 
1072*324bb76bSAndroid Build Coastguard Worker 	GifByteType NextByte;
1073*324bb76bSAndroid Build Coastguard Worker 
1074*324bb76bSAndroid Build Coastguard Worker 	/* The image can't contain more than LZ_BITS per code. */
1075*324bb76bSAndroid Build Coastguard Worker 	if (Private->RunningBits > LZ_BITS) {
1076*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1077*324bb76bSAndroid Build Coastguard Worker 		return GIF_ERROR;
1078*324bb76bSAndroid Build Coastguard Worker 	}
1079*324bb76bSAndroid Build Coastguard Worker 
1080*324bb76bSAndroid Build Coastguard Worker 	while (Private->CrntShiftState < Private->RunningBits) {
1081*324bb76bSAndroid Build Coastguard Worker 		/* Needs to get more bytes from input stream for next code: */
1082*324bb76bSAndroid Build Coastguard Worker 		if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) ==
1083*324bb76bSAndroid Build Coastguard Worker 		    GIF_ERROR) {
1084*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
1085*324bb76bSAndroid Build Coastguard Worker 		}
1086*324bb76bSAndroid Build Coastguard Worker 		Private->CrntShiftDWord |= ((unsigned long)NextByte)
1087*324bb76bSAndroid Build Coastguard Worker 		                           << Private->CrntShiftState;
1088*324bb76bSAndroid Build Coastguard Worker 		Private->CrntShiftState += 8;
1089*324bb76bSAndroid Build Coastguard Worker 	}
1090*324bb76bSAndroid Build Coastguard Worker 	*Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1091*324bb76bSAndroid Build Coastguard Worker 
1092*324bb76bSAndroid Build Coastguard Worker 	Private->CrntShiftDWord >>= Private->RunningBits;
1093*324bb76bSAndroid Build Coastguard Worker 	Private->CrntShiftState -= Private->RunningBits;
1094*324bb76bSAndroid Build Coastguard Worker 
1095*324bb76bSAndroid Build Coastguard Worker 	/* If code cannot fit into RunningBits bits, must raise its size. Note
1096*324bb76bSAndroid Build Coastguard Worker 	 * however that codes above 4095 are used for special signaling.
1097*324bb76bSAndroid Build Coastguard Worker 	 * If we're using LZ_BITS bits already and we're at the max code, just
1098*324bb76bSAndroid Build Coastguard Worker 	 * keep using the table as it is, don't increment Private->RunningCode.
1099*324bb76bSAndroid Build Coastguard Worker 	 */
1100*324bb76bSAndroid Build Coastguard Worker 	if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1101*324bb76bSAndroid Build Coastguard Worker 	    ++Private->RunningCode > Private->MaxCode1 &&
1102*324bb76bSAndroid Build Coastguard Worker 	    Private->RunningBits < LZ_BITS) {
1103*324bb76bSAndroid Build Coastguard Worker 		Private->MaxCode1 <<= 1;
1104*324bb76bSAndroid Build Coastguard Worker 		Private->RunningBits++;
1105*324bb76bSAndroid Build Coastguard Worker 	}
1106*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
1107*324bb76bSAndroid Build Coastguard Worker }
1108*324bb76bSAndroid Build Coastguard Worker 
1109*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
1110*324bb76bSAndroid Build Coastguard Worker  This routines read one GIF data block at a time and buffers it internally
1111*324bb76bSAndroid Build Coastguard Worker  so that the decompression routine could access it.
1112*324bb76bSAndroid Build Coastguard Worker  The routine returns the next byte from its internal buffer (or read next
1113*324bb76bSAndroid Build Coastguard Worker  block in if buffer empty) and returns GIF_OK if succesful.
1114*324bb76bSAndroid Build Coastguard Worker ******************************************************************************/
DGifBufferedInput(GifFileType * GifFile,GifByteType * Buf,GifByteType * NextByte)1115*324bb76bSAndroid Build Coastguard Worker static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
1116*324bb76bSAndroid Build Coastguard Worker                              GifByteType *NextByte) {
1117*324bb76bSAndroid Build Coastguard Worker 	if (Buf[0] == 0) {
1118*324bb76bSAndroid Build Coastguard Worker 		/* Needs to read the next buffer - this one is empty: */
1119*324bb76bSAndroid Build Coastguard Worker 		/* coverity[check_return] */
1120*324bb76bSAndroid Build Coastguard Worker 		if (InternalRead(GifFile, Buf, 1) != 1) {
1121*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_READ_FAILED;
1122*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
1123*324bb76bSAndroid Build Coastguard Worker 		}
1124*324bb76bSAndroid Build Coastguard Worker 		/* There shouldn't be any empty data blocks here as the LZW spec
1125*324bb76bSAndroid Build Coastguard Worker 		 * says the LZW termination code should come first.  Therefore
1126*324bb76bSAndroid Build Coastguard Worker 		 * we shouldn't be inside this routine at that point.
1127*324bb76bSAndroid Build Coastguard Worker 		 */
1128*324bb76bSAndroid Build Coastguard Worker 		if (Buf[0] == 0) {
1129*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1130*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
1131*324bb76bSAndroid Build Coastguard Worker 		}
1132*324bb76bSAndroid Build Coastguard Worker 		if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1133*324bb76bSAndroid Build Coastguard Worker 			GifFile->Error = D_GIF_ERR_READ_FAILED;
1134*324bb76bSAndroid Build Coastguard Worker 			return GIF_ERROR;
1135*324bb76bSAndroid Build Coastguard Worker 		}
1136*324bb76bSAndroid Build Coastguard Worker 		*NextByte = Buf[1];
1137*324bb76bSAndroid Build Coastguard Worker 		Buf[1] = 2; /* We use now the second place as last char read! */
1138*324bb76bSAndroid Build Coastguard Worker 		Buf[0]--;
1139*324bb76bSAndroid Build Coastguard Worker 	} else {
1140*324bb76bSAndroid Build Coastguard Worker 		*NextByte = Buf[Buf[1]++];
1141*324bb76bSAndroid Build Coastguard Worker 		Buf[0]--;
1142*324bb76bSAndroid Build Coastguard Worker 	}
1143*324bb76bSAndroid Build Coastguard Worker 
1144*324bb76bSAndroid Build Coastguard Worker 	return GIF_OK;
1145*324bb76bSAndroid Build Coastguard Worker }
1146*324bb76bSAndroid Build Coastguard Worker 
1147*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
1148*324bb76bSAndroid Build Coastguard Worker  This routine is called in case of error during parsing image. We need to
1149*324bb76bSAndroid Build Coastguard Worker  decrease image counter and reallocate memory for saved images. Not decreasing
1150*324bb76bSAndroid Build Coastguard Worker  ImageCount may lead to null pointer dereference, because the last element in
1151*324bb76bSAndroid Build Coastguard Worker  SavedImages may point to the spoilt image and null pointer buffers.
1152*324bb76bSAndroid Build Coastguard Worker *******************************************************************************/
DGifDecreaseImageCounter(GifFileType * GifFile)1153*324bb76bSAndroid Build Coastguard Worker void DGifDecreaseImageCounter(GifFileType *GifFile) {
1154*324bb76bSAndroid Build Coastguard Worker 	GifFile->ImageCount--;
1155*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) {
1156*324bb76bSAndroid Build Coastguard Worker 		free(GifFile->SavedImages[GifFile->ImageCount].RasterBits);
1157*324bb76bSAndroid Build Coastguard Worker 	}
1158*324bb76bSAndroid Build Coastguard Worker 
1159*324bb76bSAndroid Build Coastguard Worker 	// Realloc array according to the new image counter.
1160*324bb76bSAndroid Build Coastguard Worker 	SavedImage *correct_saved_images = (SavedImage *)reallocarray(
1161*324bb76bSAndroid Build Coastguard Worker 	    GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage));
1162*324bb76bSAndroid Build Coastguard Worker 	if (correct_saved_images != NULL) {
1163*324bb76bSAndroid Build Coastguard Worker 		GifFile->SavedImages = correct_saved_images;
1164*324bb76bSAndroid Build Coastguard Worker 	}
1165*324bb76bSAndroid Build Coastguard Worker }
1166*324bb76bSAndroid Build Coastguard Worker 
1167*324bb76bSAndroid Build Coastguard Worker /******************************************************************************
1168*324bb76bSAndroid Build Coastguard Worker  This routine reads an entire GIF into core, hanging all its state info off
1169*324bb76bSAndroid Build Coastguard Worker  the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
1170*324bb76bSAndroid Build Coastguard Worker  first to initialize I/O.  Its inverse is EGifSpew().
1171*324bb76bSAndroid Build Coastguard Worker *******************************************************************************/
DGifSlurp(GifFileType * GifFile)1172*324bb76bSAndroid Build Coastguard Worker int DGifSlurp(GifFileType *GifFile) {
1173*324bb76bSAndroid Build Coastguard Worker 	size_t ImageSize;
1174*324bb76bSAndroid Build Coastguard Worker 	GifRecordType RecordType;
1175*324bb76bSAndroid Build Coastguard Worker 	SavedImage *sp;
1176*324bb76bSAndroid Build Coastguard Worker 	GifByteType *ExtData;
1177*324bb76bSAndroid Build Coastguard Worker 	int ExtFunction;
1178*324bb76bSAndroid Build Coastguard Worker 
1179*324bb76bSAndroid Build Coastguard Worker 	GifFile->ExtensionBlocks = NULL;
1180*324bb76bSAndroid Build Coastguard Worker 	GifFile->ExtensionBlockCount = 0;
1181*324bb76bSAndroid Build Coastguard Worker 
1182*324bb76bSAndroid Build Coastguard Worker 	do {
1183*324bb76bSAndroid Build Coastguard Worker 		if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
1184*324bb76bSAndroid Build Coastguard Worker 			return (GIF_ERROR);
1185*324bb76bSAndroid Build Coastguard Worker 		}
1186*324bb76bSAndroid Build Coastguard Worker 
1187*324bb76bSAndroid Build Coastguard Worker 		switch (RecordType) {
1188*324bb76bSAndroid Build Coastguard Worker 		case IMAGE_DESC_RECORD_TYPE:
1189*324bb76bSAndroid Build Coastguard Worker 			if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
1190*324bb76bSAndroid Build Coastguard Worker 				return (GIF_ERROR);
1191*324bb76bSAndroid Build Coastguard Worker 			}
1192*324bb76bSAndroid Build Coastguard Worker 
1193*324bb76bSAndroid Build Coastguard Worker 			sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1194*324bb76bSAndroid Build Coastguard Worker 			/* Allocate memory for the image */
1195*324bb76bSAndroid Build Coastguard Worker 			if (sp->ImageDesc.Width <= 0 ||
1196*324bb76bSAndroid Build Coastguard Worker 			    sp->ImageDesc.Height <= 0 ||
1197*324bb76bSAndroid Build Coastguard Worker 			    sp->ImageDesc.Width >
1198*324bb76bSAndroid Build Coastguard Worker 			        (INT_MAX / sp->ImageDesc.Height)) {
1199*324bb76bSAndroid Build Coastguard Worker 				DGifDecreaseImageCounter(GifFile);
1200*324bb76bSAndroid Build Coastguard Worker 				return GIF_ERROR;
1201*324bb76bSAndroid Build Coastguard Worker 			}
1202*324bb76bSAndroid Build Coastguard Worker 			ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1203*324bb76bSAndroid Build Coastguard Worker 
1204*324bb76bSAndroid Build Coastguard Worker 			if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1205*324bb76bSAndroid Build Coastguard Worker 				DGifDecreaseImageCounter(GifFile);
1206*324bb76bSAndroid Build Coastguard Worker 				return GIF_ERROR;
1207*324bb76bSAndroid Build Coastguard Worker 			}
1208*324bb76bSAndroid Build Coastguard Worker 			sp->RasterBits = (unsigned char *)reallocarray(
1209*324bb76bSAndroid Build Coastguard Worker 			    NULL, ImageSize, sizeof(GifPixelType));
1210*324bb76bSAndroid Build Coastguard Worker 
1211*324bb76bSAndroid Build Coastguard Worker 			if (sp->RasterBits == NULL) {
1212*324bb76bSAndroid Build Coastguard Worker 				DGifDecreaseImageCounter(GifFile);
1213*324bb76bSAndroid Build Coastguard Worker 				return GIF_ERROR;
1214*324bb76bSAndroid Build Coastguard Worker 			}
1215*324bb76bSAndroid Build Coastguard Worker 
1216*324bb76bSAndroid Build Coastguard Worker 			if (sp->ImageDesc.Interlace) {
1217*324bb76bSAndroid Build Coastguard Worker 				int i, j;
1218*324bb76bSAndroid Build Coastguard Worker 				/*
1219*324bb76bSAndroid Build Coastguard Worker 				 * The way an interlaced image should be read -
1220*324bb76bSAndroid Build Coastguard Worker 				 * offsets and jumps...
1221*324bb76bSAndroid Build Coastguard Worker 				 */
1222*324bb76bSAndroid Build Coastguard Worker 				static const int InterlacedOffset[] = {0, 4, 2,
1223*324bb76bSAndroid Build Coastguard Worker 				                                       1};
1224*324bb76bSAndroid Build Coastguard Worker 				static const int InterlacedJumps[] = {8, 8, 4,
1225*324bb76bSAndroid Build Coastguard Worker 				                                      2};
1226*324bb76bSAndroid Build Coastguard Worker 				/* Need to perform 4 passes on the image */
1227*324bb76bSAndroid Build Coastguard Worker 				for (i = 0; i < 4; i++) {
1228*324bb76bSAndroid Build Coastguard Worker 					for (j = InterlacedOffset[i];
1229*324bb76bSAndroid Build Coastguard Worker 					     j < sp->ImageDesc.Height;
1230*324bb76bSAndroid Build Coastguard Worker 					     j += InterlacedJumps[i]) {
1231*324bb76bSAndroid Build Coastguard Worker 						if (DGifGetLine(
1232*324bb76bSAndroid Build Coastguard Worker 						        GifFile,
1233*324bb76bSAndroid Build Coastguard Worker 						        sp->RasterBits +
1234*324bb76bSAndroid Build Coastguard Worker 						            j * sp->ImageDesc
1235*324bb76bSAndroid Build Coastguard Worker 						                    .Width,
1236*324bb76bSAndroid Build Coastguard Worker 						        sp->ImageDesc.Width) ==
1237*324bb76bSAndroid Build Coastguard Worker 						    GIF_ERROR) {
1238*324bb76bSAndroid Build Coastguard Worker 							DGifDecreaseImageCounter(
1239*324bb76bSAndroid Build Coastguard Worker 							    GifFile);
1240*324bb76bSAndroid Build Coastguard Worker 							return GIF_ERROR;
1241*324bb76bSAndroid Build Coastguard Worker 						}
1242*324bb76bSAndroid Build Coastguard Worker 					}
1243*324bb76bSAndroid Build Coastguard Worker 				}
1244*324bb76bSAndroid Build Coastguard Worker 			} else {
1245*324bb76bSAndroid Build Coastguard Worker 				if (DGifGetLine(GifFile, sp->RasterBits,
1246*324bb76bSAndroid Build Coastguard Worker 				                ImageSize) == GIF_ERROR) {
1247*324bb76bSAndroid Build Coastguard Worker 					DGifDecreaseImageCounter(GifFile);
1248*324bb76bSAndroid Build Coastguard Worker 					return GIF_ERROR;
1249*324bb76bSAndroid Build Coastguard Worker 				}
1250*324bb76bSAndroid Build Coastguard Worker 			}
1251*324bb76bSAndroid Build Coastguard Worker 
1252*324bb76bSAndroid Build Coastguard Worker 			if (GifFile->ExtensionBlocks) {
1253*324bb76bSAndroid Build Coastguard Worker 				sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1254*324bb76bSAndroid Build Coastguard Worker 				sp->ExtensionBlockCount =
1255*324bb76bSAndroid Build Coastguard Worker 				    GifFile->ExtensionBlockCount;
1256*324bb76bSAndroid Build Coastguard Worker 
1257*324bb76bSAndroid Build Coastguard Worker 				GifFile->ExtensionBlocks = NULL;
1258*324bb76bSAndroid Build Coastguard Worker 				GifFile->ExtensionBlockCount = 0;
1259*324bb76bSAndroid Build Coastguard Worker 			}
1260*324bb76bSAndroid Build Coastguard Worker 			break;
1261*324bb76bSAndroid Build Coastguard Worker 
1262*324bb76bSAndroid Build Coastguard Worker 		case EXTENSION_RECORD_TYPE:
1263*324bb76bSAndroid Build Coastguard Worker 			if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) ==
1264*324bb76bSAndroid Build Coastguard Worker 			    GIF_ERROR) {
1265*324bb76bSAndroid Build Coastguard Worker 				return (GIF_ERROR);
1266*324bb76bSAndroid Build Coastguard Worker 			}
1267*324bb76bSAndroid Build Coastguard Worker 			/* Create an extension block with our data */
1268*324bb76bSAndroid Build Coastguard Worker 			if (ExtData != NULL) {
1269*324bb76bSAndroid Build Coastguard Worker 				if (GifAddExtensionBlock(
1270*324bb76bSAndroid Build Coastguard Worker 				        &GifFile->ExtensionBlockCount,
1271*324bb76bSAndroid Build Coastguard Worker 				        &GifFile->ExtensionBlocks, ExtFunction,
1272*324bb76bSAndroid Build Coastguard Worker 				        ExtData[0], &ExtData[1]) == GIF_ERROR) {
1273*324bb76bSAndroid Build Coastguard Worker 					return (GIF_ERROR);
1274*324bb76bSAndroid Build Coastguard Worker 				}
1275*324bb76bSAndroid Build Coastguard Worker 			}
1276*324bb76bSAndroid Build Coastguard Worker 			for (;;) {
1277*324bb76bSAndroid Build Coastguard Worker 				if (DGifGetExtensionNext(GifFile, &ExtData) ==
1278*324bb76bSAndroid Build Coastguard Worker 				    GIF_ERROR) {
1279*324bb76bSAndroid Build Coastguard Worker 					return (GIF_ERROR);
1280*324bb76bSAndroid Build Coastguard Worker 				}
1281*324bb76bSAndroid Build Coastguard Worker 				if (ExtData == NULL) {
1282*324bb76bSAndroid Build Coastguard Worker 					break;
1283*324bb76bSAndroid Build Coastguard Worker 				}
1284*324bb76bSAndroid Build Coastguard Worker 				/* Continue the extension block */
1285*324bb76bSAndroid Build Coastguard Worker 				if (GifAddExtensionBlock(
1286*324bb76bSAndroid Build Coastguard Worker 				        &GifFile->ExtensionBlockCount,
1287*324bb76bSAndroid Build Coastguard Worker 				        &GifFile->ExtensionBlocks,
1288*324bb76bSAndroid Build Coastguard Worker 				        CONTINUE_EXT_FUNC_CODE, ExtData[0],
1289*324bb76bSAndroid Build Coastguard Worker 				        &ExtData[1]) == GIF_ERROR) {
1290*324bb76bSAndroid Build Coastguard Worker 					return (GIF_ERROR);
1291*324bb76bSAndroid Build Coastguard Worker 				}
1292*324bb76bSAndroid Build Coastguard Worker 			}
1293*324bb76bSAndroid Build Coastguard Worker 			break;
1294*324bb76bSAndroid Build Coastguard Worker 
1295*324bb76bSAndroid Build Coastguard Worker 		case TERMINATE_RECORD_TYPE:
1296*324bb76bSAndroid Build Coastguard Worker 			break;
1297*324bb76bSAndroid Build Coastguard Worker 
1298*324bb76bSAndroid Build Coastguard Worker 		default: /* Should be trapped by DGifGetRecordType */
1299*324bb76bSAndroid Build Coastguard Worker 			break;
1300*324bb76bSAndroid Build Coastguard Worker 		}
1301*324bb76bSAndroid Build Coastguard Worker 	} while (RecordType != TERMINATE_RECORD_TYPE);
1302*324bb76bSAndroid Build Coastguard Worker 
1303*324bb76bSAndroid Build Coastguard Worker 	/* Sanity check for corrupted file */
1304*324bb76bSAndroid Build Coastguard Worker 	if (GifFile->ImageCount == 0) {
1305*324bb76bSAndroid Build Coastguard Worker 		GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1306*324bb76bSAndroid Build Coastguard Worker 		return (GIF_ERROR);
1307*324bb76bSAndroid Build Coastguard Worker 	}
1308*324bb76bSAndroid Build Coastguard Worker 
1309*324bb76bSAndroid Build Coastguard Worker 	return (GIF_OK);
1310*324bb76bSAndroid Build Coastguard Worker }
1311*324bb76bSAndroid Build Coastguard Worker 
1312*324bb76bSAndroid Build Coastguard Worker /* end */
1313