Coverage Report

Created: 2026-08-14 06:29

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