Coverage Report

Created: 2026-02-14 06:15

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