Coverage Report

Created: 2025-06-13 06:08

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