Coverage Report

Created: 2023-03-26 07:33

/src/giflib-code/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
315k
#define UNSIGNED_LITTLE_ENDIAN(lo, hi)  ((lo) | ((hi) << 8))
31
32
/* avoid extra function call in case we use fread (TVT) */
33
1.18M
static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
34
    //fprintf(stderr, "### Read: %d\n", len);
35
1.18M
    return 
36
1.18M
  (((GifFilePrivateType*)gif->Private)->Read ?
37
1.18M
   ((GifFilePrivateType*)gif->Private)->Read(gif,buf,len) : 
38
1.18M
   fread(buf,1,len,((GifFilePrivateType*)gif->Private)->File));
39
1.18M
}
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
2.22k
{
167
2.22k
    char Buf[GIF_STAMP_LEN + 1];
168
2.22k
    GifFileType *GifFile;
169
2.22k
    GifFilePrivateType *Private;
170
171
2.22k
    GifFile = (GifFileType *)malloc(sizeof(GifFileType));
172
2.22k
    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
2.22k
    memset(GifFile, '\0', sizeof(GifFileType));
179
180
    /* Belt and suspenders, in case the null pointer isn't zero */
181
2.22k
    GifFile->SavedImages = NULL;
182
2.22k
    GifFile->SColorMap = NULL;
183
184
2.22k
    Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
185
2.22k
    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
2.22k
    /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
192
193
2.22k
    GifFile->Private = (void *)Private;
194
2.22k
    Private->FileHandle = 0;
195
2.22k
    Private->File = NULL;
196
2.22k
    Private->FileState = FILE_STATE_READ;
197
198
2.22k
    Private->Read = readFunc;    /* TVT */
199
2.22k
    GifFile->UserData = userData;    /* TVT */
200
201
    /* Lets see if this is a GIF file: */
202
    /* coverity[check_return] */
203
2.22k
    if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
204
4
        if (Error != NULL)
205
4
      *Error = D_GIF_ERR_READ_FAILED;
206
4
        free((char *)Private);
207
4
        free((char *)GifFile);
208
4
        return NULL;
209
4
    }
210
211
    /* Check for GIF prefix at start of file */
212
2.21k
    Buf[GIF_STAMP_LEN] = '\0';
213
2.21k
    if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
214
34
        if (Error != NULL)
215
34
      *Error = D_GIF_ERR_NOT_GIF_FILE;
216
34
        free((char *)Private);
217
34
        free((char *)GifFile);
218
34
        return NULL;
219
34
    }
220
221
2.18k
    if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
222
45
        free((char *)Private);
223
45
        free((char *)GifFile);
224
45
        if (Error != NULL)
225
45
      *Error = D_GIF_ERR_NO_SCRN_DSCR;
226
45
        return NULL;
227
45
    }
228
229
2.13k
    GifFile->Error = 0;
230
231
    /* What version of GIF? */
232
2.13k
    Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
233
234
2.13k
    return GifFile;
235
2.18k
}
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
2.18k
{
244
2.18k
    int BitsPerPixel;
245
2.18k
    bool SortFlag;
246
2.18k
    GifByteType Buf[3];
247
2.18k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
248
249
2.18k
    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
2.18k
    if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
257
2.18k
        DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
258
4
        return GIF_ERROR;
259
260
2.18k
    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
2.17k
    GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
267
2.17k
    SortFlag = (Buf[0] & 0x08) != 0;
268
2.17k
    BitsPerPixel = (Buf[0] & 0x07) + 1;
269
2.17k
    GifFile->SBackGroundColor = Buf[1];
270
2.17k
    GifFile->AspectByte = Buf[2]; 
271
2.17k
    if (Buf[0] & 0x80) {    /* Do we have global color map? */
272
131
  int i;
273
274
131
        GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
275
131
        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
131
  GifFile->SColorMap->SortFlag = SortFlag;
282
1.40k
        for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
283
      /* coverity[check_return] */
284
1.30k
            if (InternalRead(GifFile, Buf, 3) != 3) {
285
37
                GifFreeMapObject(GifFile->SColorMap);
286
37
                GifFile->SColorMap = NULL;
287
37
                GifFile->Error = D_GIF_ERR_READ_FAILED;
288
37
                return GIF_ERROR;
289
37
            }
290
1.27k
            GifFile->SColorMap->Colors[i].Red = Buf[0];
291
1.27k
            GifFile->SColorMap->Colors[i].Green = Buf[1];
292
1.27k
            GifFile->SColorMap->Colors[i].Blue = Buf[2];
293
1.27k
        }
294
2.04k
    } else {
295
2.04k
        GifFile->SColorMap = NULL;
296
2.04k
    }
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
2.13k
    return GIF_OK;
304
2.17k
}
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
85.0k
{
323
85.0k
    GifByteType Buf;
324
85.0k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
325
326
85.0k
    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
85.0k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
334
80
        GifFile->Error = D_GIF_ERR_READ_FAILED;
335
80
        return GIF_ERROR;
336
80
    }
337
338
    //fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
339
84.9k
    switch (Buf) {
340
77.5k
      case DESCRIPTOR_INTRODUCER:
341
77.5k
          *Type = IMAGE_DESC_RECORD_TYPE;
342
77.5k
          break;
343
6.96k
      case EXTENSION_INTRODUCER:
344
6.96k
          *Type = EXTENSION_RECORD_TYPE;
345
6.96k
          break;
346
345
      case TERMINATOR_INTRODUCER:
347
345
          *Type = TERMINATE_RECORD_TYPE;
348
345
          break;
349
119
      default:
350
119
          *Type = UNDEFINED_RECORD_TYPE;
351
119
          GifFile->Error = D_GIF_ERR_WRONG_RECORD;
352
119
          return GIF_ERROR;
353
84.9k
    }
354
355
84.8k
    return GIF_OK;
356
84.9k
}
357
358
int
359
DGifGetImageHeader(GifFileType *GifFile)
360
77.5k
{
361
77.5k
    unsigned int BitsPerPixel;
362
77.5k
    GifByteType Buf[3];
363
77.5k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
364
365
77.5k
    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
77.5k
    if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
372
77.5k
        DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
373
77.5k
        DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
374
77.5k
        DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
375
51
        return GIF_ERROR;
376
77.4k
    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
77.4k
    BitsPerPixel = (Buf[0] & 0x07) + 1;
383
77.4k
    GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
384
385
    /* Setup the colormap */
386
77.4k
    if (GifFile->Image.ColorMap) {
387
1.32k
        GifFreeMapObject(GifFile->Image.ColorMap);
388
1.32k
        GifFile->Image.ColorMap = NULL;
389
1.32k
    }
390
    /* Does this image have local color map? */
391
77.4k
    if (Buf[0] & 0x80) {
392
1.44k
        unsigned int i;
393
394
1.44k
        GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
395
1.44k
        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
6.07k
        for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
402
            /* coverity[check_return] */
403
4.70k
            if (InternalRead(GifFile, Buf, 3) != 3) {
404
68
                GifFreeMapObject(GifFile->Image.ColorMap);
405
68
                GifFile->Error = D_GIF_ERR_READ_FAILED;
406
68
                GifFile->Image.ColorMap = NULL;
407
68
                return GIF_ERROR;
408
68
            }
409
4.63k
            GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
410
4.63k
            GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
411
4.63k
            GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
412
4.63k
        }
413
1.44k
    }
414
415
77.3k
    Private->PixelCount = (long)GifFile->Image.Width *
416
77.3k
       (long)GifFile->Image.Height;
417
418
    /* Reset decompress algorithm parameters. */
419
77.3k
    return DGifSetupDecompress(GifFile);
420
77.4k
}
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
77.5k
{
429
77.5k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
430
77.5k
    SavedImage *sp;
431
432
77.5k
    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
77.5k
    if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
439
259
        return GIF_ERROR;
440
259
    }
441
442
77.2k
    if (GifFile->SavedImages) {
443
75.7k
        SavedImage* new_saved_images =
444
75.7k
            (SavedImage *)reallocarray(GifFile->SavedImages,
445
75.7k
                            (GifFile->ImageCount + 1), sizeof(SavedImage));
446
75.7k
        if (new_saved_images == NULL) {
447
0
            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
448
0
            return GIF_ERROR;
449
0
        }
450
75.7k
        GifFile->SavedImages = new_saved_images;
451
75.7k
    } else {
452
1.45k
        if ((GifFile->SavedImages =
453
1.45k
             (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
454
0
            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
455
0
            return GIF_ERROR;
456
0
        }
457
1.45k
    }
458
459
77.2k
    sp = &GifFile->SavedImages[GifFile->ImageCount];
460
77.2k
    memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
461
77.2k
    if (GifFile->Image.ColorMap != NULL) {
462
1.35k
        sp->ImageDesc.ColorMap = GifMakeMapObject(
463
1.35k
                                 GifFile->Image.ColorMap->ColorCount,
464
1.35k
                                 GifFile->Image.ColorMap->Colors);
465
1.35k
        if (sp->ImageDesc.ColorMap == NULL) {
466
0
            GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
467
0
            return GIF_ERROR;
468
0
        }
469
1.35k
    }
470
77.2k
    sp->RasterBits = (unsigned char *)NULL;
471
77.2k
    sp->ExtensionBlockCount = 0;
472
77.2k
    sp->ExtensionBlocks = (ExtensionBlock *) NULL;
473
474
77.2k
    GifFile->ImageCount++;
475
476
77.2k
    return GIF_OK;
477
77.2k
}
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
1.15M
{
485
1.15M
    GifByteType *Dummy;
486
1.15M
    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
487
488
1.15M
    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
1.15M
    if (!LineLen)
495
0
        LineLen = GifFile->Image.Width;
496
497
1.15M
    if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
498
0
        GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
499
0
        return GIF_ERROR;
500
0
    }
501
502
1.15M
    if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
503
1.15M
        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
76.2k
            do
510
77.5k
                if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
511
56
                    return GIF_ERROR;
512
77.4k
            while (Dummy != NULL) ;
513
76.2k
        }
514
1.15M
        return GIF_OK;
515
1.15M
    } else
516
858
        return GIF_ERROR;
517
1.15M
}
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
6.96k
{
566
6.96k
    GifByteType Buf;
567
6.96k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
568
569
    //fprintf(stderr, "### -> DGifGetExtension:\n");
570
6.96k
    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
6.96k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
578
8
        GifFile->Error = D_GIF_ERR_READ_FAILED;
579
8
        return GIF_ERROR;
580
8
    }
581
6.96k
    *ExtCode = Buf;
582
    //fprintf(stderr, "### <- DGifGetExtension: %02x, about to call next\n", Buf);
583
584
6.96k
    return DGifGetExtensionNext(GifFile, Extension);
585
6.96k
}
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
179k
{
595
179k
    GifByteType Buf;
596
179k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
597
598
    //fprintf(stderr, "### -> DGifGetExtensionNext\n");
599
179k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
600
62
        GifFile->Error = D_GIF_ERR_READ_FAILED;
601
62
        return GIF_ERROR;
602
62
    }
603
    //fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
604
605
179k
    if (Buf > 0) {
606
170k
        *Extension = Private->Buf;    /* Use private unused buffer. */
607
170k
        (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
608
  /* coverity[tainted_data,check_return] */
609
170k
        if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
610
225
            GifFile->Error = D_GIF_ERR_READ_FAILED;
611
225
            return GIF_ERROR;
612
225
        }
613
170k
    } else
614
8.96k
        *Extension = NULL;
615
    //fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
616
617
179k
    return GIF_OK;
618
179k
}
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
1.30k
{
628
1.30k
    if (GifExtensionLength != 4) {
629
412
  return GIF_ERROR;
630
412
    }
631
632
893
    GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
633
893
    GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
634
893
    GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
635
893
    if (GifExtension[0] & 0x01)
636
445
  GCB->TransparentColor = (int)GifExtension[3];
637
448
    else
638
448
  GCB->TransparentColor = NO_TRANSPARENT_COLOR;
639
640
893
    return GIF_OK;
641
1.30k
}
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
68.7k
{
650
68.7k
    int i;
651
652
68.7k
    if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
653
0
  return GIF_ERROR;
654
655
68.7k
    GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
656
68.7k
    GCB->UserInputFlag = false;
657
68.7k
    GCB->DelayTime = 0;
658
68.7k
    GCB->TransparentColor = NO_TRANSPARENT_COLOR;
659
660
165k
    for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
661
98.4k
  ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
662
98.4k
  if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
663
1.30k
      return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
664
98.4k
    }
665
666
67.4k
    return GIF_ERROR;
667
68.7k
}
668
669
/******************************************************************************
670
 This routine should be called last, to close the GIF file.
671
******************************************************************************/
672
int
673
DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
674
2.13k
{
675
2.13k
    GifFilePrivateType *Private;
676
677
2.13k
    if (GifFile == NULL || GifFile->Private == NULL)
678
0
        return GIF_ERROR;
679
680
2.13k
    if (GifFile->Image.ColorMap) {
681
50
        GifFreeMapObject(GifFile->Image.ColorMap);
682
50
        GifFile->Image.ColorMap = NULL;
683
50
    }
684
685
2.13k
    if (GifFile->SColorMap) {
686
94
        GifFreeMapObject(GifFile->SColorMap);
687
94
        GifFile->SColorMap = NULL;
688
94
    }
689
690
2.13k
    if (GifFile->SavedImages) {
691
1.45k
        GifFreeSavedImages(GifFile);
692
1.45k
        GifFile->SavedImages = NULL;
693
1.45k
    }
694
695
2.13k
    GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
696
697
2.13k
    Private = (GifFilePrivateType *) GifFile->Private;
698
699
2.13k
    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
2.13k
    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
2.13k
    free((char *)GifFile->Private);
717
2.13k
    free(GifFile);
718
2.13k
    if (ErrorCode != NULL)
719
2.13k
  *ErrorCode = D_GIF_SUCCEEDED;
720
2.13k
    return GIF_OK;
721
2.13k
}
722
723
/******************************************************************************
724
 Get 2 bytes (word) from the given file:
725
******************************************************************************/
726
static int
727
DGifGetWord(GifFileType *GifFile, GifWord *Word)
728
314k
{
729
314k
    unsigned char c[2];
730
731
    /* coverity[check_return] */
732
314k
    if (InternalRead(GifFile, c, 2) != 2) {
733
55
        GifFile->Error = D_GIF_ERR_READ_FAILED;
734
55
        return GIF_ERROR;
735
55
    }
736
737
314k
    *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
738
314k
    return GIF_OK;
739
314k
}
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
77.5k
{
772
77.5k
    GifByteType Buf;
773
77.5k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
774
775
    /* coverity[tainted_data_argument] */
776
    /* coverity[check_return] */
777
77.5k
    if (InternalRead(GifFile, &Buf, 1) != 1) {
778
22
        GifFile->Error = D_GIF_ERR_READ_FAILED;
779
22
        return GIF_ERROR;
780
22
    }
781
782
    /* coverity[lower_bounds] */
783
77.5k
    if (Buf > 0) {
784
1.32k
        *CodeBlock = Private->Buf;    /* Use private unused buffer. */
785
1.32k
        (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
786
  /* coverity[tainted_data] */
787
1.32k
        if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
788
34
            GifFile->Error = D_GIF_ERR_READ_FAILED;
789
34
            return GIF_ERROR;
790
34
        }
791
76.2k
    } else {
792
76.2k
        *CodeBlock = NULL;
793
76.2k
        Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
794
76.2k
        Private->PixelCount = 0;    /* And local info. indicate image read. */
795
76.2k
    }
796
797
77.4k
    return GIF_OK;
798
77.5k
}
799
800
/******************************************************************************
801
 Setup the LZ decompression for this image:
802
******************************************************************************/
803
static int
804
DGifSetupDecompress(GifFileType *GifFile)
805
77.3k
{
806
77.3k
    int i, BitsPerPixel;
807
77.3k
    GifByteType CodeSize;
808
77.3k
    GifPrefixType *Prefix;
809
77.3k
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
810
811
    /* coverity[check_return] */
812
77.3k
    if (InternalRead(GifFile, &CodeSize, 1) < 1) {    /* Read Code size from file. */
813
36
  return GIF_ERROR;    /* Failed to read Code size. */
814
36
    }
815
77.3k
    BitsPerPixel = CodeSize;
816
817
    /* this can only happen on a severely malformed GIF */
818
77.3k
    if (BitsPerPixel > 8) {
819
91
  GifFile->Error = D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
820
91
  return GIF_ERROR;    /* Failed to read Code size. */
821
91
    }
822
823
77.2k
    Private->Buf[0] = 0;    /* Input Buffer empty. */
824
77.2k
    Private->BitsPerPixel = BitsPerPixel;
825
77.2k
    Private->ClearCode = (1 << BitsPerPixel);
826
77.2k
    Private->EOFCode = Private->ClearCode + 1;
827
77.2k
    Private->RunningCode = Private->EOFCode + 1;
828
77.2k
    Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
829
77.2k
    Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
830
77.2k
    Private->StackPtr = 0;    /* No pixels on the pixel stack. */
831
77.2k
    Private->LastCode = NO_SUCH_CODE;
832
77.2k
    Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
833
77.2k
    Private->CrntShiftDWord = 0;
834
835
77.2k
    Prefix = Private->Prefix;
836
316M
    for (i = 0; i <= LZ_MAX_CODE; i++)
837
316M
        Prefix[i] = NO_SUCH_CODE;
838
839
77.2k
    return GIF_OK;
840
77.3k
}
841
842
/******************************************************************************
843
 The LZ decompression routine:
844
 This version decompress the given GIF file into Line of length LineLen.
845
 This routine can be called few times (one per scan line, for example), in
846
 order the complete the whole image.
847
******************************************************************************/
848
static int
849
DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
850
1.15M
{
851
1.15M
    int i = 0;
852
1.15M
    int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
853
1.15M
    GifByteType *Stack, *Suffix;
854
1.15M
    GifPrefixType *Prefix;
855
1.15M
    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
856
857
1.15M
    StackPtr = Private->StackPtr;
858
1.15M
    Prefix = Private->Prefix;
859
1.15M
    Suffix = Private->Suffix;
860
1.15M
    Stack = Private->Stack;
861
1.15M
    EOFCode = Private->EOFCode;
862
1.15M
    ClearCode = Private->ClearCode;
863
1.15M
    LastCode = Private->LastCode;
864
865
1.15M
    if (StackPtr > LZ_MAX_CODE) {
866
0
        return GIF_ERROR;
867
0
    }
868
869
1.15M
    if (StackPtr != 0) {
870
        /* Let pop the stack off before continueing to read the GIF file: */
871
1.55M
        while (StackPtr != 0 && i < LineLen)
872
815k
            Line[i++] = Stack[--StackPtr];
873
738k
    }
874
875
2.58M
    while (i < LineLen) {    /* Decode LineLen items. */
876
1.43M
        if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
877
673
            return GIF_ERROR;
878
879
1.43M
        if (CrntCode == EOFCode) {
880
            /* Note however that usually we will not be here as we will stop
881
             * decoding as soon as we got all the pixel, or EOF code will
882
             * not be read at all, and DGifGetLine/Pixel clean everything.  */
883
26
      GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
884
26
      return GIF_ERROR;
885
1.43M
        } else if (CrntCode == ClearCode) {
886
            /* We need to start over again: */
887
839M
            for (j = 0; j <= LZ_MAX_CODE; j++)
888
839M
                Prefix[j] = NO_SUCH_CODE;
889
204k
            Private->RunningCode = Private->EOFCode + 1;
890
204k
            Private->RunningBits = Private->BitsPerPixel + 1;
891
204k
            Private->MaxCode1 = 1 << Private->RunningBits;
892
204k
            LastCode = Private->LastCode = NO_SUCH_CODE;
893
1.22M
        } else {
894
            /* Its regular code - if in pixel range simply add it to output
895
             * stream, otherwise trace to codes linked list until the prefix
896
             * is in pixel range: */
897
1.22M
            if (CrntCode < ClearCode) {
898
                /* This is simple - its pixel scalar, so add it to output: */
899
540k
                Line[i++] = CrntCode;
900
687k
            } else {
901
                /* Its a code to needed to be traced: trace the linked list
902
                 * until the prefix is a pixel, while pushing the suffix
903
                 * pixels on our stack. If we done, pop the stack in reverse
904
                 * (thats what stack is good for!) order to output.  */
905
687k
                if (Prefix[CrntCode] == NO_SUCH_CODE) {
906
164k
                    CrntPrefix = LastCode;
907
908
                    /* Only allowed if CrntCode is exactly the running code:
909
                     * In that case CrntCode = XXXCode, CrntCode or the
910
                     * prefix code is last code and the suffix char is
911
                     * exactly the prefix of last code! */
912
164k
                    if (CrntCode == Private->RunningCode - 2) {
913
55.0k
                        Suffix[Private->RunningCode - 2] =
914
55.0k
                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
915
55.0k
                                                                 LastCode,
916
55.0k
                                                                 ClearCode);
917
109k
                    } else {
918
109k
                        Suffix[Private->RunningCode - 2] =
919
109k
                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
920
109k
                                                                 CrntCode,
921
109k
                                                                 ClearCode);
922
109k
                    }
923
164k
                } else
924
522k
                    CrntPrefix = CrntCode;
925
926
                /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
927
                 * during the trace. As we might loop forever, in case of
928
                 * defective image, we use StackPtr as loop counter and stop
929
                 * before overflowing Stack[]. */
930
2.92M
                while (StackPtr < LZ_MAX_CODE &&
931
2.92M
                       CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
932
2.23M
                    Stack[StackPtr++] = Suffix[CrntPrefix];
933
2.23M
                    CrntPrefix = Prefix[CrntPrefix];
934
2.23M
                }
935
687k
                if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
936
159
                    GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
937
159
                    return GIF_ERROR;
938
159
                }
939
                /* Push the last character on stack: */
940
687k
                Stack[StackPtr++] = CrntPrefix;
941
942
                /* Now lets pop all the stack into output: */
943
2.92M
                while (StackPtr != 0 && i < LineLen)
944
2.23M
                    Line[i++] = Stack[--StackPtr];
945
687k
            }
946
1.22M
            if (LastCode != NO_SUCH_CODE && Private->RunningCode - 2 < (LZ_MAX_CODE+1) && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
947
1.08M
                Prefix[Private->RunningCode - 2] = LastCode;
948
949
1.08M
                if (CrntCode == Private->RunningCode - 2) {
950
                    /* Only allowed if CrntCode is exactly the running code:
951
                     * In that case CrntCode = XXXCode, CrntCode or the
952
                     * prefix code is last code and the suffix char is
953
                     * exactly the prefix of last code! */
954
55.0k
                    Suffix[Private->RunningCode - 2] =
955
55.0k
                       DGifGetPrefixChar(Prefix, LastCode, ClearCode);
956
1.02M
                } else {
957
1.02M
                    Suffix[Private->RunningCode - 2] =
958
1.02M
                       DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
959
1.02M
                }
960
1.08M
            }
961
1.22M
            LastCode = CrntCode;
962
1.22M
        }
963
1.43M
    }
964
965
1.15M
    Private->LastCode = LastCode;
966
1.15M
    Private->StackPtr = StackPtr;
967
968
1.15M
    return GIF_OK;
969
1.15M
}
970
971
/******************************************************************************
972
 Routine to trace the Prefixes linked list until we get a prefix which is
973
 not code, but a pixel value (less than ClearCode). Returns that pixel value.
974
 If image is defective, we might loop here forever, so we limit the loops to
975
 the maximum possible if image O.k. - LZ_MAX_CODE times.
976
******************************************************************************/
977
static int
978
DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
979
1.24M
{
980
1.24M
    int i = 0;
981
982
3.83M
    while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
983
2.80M
        if (Code > LZ_MAX_CODE) {
984
219k
            return NO_SUCH_CODE;
985
219k
        }
986
2.58M
        Code = Prefix[Code];
987
2.58M
    }
988
1.02M
    return Code;
989
1.24M
}
990
991
/******************************************************************************
992
 Interface for accessing the LZ codes directly. Set Code to the real code
993
 (12bits), or to -1 if EOF code is returned.
994
******************************************************************************/
995
int
996
DGifGetLZCodes(GifFileType *GifFile, int *Code)
997
0
{
998
0
    GifByteType *CodeBlock;
999
0
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1000
1001
0
    if (!IS_READABLE(Private)) {
1002
        /* This file was NOT open for reading: */
1003
0
        GifFile->Error = D_GIF_ERR_NOT_READABLE;
1004
0
        return GIF_ERROR;
1005
0
    }
1006
1007
0
    if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
1008
0
        return GIF_ERROR;
1009
1010
0
    if (*Code == Private->EOFCode) {
1011
        /* Skip rest of codes (hopefully only NULL terminating block): */
1012
0
        do {
1013
0
            if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
1014
0
                return GIF_ERROR;
1015
0
        } while (CodeBlock != NULL) ;
1016
1017
0
        *Code = -1;
1018
0
    } else if (*Code == Private->ClearCode) {
1019
        /* We need to start over again: */
1020
0
        Private->RunningCode = Private->EOFCode + 1;
1021
0
        Private->RunningBits = Private->BitsPerPixel + 1;
1022
0
        Private->MaxCode1 = 1 << Private->RunningBits;
1023
0
    }
1024
1025
0
    return GIF_OK;
1026
0
}
1027
1028
/******************************************************************************
1029
 The LZ decompression input routine:
1030
 This routine is responsable for the decompression of the bit stream from
1031
 8 bits (bytes) packets, into the real codes.
1032
 Returns GIF_OK if read successfully.
1033
******************************************************************************/
1034
static int
1035
DGifDecompressInput(GifFileType *GifFile, int *Code)
1036
1.43M
{
1037
1.43M
    static const unsigned short CodeMasks[] = {
1038
1.43M
  0x0000, 0x0001, 0x0003, 0x0007,
1039
1.43M
  0x000f, 0x001f, 0x003f, 0x007f,
1040
1.43M
  0x00ff, 0x01ff, 0x03ff, 0x07ff,
1041
1.43M
  0x0fff
1042
1.43M
    };
1043
1044
1.43M
    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1045
1046
1.43M
    GifByteType NextByte;
1047
1048
    /* The image can't contain more than LZ_BITS per code. */
1049
1.43M
    if (Private->RunningBits > LZ_BITS) {
1050
0
        GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1051
0
        return GIF_ERROR;
1052
0
    }
1053
    
1054
2.88M
    while (Private->CrntShiftState < Private->RunningBits) {
1055
        /* Needs to get more bytes from input stream for next code: */
1056
1.45M
        if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
1057
673
            return GIF_ERROR;
1058
673
        }
1059
1.44M
        Private->CrntShiftDWord |=
1060
1.44M
      ((unsigned long)NextByte) << Private->CrntShiftState;
1061
1.44M
        Private->CrntShiftState += 8;
1062
1.44M
    }
1063
1.43M
    *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1064
1065
1.43M
    Private->CrntShiftDWord >>= Private->RunningBits;
1066
1.43M
    Private->CrntShiftState -= Private->RunningBits;
1067
1068
    /* If code cannot fit into RunningBits bits, must raise its size. Note
1069
     * however that codes above 4095 are used for special signaling.
1070
     * If we're using LZ_BITS bits already and we're at the max code, just
1071
     * keep using the table as it is, don't increment Private->RunningCode.
1072
     */
1073
1.43M
    if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1074
1.43M
  ++Private->RunningCode > Private->MaxCode1 &&
1075
1.43M
  Private->RunningBits < LZ_BITS) {
1076
356k
        Private->MaxCode1 <<= 1;
1077
356k
        Private->RunningBits++;
1078
356k
    }
1079
1.43M
    return GIF_OK;
1080
1.43M
}
1081
1082
/******************************************************************************
1083
 This routines read one GIF data block at a time and buffers it internally
1084
 so that the decompression routine could access it.
1085
 The routine returns the next byte from its internal buffer (or read next
1086
 block in if buffer empty) and returns GIF_OK if succesful.
1087
******************************************************************************/
1088
static int
1089
DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
1090
1.45M
{
1091
1.45M
    if (Buf[0] == 0) {
1092
        /* Needs to read the next buffer - this one is empty: */
1093
  /* coverity[check_return] */
1094
90.8k
        if (InternalRead(GifFile, Buf, 1) != 1) {
1095
466
            GifFile->Error = D_GIF_ERR_READ_FAILED;
1096
466
            return GIF_ERROR;
1097
466
        }
1098
        /* There shouldn't be any empty data blocks here as the LZW spec
1099
         * says the LZW termination code should come first.  Therefore we
1100
         * shouldn't be inside this routine at that point.
1101
         */
1102
90.4k
        if (Buf[0] == 0) {
1103
69
            GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1104
69
            return GIF_ERROR;
1105
69
        }
1106
90.3k
        if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1107
138
            GifFile->Error = D_GIF_ERR_READ_FAILED;
1108
138
            return GIF_ERROR;
1109
138
        }
1110
90.2k
        *NextByte = Buf[1];
1111
90.2k
        Buf[1] = 2;    /* We use now the second place as last char read! */
1112
90.2k
        Buf[0]--;
1113
1.35M
    } else {
1114
1.35M
        *NextByte = Buf[Buf[1]++];
1115
1.35M
        Buf[0]--;
1116
1.35M
    }
1117
1118
1.44M
    return GIF_OK;
1119
1.45M
}
1120
1121
/******************************************************************************
1122
 This routine reads an entire GIF into core, hanging all its state info off
1123
 the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
1124
 first to initialize I/O.  Its inverse is EGifSpew().
1125
*******************************************************************************/
1126
int
1127
DGifSlurp(GifFileType *GifFile)
1128
2.13k
{
1129
2.13k
    size_t ImageSize;
1130
2.13k
    GifRecordType RecordType;
1131
2.13k
    SavedImage *sp;
1132
2.13k
    GifByteType *ExtData;
1133
2.13k
    int ExtFunction;
1134
1135
2.13k
    GifFile->ExtensionBlocks = NULL;
1136
2.13k
    GifFile->ExtensionBlockCount = 0;
1137
1138
85.0k
    do {
1139
85.0k
        if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
1140
199
            return (GIF_ERROR);
1141
1142
84.8k
        switch (RecordType) {
1143
77.5k
          case IMAGE_DESC_RECORD_TYPE:
1144
77.5k
              if (DGifGetImageDesc(GifFile) == GIF_ERROR)
1145
259
                  return (GIF_ERROR);
1146
1147
77.2k
              sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1148
              /* Allocate memory for the image */
1149
77.2k
              if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 ||
1150
77.2k
                      sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
1151
127
                  return GIF_ERROR;
1152
127
              }
1153
77.1k
              ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1154
1155
77.1k
              if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1156
0
                  return GIF_ERROR;
1157
0
              }
1158
77.1k
              sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
1159
77.1k
                      sizeof(GifPixelType));
1160
1161
77.1k
              if (sp->RasterBits == NULL) {
1162
0
                  return GIF_ERROR;
1163
0
              }
1164
1165
77.1k
        if (sp->ImageDesc.Interlace) {
1166
71.2k
      int i, j;
1167
       /* 
1168
        * The way an interlaced image should be read - 
1169
        * offsets and jumps...
1170
        */
1171
71.2k
      int InterlacedOffset[] = { 0, 4, 2, 1 };
1172
71.2k
      int InterlacedJumps[] = { 8, 8, 4, 2 };
1173
      /* Need to perform 4 passes on the image */
1174
354k
      for (i = 0; i < 4; i++)
1175
283k
          for (j = InterlacedOffset[i]; 
1176
1.42M
         j < sp->ImageDesc.Height;
1177
1.14M
         j += InterlacedJumps[i]) {
1178
1.14M
        if (DGifGetLine(GifFile, 
1179
1.14M
            sp->RasterBits+j*sp->ImageDesc.Width, 
1180
1.14M
            sp->ImageDesc.Width) == GIF_ERROR)
1181
413
            return GIF_ERROR;
1182
1.14M
          }
1183
71.2k
        }
1184
5.91k
        else {
1185
5.91k
      if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
1186
501
          return (GIF_ERROR);
1187
5.91k
        }
1188
1189
76.2k
              if (GifFile->ExtensionBlocks) {
1190
2.88k
                  sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1191
2.88k
                  sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
1192
1193
2.88k
                  GifFile->ExtensionBlocks = NULL;
1194
2.88k
                  GifFile->ExtensionBlockCount = 0;
1195
2.88k
              }
1196
76.2k
              break;
1197
1198
6.96k
          case EXTENSION_RECORD_TYPE:
1199
6.96k
              if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
1200
49
                  return (GIF_ERROR);
1201
        /* Create an extension block with our data */
1202
6.91k
              if (ExtData != NULL) {
1203
4.63k
      if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1204
4.63k
             &GifFile->ExtensionBlocks, 
1205
4.63k
             ExtFunction, ExtData[0], &ExtData[1])
1206
4.63k
          == GIF_ERROR)
1207
0
          return (GIF_ERROR);
1208
4.63k
        }
1209
172k
              for (;;) {
1210
172k
                  if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
1211
246
                      return (GIF_ERROR);
1212
172k
      if (ExtData == NULL)
1213
6.67k
          break;
1214
                  /* Continue the extension block */
1215
165k
      if (ExtData != NULL)
1216
165k
          if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
1217
165k
                 &GifFile->ExtensionBlocks,
1218
165k
                 CONTINUE_EXT_FUNC_CODE, 
1219
165k
                 ExtData[0], &ExtData[1]) == GIF_ERROR)
1220
0
                      return (GIF_ERROR);
1221
165k
              }
1222
6.67k
              break;
1223
1224
6.67k
          case TERMINATE_RECORD_TYPE:
1225
345
              break;
1226
1227
0
          default:    /* Should be trapped by DGifGetRecordType */
1228
0
              break;
1229
84.8k
        }
1230
84.8k
    } while (RecordType != TERMINATE_RECORD_TYPE);
1231
1232
    /* Sanity check for corrupted file */
1233
345
    if (GifFile->ImageCount == 0) {
1234
99
  GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1235
99
  return(GIF_ERROR);
1236
99
    }
1237
1238
246
    return (GIF_OK);
1239
345
}
1240
1241
/* end */