Coverage Report

Created: 2026-06-15 06:33

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
20.3k
#define UNSIGNED_LITTLE_ENDIAN(lo, hi) ((lo) | ((hi) << 8))
31
32
/* avoid extra function call in case we use fread (TVT) */
33
123k
static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
34
  // fprintf(stderr, "### Read: %d\n", len);
35
123k
  return (((GifFilePrivateType *)gif->Private)->Read
36
123k
              ? ((GifFilePrivateType *)gif->Private)->Read(gif, buf, len)
37
123k
              : fread(buf, 1, len,
38
0
                      ((GifFilePrivateType *)gif->Private)->File));
39
123k
}
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.04k
GifFileType *DGifOpen(void *userData, InputFunc readFunc, int *Error) {
168
1.04k
  char Buf[GIF_STAMP_LEN + 1];
169
1.04k
  GifFileType *GifFile;
170
1.04k
  GifFilePrivateType *Private;
171
172
1.04k
  GifFile = (GifFileType *)malloc(sizeof(GifFileType));
173
1.04k
  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.04k
  memset(GifFile, '\0', sizeof(GifFileType));
181
182
  /* Belt and suspenders, in case the null pointer isn't zero */
183
1.04k
  GifFile->SavedImages = NULL;
184
1.04k
  GifFile->SColorMap = NULL;
185
186
1.04k
  Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
187
1.04k
  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.04k
  /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType));
195
196
1.04k
  GifFile->Private = (void *)Private;
197
1.04k
  Private->FileHandle = 0;
198
1.04k
  Private->File = NULL;
199
1.04k
  Private->FileState = FILE_STATE_READ;
200
201
1.04k
  Private->Read = readFunc;     /* TVT */
202
1.04k
  GifFile->UserData = userData; /* TVT */
203
204
  /* Lets see if this is a GIF file: */
205
  /* coverity[check_return] */
206
1.04k
  if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) !=
207
1.04k
      GIF_STAMP_LEN) {
208
0
    if (Error != NULL) {
209
0
      *Error = D_GIF_ERR_READ_FAILED;
210
0
    }
211
0
    free((char *)Private);
212
0
    free((char *)GifFile);
213
0
    return NULL;
214
0
  }
215
216
  /* Check for GIF prefix at start of file */
217
1.04k
  Buf[GIF_STAMP_LEN] = '\0';
218
1.04k
  if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
219
0
    if (Error != NULL) {
220
0
      *Error = D_GIF_ERR_NOT_GIF_FILE;
221
0
    }
222
0
    free((char *)Private);
223
0
    free((char *)GifFile);
224
0
    return NULL;
225
0
  }
226
227
1.04k
  if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
228
25
    free((char *)Private);
229
25
    free((char *)GifFile);
230
25
    if (Error != NULL) {
231
25
      *Error = D_GIF_ERR_NO_SCRN_DSCR;
232
25
    }
233
25
    return NULL;
234
25
  }
235
236
1.02k
  GifFile->Error = 0;
237
238
  /* What version of GIF? */
239
1.02k
  Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9');
240
241
1.02k
  return GifFile;
242
1.04k
}
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.04k
int DGifGetScreenDesc(GifFileType *GifFile) {
249
1.04k
  int BitsPerPixel;
250
1.04k
  bool SortFlag;
251
1.04k
  GifByteType Buf[3];
252
1.04k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
253
254
1.04k
  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.04k
  if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
262
1.04k
      DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) {
263
0
    return GIF_ERROR;
264
0
  }
265
266
1.04k
  if (InternalRead(GifFile, Buf, 3) != 3) {
267
6
    GifFile->Error = D_GIF_ERR_READ_FAILED;
268
6
    GifFreeMapObject(GifFile->SColorMap);
269
6
    GifFile->SColorMap = NULL;
270
6
    return GIF_ERROR;
271
6
  }
272
1.04k
  GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
273
1.04k
  SortFlag = (Buf[0] & 0x08) != 0;
274
1.04k
  BitsPerPixel = (Buf[0] & 0x07) + 1;
275
1.04k
  GifFile->SBackGroundColor = Buf[1];
276
1.04k
  GifFile->AspectByte = Buf[2];
277
1.04k
  if (Buf[0] & 0x80) { /* Do we have global color map? */
278
71
    int i;
279
280
71
    GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
281
71
    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
71
    GifFile->SColorMap->SortFlag = SortFlag;
288
517
    for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
289
      /* coverity[check_return] */
290
465
      if (InternalRead(GifFile, Buf, 3) != 3) {
291
19
        GifFreeMapObject(GifFile->SColorMap);
292
19
        GifFile->SColorMap = NULL;
293
19
        GifFile->Error = D_GIF_ERR_READ_FAILED;
294
19
        return GIF_ERROR;
295
19
      }
296
446
      GifFile->SColorMap->Colors[i].Red = Buf[0];
297
446
      GifFile->SColorMap->Colors[i].Green = Buf[1];
298
446
      GifFile->SColorMap->Colors[i].Blue = Buf[2];
299
446
    }
300
969
  } else {
301
969
    GifFile->SColorMap = NULL;
302
969
  }
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.02k
  return GIF_OK;
310
1.04k
}
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
8.09k
int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type) {
326
8.09k
  GifByteType Buf;
327
8.09k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
328
329
8.09k
  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
8.09k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
337
12
    GifFile->Error = D_GIF_ERR_READ_FAILED;
338
12
    return GIF_ERROR;
339
12
  }
340
341
  // fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
342
8.08k
  switch (Buf) {
343
4.51k
  case DESCRIPTOR_INTRODUCER:
344
4.51k
    *Type = IMAGE_DESC_RECORD_TYPE;
345
4.51k
    break;
346
3.25k
  case EXTENSION_INTRODUCER:
347
3.25k
    *Type = EXTENSION_RECORD_TYPE;
348
3.25k
    break;
349
205
  case TERMINATOR_INTRODUCER:
350
205
    *Type = TERMINATE_RECORD_TYPE;
351
205
    break;
352
108
  default:
353
108
    *Type = UNDEFINED_RECORD_TYPE;
354
108
    GifFile->Error = D_GIF_ERR_WRONG_RECORD;
355
108
    return GIF_ERROR;
356
8.08k
  }
357
358
7.97k
  return GIF_OK;
359
8.08k
}
360
361
4.51k
int DGifGetImageHeader(GifFileType *GifFile) {
362
4.51k
  unsigned int BitsPerPixel;
363
4.51k
  GifByteType Buf[3];
364
4.51k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
365
366
4.51k
  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
4.51k
  if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
373
4.51k
      DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
374
4.51k
      DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
375
4.51k
      DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) {
376
10
    return GIF_ERROR;
377
10
  }
378
4.50k
  if (InternalRead(GifFile, Buf, 1) != 1) {
379
1
    GifFile->Error = D_GIF_ERR_READ_FAILED;
380
1
    GifFreeMapObject(GifFile->Image.ColorMap);
381
1
    GifFile->Image.ColorMap = NULL;
382
1
    return GIF_ERROR;
383
1
  }
384
4.50k
  BitsPerPixel = (Buf[0] & 0x07) + 1;
385
4.50k
  GifFile->Image.Interlace = (Buf[0] & 0x40) ? true : false;
386
387
  /* Setup the colormap */
388
4.50k
  if (GifFile->Image.ColorMap) {
389
287
    GifFreeMapObject(GifFile->Image.ColorMap);
390
287
    GifFile->Image.ColorMap = NULL;
391
287
  }
392
  /* Does this image have local color map? */
393
4.50k
  if (Buf[0] & 0x80) {
394
347
    unsigned int i;
395
396
347
    GifFile->Image.ColorMap =
397
347
        GifMakeMapObject(1 << BitsPerPixel, NULL);
398
347
    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
2.28k
    for (i = 0; i < GifFile->Image.ColorMap->ColorCount; i++) {
405
      /* coverity[check_return] */
406
1.96k
      if (InternalRead(GifFile, Buf, 3) != 3) {
407
24
        GifFreeMapObject(GifFile->Image.ColorMap);
408
24
        GifFile->Error = D_GIF_ERR_READ_FAILED;
409
24
        GifFile->Image.ColorMap = NULL;
410
24
        return GIF_ERROR;
411
24
      }
412
1.93k
      GifFile->Image.ColorMap->Colors[i].Red = Buf[0];
413
1.93k
      GifFile->Image.ColorMap->Colors[i].Green = Buf[1];
414
1.93k
      GifFile->Image.ColorMap->Colors[i].Blue = Buf[2];
415
1.93k
    }
416
347
  }
417
418
4.48k
  Private->PixelCount =
419
4.48k
      (unsigned long)GifFile->Image.Width *
420
4.48k
      (unsigned long)GifFile->Image.Height;
421
422
  /* Reset decompress algorithm parameters. */
423
4.48k
  return DGifSetupDecompress(GifFile);
424
4.50k
}
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
4.51k
int DGifGetImageDesc(GifFileType *GifFile) {
431
4.51k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
432
4.51k
  SavedImage *sp;
433
434
4.51k
  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
4.51k
  if (DGifGetImageHeader(GifFile) == GIF_ERROR) {
441
185
    return GIF_ERROR;
442
185
  }
443
444
4.33k
  if (GifFile->SavedImages) {
445
3.79k
    SavedImage *new_saved_images = (SavedImage *)reallocarray(
446
3.79k
        GifFile->SavedImages, (GifFile->ImageCount + 1),
447
3.79k
        sizeof(SavedImage));
448
3.79k
    if (new_saved_images == NULL) {
449
0
      GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
450
0
      return GIF_ERROR;
451
0
    }
452
3.79k
    GifFile->SavedImages = new_saved_images;
453
3.79k
  } else {
454
543
    if ((GifFile->SavedImages =
455
543
             (SavedImage *)malloc(sizeof(SavedImage))) == NULL) {
456
0
      GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
457
0
      return GIF_ERROR;
458
0
    }
459
543
  }
460
461
4.33k
  sp = &GifFile->SavedImages[GifFile->ImageCount];
462
4.33k
  memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
463
4.33k
  if (GifFile->Image.ColorMap != NULL) {
464
308
    sp->ImageDesc.ColorMap =
465
308
        GifMakeMapObject(GifFile->Image.ColorMap->ColorCount,
466
308
                         GifFile->Image.ColorMap->Colors);
467
308
    if (sp->ImageDesc.ColorMap == NULL) {
468
0
      GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
469
0
      return GIF_ERROR;
470
0
    }
471
308
  }
472
4.33k
  sp->RasterBits = (unsigned char *)NULL;
473
4.33k
  sp->ExtensionBlockCount = 0;
474
4.33k
  sp->ExtensionBlocks = (ExtensionBlock *)NULL;
475
476
4.33k
  GifFile->ImageCount++;
477
478
4.33k
  return GIF_OK;
479
4.33k
}
480
481
/******************************************************************************
482
 Get one full scanned line (Line) of length LineLen from GIF file.
483
******************************************************************************/
484
390k
int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) {
485
390k
  GifByteType *Dummy;
486
390k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
487
488
390k
  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
390k
  if (!LineLen) {
495
0
    LineLen = GifFile->Image.Width;
496
0
  }
497
498
390k
  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
390k
  Private->PixelCount -= LineLen;
503
504
390k
  if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
505
390k
    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
4.42k
      do {
512
4.42k
        if (DGifGetCodeNext(GifFile, &Dummy) ==
513
4.42k
            GIF_ERROR) {
514
21
          return GIF_ERROR;
515
21
        }
516
4.42k
      } while (Dummy != NULL);
517
3.95k
    }
518
390k
    return GIF_OK;
519
390k
  } else {
520
357
    return GIF_ERROR;
521
357
  }
522
390k
}
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
3.25k
                     GifByteType **Extension) {
571
3.25k
  GifByteType Buf;
572
3.25k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
573
574
  // fprintf(stderr, "### -> DGifGetExtension:\n");
575
3.25k
  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
3.25k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
583
0
    GifFile->Error = D_GIF_ERR_READ_FAILED;
584
0
    return GIF_ERROR;
585
0
  }
586
3.25k
  *ExtCode = Buf;
587
  // fprintf(stderr, "### <- DGifGetExtension: %02x, about to call
588
  // next\n", Buf);
589
590
3.25k
  return DGifGetExtensionNext(GifFile, Extension);
591
3.25k
}
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
28.2k
int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) {
599
28.2k
  GifByteType Buf;
600
28.2k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
601
602
  // fprintf(stderr, "### -> DGifGetExtensionNext\n");
603
28.2k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
604
4
    GifFile->Error = D_GIF_ERR_READ_FAILED;
605
4
    return GIF_ERROR;
606
4
  }
607
  // fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
608
609
28.2k
  if (Buf > 0) {
610
23.6k
    *Extension = Private->Buf; /* Use private unused buffer. */
611
23.6k
    (*Extension)[0] =
612
23.6k
        Buf; /* Pascal strings notation (pos. 0 is len.). */
613
             /* coverity[tainted_data,check_return] */
614
23.6k
    if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
615
110
      GifFile->Error = D_GIF_ERR_READ_FAILED;
616
110
      return GIF_ERROR;
617
110
    }
618
23.6k
  } else {
619
4.60k
    *Extension = NULL;
620
4.60k
  }
621
  // fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
622
623
28.1k
  return GIF_OK;
624
28.2k
}
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
347
                       GraphicsControlBlock *GCB) {
633
347
  if (GifExtensionLength != 4) {
634
102
    return GIF_ERROR;
635
102
  }
636
637
245
  GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
638
245
  GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
639
245
  GCB->DelayTime =
640
245
      UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
641
245
  if (GifExtension[0] & 0x01) {
642
50
    GCB->TransparentColor = (int)GifExtension[3];
643
195
  } else {
644
195
    GCB->TransparentColor = NO_TRANSPARENT_COLOR;
645
195
  }
646
647
245
  return GIF_OK;
648
347
}
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
2.44k
                            GraphicsControlBlock *GCB) {
656
2.44k
  int i;
657
658
2.44k
  if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) {
659
0
    return GIF_ERROR;
660
0
  }
661
662
2.44k
  GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
663
2.44k
  GCB->UserInputFlag = false;
664
2.44k
  GCB->DelayTime = 0;
665
2.44k
  GCB->TransparentColor = NO_TRANSPARENT_COLOR;
666
667
7.35k
  for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount;
668
5.26k
       i++) {
669
5.26k
    ExtensionBlock *ep =
670
5.26k
        &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
671
5.26k
    if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
672
347
      return DGifExtensionToGCB(ep->ByteCount, ep->Bytes,
673
347
                                GCB);
674
347
    }
675
5.26k
  }
676
677
2.09k
  return GIF_ERROR;
678
2.44k
}
679
680
/******************************************************************************
681
 This routine should be called last, to close the GIF file.
682
******************************************************************************/
683
1.02k
int DGifCloseFile(GifFileType *GifFile, int *ErrorCode) {
684
1.02k
  GifFilePrivateType *Private;
685
686
1.02k
  if (GifFile == NULL || GifFile->Private == NULL) {
687
0
    return GIF_ERROR;
688
0
  }
689
690
1.02k
  if (GifFile->Image.ColorMap) {
691
36
    GifFreeMapObject(GifFile->Image.ColorMap);
692
36
    GifFile->Image.ColorMap = NULL;
693
36
  }
694
695
1.02k
  if (GifFile->SColorMap) {
696
52
    GifFreeMapObject(GifFile->SColorMap);
697
52
    GifFile->SColorMap = NULL;
698
52
  }
699
700
1.02k
  if (GifFile->SavedImages) {
701
171
    GifFreeSavedImages(GifFile);
702
171
    GifFile->SavedImages = NULL;
703
171
  }
704
705
1.02k
  GifFreeExtensions(&GifFile->ExtensionBlockCount,
706
1.02k
                    &GifFile->ExtensionBlocks);
707
708
1.02k
  Private = (GifFilePrivateType *)GifFile->Private;
709
710
1.02k
  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.02k
  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.02k
  free((char *)GifFile->Private);
730
1.02k
  free(GifFile);
731
1.02k
  if (ErrorCode != NULL) {
732
1.02k
    *ErrorCode = D_GIF_SUCCEEDED;
733
1.02k
  }
734
1.02k
  return GIF_OK;
735
1.02k
}
736
737
/******************************************************************************
738
 Get 2 bytes (word) from the given file:
739
******************************************************************************/
740
20.1k
static int DGifGetWord(GifFileType *GifFile, GifWord *Word) {
741
20.1k
  unsigned char c[2];
742
743
  /* coverity[check_return] */
744
20.1k
  if (InternalRead(GifFile, c, 2) != 2) {
745
10
    GifFile->Error = D_GIF_ERR_READ_FAILED;
746
10
    return GIF_ERROR;
747
10
  }
748
749
20.1k
  *Word = (GifWord)UNSIGNED_LITTLE_ENDIAN(c[0], c[1]);
750
20.1k
  return GIF_OK;
751
20.1k
}
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
4.42k
int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) {
780
4.42k
  GifByteType Buf;
781
4.42k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
782
783
  /* coverity[tainted_data_argument] */
784
  /* coverity[check_return] */
785
4.42k
  if (InternalRead(GifFile, &Buf, 1) != 1) {
786
4
    GifFile->Error = D_GIF_ERR_READ_FAILED;
787
4
    return GIF_ERROR;
788
4
  }
789
790
  /* coverity[lower_bounds] */
791
4.41k
  if (Buf > 0) {
792
483
    *CodeBlock = Private->Buf; /* Use private unused buffer. */
793
483
    (*CodeBlock)[0] =
794
483
        Buf; /* Pascal strings notation (pos. 0 is len.). */
795
             /* coverity[tainted_data] */
796
483
    if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
797
17
      GifFile->Error = D_GIF_ERR_READ_FAILED;
798
17
      return GIF_ERROR;
799
17
    }
800
3.93k
  } else {
801
3.93k
    *CodeBlock = NULL;
802
3.93k
    Private->Buf[0] = 0; /* Make sure the buffer is empty! */
803
3.93k
    Private->PixelCount =
804
3.93k
        0; /* And local info. indicate image read. */
805
3.93k
  }
806
807
4.40k
  return GIF_OK;
808
4.41k
}
809
810
/******************************************************************************
811
 Setup the LZ decompression for this image:
812
******************************************************************************/
813
4.48k
static int DGifSetupDecompress(GifFileType *GifFile) {
814
4.48k
  int i, BitsPerPixel;
815
4.48k
  GifByteType CodeSize;
816
4.48k
  GifPrefixType *Prefix;
817
4.48k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
818
819
  /* coverity[check_return] */
820
4.48k
  if (InternalRead(GifFile, &CodeSize, 1) <
821
4.48k
      1) { /* Read Code size from file. */
822
7
    GifFile->Error = D_GIF_ERR_READ_FAILED;
823
7
    return GIF_ERROR; /* Failed to read Code size. */
824
7
  }
825
4.47k
  BitsPerPixel = CodeSize;
826
827
  /* this can only happen on a severely malformed GIF */
828
4.47k
  if (BitsPerPixel < 2 || BitsPerPixel > 8) {
829
143
    GifFile->Error =
830
143
        D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
831
143
    return GIF_ERROR;          /* Failed to read Code size. */
832
143
  }
833
834
4.33k
  Private->Buf[0] = 0; /* Input Buffer empty. */
835
4.33k
  Private->BitsPerPixel = BitsPerPixel;
836
4.33k
  Private->ClearCode = (1 << BitsPerPixel);
837
4.33k
  Private->EOFCode = Private->ClearCode + 1;
838
4.33k
  Private->RunningCode = Private->EOFCode + 1;
839
4.33k
  Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
840
4.33k
  Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
841
4.33k
  Private->StackPtr = 0; /* No pixels on the pixel stack. */
842
4.33k
  Private->LastCode = NO_SUCH_CODE;
843
4.33k
  Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
844
4.33k
  Private->CrntShiftDWord = 0;
845
846
4.33k
  Prefix = Private->Prefix;
847
17.7M
  for (i = 0; i <= LZ_MAX_CODE; i++) {
848
17.7M
    Prefix[i] = NO_SUCH_CODE;
849
17.7M
  }
850
851
4.33k
  return GIF_OK;
852
4.47k
}
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
390k
                              int LineLen) {
862
390k
  int i = 0;
863
390k
  int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
864
390k
  GifByteType *Stack, *Suffix;
865
390k
  GifPrefixType *Prefix;
866
390k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
867
868
390k
  StackPtr = Private->StackPtr;
869
390k
  Prefix = Private->Prefix;
870
390k
  Suffix = Private->Suffix;
871
390k
  Stack = Private->Stack;
872
390k
  EOFCode = Private->EOFCode;
873
390k
  ClearCode = Private->ClearCode;
874
390k
  LastCode = Private->LastCode;
875
876
390k
  if (StackPtr > LZ_MAX_CODE) {
877
0
    return GIF_ERROR;
878
0
  }
879
880
390k
  if (StackPtr != 0) {
881
    /* Let pop the stack off before continueing to read the GIF
882
     * file: */
883
504k
    while (StackPtr != 0 && i < LineLen) {
884
252k
      Line[i++] = Stack[--StackPtr];
885
252k
    }
886
252k
  }
887
888
814k
  while (i < LineLen) { /* Decode LineLen items. */
889
424k
    if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) {
890
277
      return GIF_ERROR;
891
277
    }
892
893
424k
    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
11
      GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
899
11
      return GIF_ERROR;
900
424k
    } else if (CrntCode == ClearCode) {
901
      /* We need to start over again: */
902
35.4M
      for (j = 0; j <= LZ_MAX_CODE; j++) {
903
35.4M
        Prefix[j] = NO_SUCH_CODE;
904
35.4M
      }
905
8.66k
      Private->RunningCode = Private->EOFCode + 1;
906
8.66k
      Private->RunningBits = Private->BitsPerPixel + 1;
907
8.66k
      Private->MaxCode1 = 1 << Private->RunningBits;
908
8.66k
      LastCode = Private->LastCode = NO_SUCH_CODE;
909
415k
    } 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
415k
      if (CrntCode < ClearCode) {
914
        /* This is simple - its pixel scalar, so add it
915
         * to output: */
916
204k
        Line[i++] = CrntCode;
917
210k
      } 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
210k
        if (Prefix[CrntCode] == NO_SUCH_CODE) {
924
45.0k
          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
45.0k
          if (CrntCode ==
933
45.0k
              Private->RunningCode - 2) {
934
957
            Suffix[Private->RunningCode -
935
957
                   2] = Stack[StackPtr++] =
936
957
                DGifGetPrefixChar(
937
957
                    Prefix, LastCode,
938
957
                    ClearCode);
939
44.0k
          } else {
940
44.0k
            Suffix[Private->RunningCode -
941
44.0k
                   2] = Stack[StackPtr++] =
942
44.0k
                DGifGetPrefixChar(
943
44.0k
                    Prefix, CrntCode,
944
44.0k
                    ClearCode);
945
44.0k
          }
946
165k
        } else {
947
165k
          CrntPrefix = CrntCode;
948
165k
        }
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
651k
        while (StackPtr < LZ_MAX_CODE &&
956
651k
               CrntPrefix > ClearCode &&
957
440k
               CrntPrefix <= LZ_MAX_CODE) {
958
440k
          Stack[StackPtr++] = Suffix[CrntPrefix];
959
440k
          CrntPrefix = Prefix[CrntPrefix];
960
440k
        }
961
210k
        if (StackPtr >= LZ_MAX_CODE ||
962
210k
            CrntPrefix > LZ_MAX_CODE) {
963
69
          GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
964
69
          return GIF_ERROR;
965
69
        }
966
        /* Push the last character on stack: */
967
210k
        Stack[StackPtr++] = CrntPrefix;
968
969
        /* Now lets pop all the stack into output: */
970
641k
        while (StackPtr != 0 && i < LineLen) {
971
430k
          Line[i++] = Stack[--StackPtr];
972
430k
        }
973
210k
      }
974
415k
      if (LastCode != NO_SUCH_CODE &&
975
403k
          Private->RunningCode - 2 < (LZ_MAX_CODE + 1) &&
976
403k
          Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
977
402k
        Prefix[Private->RunningCode - 2] = LastCode;
978
979
402k
        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
944
          Suffix[Private->RunningCode - 2] =
987
944
              DGifGetPrefixChar(Prefix, LastCode,
988
944
                                ClearCode);
989
401k
        } else {
990
401k
          Suffix[Private->RunningCode - 2] =
991
401k
              DGifGetPrefixChar(Prefix, CrntCode,
992
401k
                                ClearCode);
993
401k
        }
994
402k
      }
995
415k
      LastCode = CrntCode;
996
415k
    }
997
424k
  }
998
999
390k
  Private->LastCode = LastCode;
1000
390k
  Private->StackPtr = StackPtr;
1001
1002
390k
  return GIF_OK;
1003
390k
}
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
447k
                             int ClearCode) {
1013
447k
  int i = 0;
1014
1015
945k
  while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
1016
586k
    if (Code > LZ_MAX_CODE) {
1017
88.1k
      return NO_SUCH_CODE;
1018
88.1k
    }
1019
498k
    Code = Prefix[Code];
1020
498k
  }
1021
359k
  return Code;
1022
447k
}
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
424k
static int DGifDecompressInput(GifFileType *GifFile, int *Code) {
1069
424k
  static const unsigned short CodeMasks[] = {
1070
424k
      0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f,
1071
424k
      0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff};
1072
1073
424k
  GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
1074
1075
424k
  GifByteType NextByte;
1076
1077
  /* The image can't contain more than LZ_BITS per code. */
1078
424k
  if (Private->RunningBits > LZ_BITS) {
1079
0
    GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1080
0
    return GIF_ERROR;
1081
0
  }
1082
1083
934k
  while (Private->CrntShiftState < Private->RunningBits) {
1084
    /* Needs to get more bytes from input stream for next code: */
1085
510k
    if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) ==
1086
510k
        GIF_ERROR) {
1087
277
      return GIF_ERROR;
1088
277
    }
1089
509k
    Private->CrntShiftDWord |= ((unsigned long)NextByte)
1090
509k
                               << Private->CrntShiftState;
1091
509k
    Private->CrntShiftState += 8;
1092
509k
  }
1093
424k
  *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
1094
1095
424k
  Private->CrntShiftDWord >>= Private->RunningBits;
1096
424k
  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
424k
  if (Private->RunningCode < LZ_MAX_CODE + 2 &&
1104
423k
      ++Private->RunningCode > Private->MaxCode1 &&
1105
5.67k
      Private->RunningBits < LZ_BITS) {
1106
5.61k
    Private->MaxCode1 <<= 1;
1107
5.61k
    Private->RunningBits++;
1108
5.61k
  }
1109
424k
  return GIF_OK;
1110
424k
}
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
510k
                             GifByteType *NextByte) {
1120
510k
  if (Buf[0] == 0) {
1121
    /* Needs to read the next buffer - this one is empty: */
1122
    /* coverity[check_return] */
1123
11.0k
    if (InternalRead(GifFile, Buf, 1) != 1) {
1124
78
      GifFile->Error = D_GIF_ERR_READ_FAILED;
1125
78
      return GIF_ERROR;
1126
78
    }
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
10.9k
    if (Buf[0] == 0) {
1132
113
      GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
1133
113
      return GIF_ERROR;
1134
113
    }
1135
10.8k
    if (InternalRead(GifFile, &Buf[1], Buf[0]) != Buf[0]) {
1136
86
      GifFile->Error = D_GIF_ERR_READ_FAILED;
1137
86
      return GIF_ERROR;
1138
86
    }
1139
10.7k
    *NextByte = Buf[1];
1140
10.7k
    Buf[1] = 2; /* We use now the second place as last char read! */
1141
10.7k
    Buf[0]--;
1142
499k
  } else {
1143
499k
    *NextByte = Buf[Buf[1]++];
1144
499k
    Buf[0]--;
1145
499k
  }
1146
1147
509k
  return GIF_OK;
1148
510k
}
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
397
void DGifDecreaseImageCounter(GifFileType *GifFile) {
1157
397
  GifFile->ImageCount--;
1158
397
  if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) {
1159
378
    free(GifFile->SavedImages[GifFile->ImageCount].RasterBits);
1160
378
  }
1161
397
  if (GifFile->SavedImages[GifFile->ImageCount].ImageDesc.ColorMap != NULL) {
1162
13
    GifFreeMapObject(GifFile->SavedImages[GifFile->ImageCount].ImageDesc.ColorMap);
1163
13
  }
1164
1165
  // Avoid a dodgy edge casse in reallocarray() */
1166
397
  if (GifFile->ImageCount <= 0) {
1167
372
    free(GifFile->SavedImages);
1168
372
    GifFile->SavedImages = NULL;
1169
372
    GifFile->ImageCount = 0;
1170
372
    return;
1171
372
  }
1172
1173
  /* Realloc array according to the new image counter. */
1174
25
  SavedImage *correct_saved_images = (SavedImage *)reallocarray(
1175
25
      GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage));
1176
25
  if (correct_saved_images != NULL) {
1177
25
    GifFile->SavedImages = correct_saved_images;
1178
25
  }
1179
25
}
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.02k
int DGifSlurp(GifFileType *GifFile) {
1187
1.02k
  size_t ImageSize;
1188
1.02k
  GifRecordType RecordType;
1189
1.02k
  SavedImage *sp;
1190
1.02k
  GifByteType *ExtData;
1191
1.02k
  int ExtFunction;
1192
1193
1.02k
  GifFile->ExtensionBlocks = NULL;
1194
1.02k
  GifFile->ExtensionBlockCount = 0;
1195
1196
8.09k
  do {
1197
8.09k
    if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
1198
120
      return (GIF_ERROR);
1199
120
    }
1200
1201
7.97k
    switch (RecordType) {
1202
4.51k
    case IMAGE_DESC_RECORD_TYPE:
1203
4.51k
      if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
1204
185
        return (GIF_ERROR);
1205
185
      }
1206
1207
4.33k
      sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
1208
      /* Allocate memory for the image */
1209
4.33k
      if (sp->ImageDesc.Width <= 0 ||
1210
4.33k
          sp->ImageDesc.Height <= 0 ||
1211
4.33k
          sp->ImageDesc.Width >
1212
4.33k
              (INT_MAX / sp->ImageDesc.Height)) {
1213
19
        DGifDecreaseImageCounter(GifFile);
1214
19
        return GIF_ERROR;
1215
19
      }
1216
4.31k
      ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
1217
1218
4.31k
      if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
1219
0
        DGifDecreaseImageCounter(GifFile);
1220
0
        return GIF_ERROR;
1221
0
      }
1222
4.31k
      sp->RasterBits = (unsigned char *)reallocarray(
1223
4.31k
          NULL, ImageSize, sizeof(GifPixelType));
1224
1225
4.31k
      if (sp->RasterBits == NULL) {
1226
0
        DGifDecreaseImageCounter(GifFile);
1227
0
        return GIF_ERROR;
1228
0
      }
1229
1230
4.31k
      if (sp->ImageDesc.Interlace) {
1231
3.93k
        int i, j;
1232
        /*
1233
         * The way an interlaced image should be read -
1234
         * offsets and jumps...
1235
         */
1236
3.93k
        static const int InterlacedOffset[] = {0, 4, 2,
1237
3.93k
                                               1};
1238
3.93k
        static const int InterlacedJumps[] = {8, 8, 4,
1239
3.93k
                                              2};
1240
        /* Need to perform 4 passes on the image */
1241
18.8k
        for (i = 0; i < 4; i++) {
1242
15.1k
          for (j = InterlacedOffset[i];
1243
404k
               j < sp->ImageDesc.Height;
1244
390k
               j += InterlacedJumps[i]) {
1245
390k
            if (DGifGetLine(
1246
390k
                    GifFile,
1247
390k
                    sp->RasterBits +
1248
390k
                        j * sp->ImageDesc
1249
390k
                                .Width,
1250
390k
                    sp->ImageDesc.Width) ==
1251
390k
                GIF_ERROR) {
1252
216
              DGifDecreaseImageCounter(
1253
216
                  GifFile);
1254
216
              return GIF_ERROR;
1255
216
            }
1256
390k
          }
1257
15.1k
        }
1258
3.93k
      } else {
1259
377
        if (DGifGetLine(GifFile, sp->RasterBits,
1260
377
                        ImageSize) == GIF_ERROR) {
1261
162
          DGifDecreaseImageCounter(GifFile);
1262
162
          return GIF_ERROR;
1263
162
        }
1264
377
      }
1265
1266
3.93k
      if (GifFile->ExtensionBlocks) {
1267
501
        sp->ExtensionBlocks = GifFile->ExtensionBlocks;
1268
501
        sp->ExtensionBlockCount =
1269
501
            GifFile->ExtensionBlockCount;
1270
1271
501
        GifFile->ExtensionBlocks = NULL;
1272
501
        GifFile->ExtensionBlockCount = 0;
1273
501
      }
1274
3.93k
      break;
1275
1276
3.25k
    case EXTENSION_RECORD_TYPE:
1277
3.25k
      if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) ==
1278
3.25k
          GIF_ERROR) {
1279
14
        return (GIF_ERROR);
1280
14
      }
1281
      /* Create an extension block with our data */
1282
3.24k
      if (ExtData != NULL) {
1283
1.78k
        if (GifAddExtensionBlock(
1284
1.78k
                &GifFile->ExtensionBlockCount,
1285
1.78k
                &GifFile->ExtensionBlocks, ExtFunction,
1286
1.78k
                ExtData[0], &ExtData[1]) == GIF_ERROR) {
1287
0
          return (GIF_ERROR);
1288
0
        }
1289
1.78k
      }
1290
24.9k
      for (;;) {
1291
24.9k
        if (DGifGetExtensionNext(GifFile, &ExtData) ==
1292
24.9k
            GIF_ERROR) {
1293
100
          return (GIF_ERROR);
1294
100
        }
1295
24.8k
        if (ExtData == NULL) {
1296
3.14k
          break;
1297
3.14k
        }
1298
        /* Continue the extension block */
1299
21.7k
        if (GifAddExtensionBlock(
1300
21.7k
                &GifFile->ExtensionBlockCount,
1301
21.7k
                &GifFile->ExtensionBlocks,
1302
21.7k
                CONTINUE_EXT_FUNC_CODE, ExtData[0],
1303
21.7k
                &ExtData[1]) == GIF_ERROR) {
1304
0
          return (GIF_ERROR);
1305
0
        }
1306
21.7k
      }
1307
3.14k
      break;
1308
1309
3.14k
    case TERMINATE_RECORD_TYPE:
1310
205
      break;
1311
1312
0
    default: /* Should be trapped by DGifGetRecordType */
1313
0
      break;
1314
7.97k
    }
1315
7.97k
  } while (RecordType != TERMINATE_RECORD_TYPE);
1316
1317
  /* Sanity check for corrupted file */
1318
205
  if (GifFile->ImageCount == 0) {
1319
78
    GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
1320
78
    return (GIF_ERROR);
1321
78
  }
1322
1323
127
  return (GIF_OK);
1324
205
}
1325
1326
/* end */