Coverage Report

Created: 2026-03-29 06:25

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