Coverage Report

Created: 2024-05-04 12:45

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