/src/libjpeg-turbo.2.1.x/rdgif.c
| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * rdgif.c | 
| 3 |  |  * | 
| 4 |  |  * This file was part of the Independent JPEG Group's software: | 
| 5 |  |  * Copyright (C) 1991-1997, Thomas G. Lane. | 
| 6 |  |  * Modified 2019 by Guido Vollbeding. | 
| 7 |  |  * libjpeg-turbo Modifications: | 
| 8 |  |  * Copyright (C) 2021-2022, D. R. Commander. | 
| 9 |  |  * For conditions of distribution and use, see the accompanying README.ijg | 
| 10 |  |  * file. | 
| 11 |  |  * | 
| 12 |  |  * This file contains routines to read input images in GIF format. | 
| 13 |  |  * | 
| 14 |  |  * These routines may need modification for non-Unix environments or | 
| 15 |  |  * specialized applications.  As they stand, they assume input from | 
| 16 |  |  * an ordinary stdio stream.  They further assume that reading begins | 
| 17 |  |  * at the start of the file; start_input may need work if the | 
| 18 |  |  * user interface has already read some data (e.g., to determine that | 
| 19 |  |  * the file is indeed GIF format). | 
| 20 |  |  */ | 
| 21 |  |  | 
| 22 |  | /* | 
| 23 |  |  * This code is loosely based on giftoppm from the PBMPLUS distribution | 
| 24 |  |  * of Feb. 1991.  That file contains the following copyright notice: | 
| 25 |  |  * +-------------------------------------------------------------------+ | 
| 26 |  |  * | Copyright 1990, David Koblas.                                     | | 
| 27 |  |  * |   Permission to use, copy, modify, and distribute this software   | | 
| 28 |  |  * |   and its documentation for any purpose and without fee is hereby | | 
| 29 |  |  * |   granted, provided that the above copyright notice appear in all | | 
| 30 |  |  * |   copies and that both that copyright notice and this permission  | | 
| 31 |  |  * |   notice appear in supporting documentation.  This software is    | | 
| 32 |  |  * |   provided "as is" without express or implied warranty.           | | 
| 33 |  |  * +-------------------------------------------------------------------+ | 
| 34 |  |  */ | 
| 35 |  |  | 
| 36 |  | #include "cdjpeg.h"             /* Common decls for cjpeg/djpeg applications */ | 
| 37 |  |  | 
| 38 |  | #ifdef GIF_SUPPORTED | 
| 39 |  |  | 
| 40 |  |  | 
| 41 |  | /* Macros to deal with unsigned chars as efficiently as compiler allows */ | 
| 42 |  |  | 
| 43 |  | typedef unsigned char U_CHAR; | 
| 44 | 3.14M | #define UCH(x)  ((int)(x)) | 
| 45 |  |  | 
| 46 |  |  | 
| 47 |  | #define ReadOK(file, buffer, len) \ | 
| 48 | 19.5k |   (fread(buffer, 1, len, file) == ((size_t)(len))) | 
| 49 |  |  | 
| 50 |  |  | 
| 51 | 1.88k | #define MAXCOLORMAPSIZE  256    /* max # of colors in a GIF colormap */ | 
| 52 | 2.93k | #define NUMCOLORS        3      /* # of colors */ | 
| 53 | 156M | #define CM_RED           0      /* color component numbers */ | 
| 54 | 141M | #define CM_GREEN         1 | 
| 55 | 141M | #define CM_BLUE          2 | 
| 56 |  |  | 
| 57 | 1.04M | #define MAX_LZW_BITS     12     /* maximum LZW code size */ | 
| 58 | 1.03M | #define LZW_TABLE_SIZE   (1 << MAX_LZW_BITS) /* # of possible LZW symbols */ | 
| 59 |  |  | 
| 60 |  | /* Macros for extracting header data --- note we assume chars may be signed */ | 
| 61 |  |  | 
| 62 |  | #define LM_to_uint(array, offset) \ | 
| 63 | 6.68k |   ((unsigned int)UCH(array[offset]) + \ | 
| 64 | 6.68k |    (((unsigned int)UCH(array[offset + 1])) << 8)) | 
| 65 |  |  | 
| 66 | 4.80k | #define BitSet(byte, bit)       ((byte) & (bit)) | 
| 67 |  | #define INTERLACE       0x40    /* mask for bit signifying interlaced image */ | 
| 68 |  | #define COLORMAPFLAG    0x80    /* mask for bit signifying colormap presence */ | 
| 69 |  |  | 
| 70 |  |  | 
| 71 |  | /* | 
| 72 |  |  * LZW decompression tables look like this: | 
| 73 |  |  *   symbol_head[K] = prefix symbol of any LZW symbol K (0..LZW_TABLE_SIZE-1) | 
| 74 |  |  *   symbol_tail[K] = suffix byte   of any LZW symbol K (0..LZW_TABLE_SIZE-1) | 
| 75 |  |  * Note that entries 0..end_code of the above tables are not used, | 
| 76 |  |  * since those symbols represent raw bytes or special codes. | 
| 77 |  |  * | 
| 78 |  |  * The stack represents the not-yet-used expansion of the last LZW symbol. | 
| 79 |  |  * In the worst case, a symbol could expand to as many bytes as there are | 
| 80 |  |  * LZW symbols, so we allocate LZW_TABLE_SIZE bytes for the stack. | 
| 81 |  |  * (This is conservative since that number includes the raw-byte symbols.) | 
| 82 |  |  */ | 
| 83 |  |  | 
| 84 |  |  | 
| 85 |  | /* Private version of data source object */ | 
| 86 |  |  | 
| 87 |  | typedef struct { | 
| 88 |  |   struct cjpeg_source_struct pub; /* public fields */ | 
| 89 |  |  | 
| 90 |  |   j_compress_ptr cinfo;         /* back link saves passing separate parm */ | 
| 91 |  |  | 
| 92 |  |   JSAMPARRAY colormap;          /* GIF colormap (converted to my format) */ | 
| 93 |  |  | 
| 94 |  |   /* State for GetCode and LZWReadByte */ | 
| 95 |  |   U_CHAR code_buf[256 + 4];     /* current input data block */ | 
| 96 |  |   int last_byte;                /* # of bytes in code_buf */ | 
| 97 |  |   int last_bit;                 /* # of bits in code_buf */ | 
| 98 |  |   int cur_bit;                  /* next bit index to read */ | 
| 99 |  |   boolean first_time;           /* flags first call to GetCode */ | 
| 100 |  |   boolean out_of_blocks;        /* TRUE if hit terminator data block */ | 
| 101 |  |  | 
| 102 |  |   int input_code_size;          /* codesize given in GIF file */ | 
| 103 |  |   int clear_code, end_code;     /* values for Clear and End codes */ | 
| 104 |  |  | 
| 105 |  |   int code_size;                /* current actual code size */ | 
| 106 |  |   int limit_code;               /* 2^code_size */ | 
| 107 |  |   int max_code;                 /* first unused code value */ | 
| 108 |  |  | 
| 109 |  |   /* Private state for LZWReadByte */ | 
| 110 |  |   int oldcode;                  /* previous LZW symbol */ | 
| 111 |  |   int firstcode;                /* first byte of oldcode's expansion */ | 
| 112 |  |  | 
| 113 |  |   /* LZW symbol table and expansion stack */ | 
| 114 |  |   UINT16 *symbol_head;          /* => table of prefix symbols */ | 
| 115 |  |   UINT8  *symbol_tail;          /* => table of suffix bytes */ | 
| 116 |  |   UINT8  *symbol_stack;         /* => stack for symbol expansions */ | 
| 117 |  |   UINT8  *sp;                   /* stack pointer */ | 
| 118 |  |  | 
| 119 |  |   /* State for interlaced image processing */ | 
| 120 |  |   boolean is_interlaced;        /* TRUE if have interlaced image */ | 
| 121 |  |   jvirt_sarray_ptr interlaced_image; /* full image in interlaced order */ | 
| 122 |  |   JDIMENSION cur_row_number;    /* need to know actual row number */ | 
| 123 |  |   JDIMENSION pass2_offset;      /* # of pixel rows in pass 1 */ | 
| 124 |  |   JDIMENSION pass3_offset;      /* # of pixel rows in passes 1&2 */ | 
| 125 |  |   JDIMENSION pass4_offset;      /* # of pixel rows in passes 1,2,3 */ | 
| 126 |  | } gif_source_struct; | 
| 127 |  |  | 
| 128 |  | typedef gif_source_struct *gif_source_ptr; | 
| 129 |  |  | 
| 130 |  |  | 
| 131 |  | /* Forward declarations */ | 
| 132 |  | METHODDEF(JDIMENSION) get_pixel_rows(j_compress_ptr cinfo, | 
| 133 |  |                                      cjpeg_source_ptr sinfo); | 
| 134 |  | METHODDEF(JDIMENSION) load_interlaced_image(j_compress_ptr cinfo, | 
| 135 |  |                                             cjpeg_source_ptr sinfo); | 
| 136 |  | METHODDEF(JDIMENSION) get_interlaced_row(j_compress_ptr cinfo, | 
| 137 |  |                                          cjpeg_source_ptr sinfo); | 
| 138 |  |  | 
| 139 |  |  | 
| 140 |  | LOCAL(int) | 
| 141 |  | ReadByte(gif_source_ptr sinfo) | 
| 142 |  | /* Read next byte from GIF file */ | 
| 143 | 53.6k | { | 
| 144 | 53.6k |   register FILE *infile = sinfo->pub.input_file; | 
| 145 | 53.6k |   register int c; | 
| 146 |  |  | 
| 147 | 53.6k |   if ((c = getc(infile)) == EOF) | 
| 148 | 509 |     ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); | 
| 149 | 53.6k |   return c; | 
| 150 | 53.6k | } | 
| 151 |  |  | 
| 152 |  |  | 
| 153 |  | LOCAL(int) | 
| 154 |  | GetDataBlock(gif_source_ptr sinfo, U_CHAR *buf) | 
| 155 |  | /* Read a GIF data block, which has a leading count byte */ | 
| 156 |  | /* A zero-length block marks the end of a data block sequence */ | 
| 157 | 15.7k | { | 
| 158 | 15.7k |   int count; | 
| 159 |  |  | 
| 160 | 15.7k |   count = ReadByte(sinfo); | 
| 161 | 15.7k |   if (count > 0) { | 
| 162 | 14.3k |     if (!ReadOK(sinfo->pub.input_file, buf, count)) | 
| 163 | 119 |       ERREXIT(sinfo->cinfo, JERR_INPUT_EOF); | 
| 164 | 14.3k |   } | 
| 165 | 15.7k |   return count; | 
| 166 | 15.7k | } | 
| 167 |  |  | 
| 168 |  |  | 
| 169 |  | LOCAL(void) | 
| 170 |  | SkipDataBlocks(gif_source_ptr sinfo) | 
| 171 |  | /* Skip a series of data blocks, until a block terminator is found */ | 
| 172 | 564 | { | 
| 173 | 564 |   U_CHAR buf[256]; | 
| 174 |  |  | 
| 175 | 1.09k |   while (GetDataBlock(sinfo, buf) > 0) | 
| 176 | 532 |     /* skip */; | 
| 177 | 564 | } | 
| 178 |  |  | 
| 179 |  |  | 
| 180 |  | LOCAL(void) | 
| 181 |  | ReInitLZW(gif_source_ptr sinfo) | 
| 182 |  | /* (Re)initialize LZW state; shared code for startup and Clear processing */ | 
| 183 | 7.74k | { | 
| 184 | 7.74k |   sinfo->code_size = sinfo->input_code_size + 1; | 
| 185 | 7.74k |   sinfo->limit_code = sinfo->clear_code << 1;   /* 2^code_size */ | 
| 186 | 7.74k |   sinfo->max_code = sinfo->clear_code + 2;      /* first unused code value */ | 
| 187 | 7.74k |   sinfo->sp = sinfo->symbol_stack;              /* init stack to empty */ | 
| 188 | 7.74k | } | 
| 189 |  |  | 
| 190 |  |  | 
| 191 |  | LOCAL(void) | 
| 192 |  | InitLZWCode(gif_source_ptr sinfo) | 
| 193 |  | /* Initialize for a series of LZWReadByte (and hence GetCode) calls */ | 
| 194 | 1.25k | { | 
| 195 |  |   /* GetCode initialization */ | 
| 196 | 1.25k |   sinfo->last_byte = 2;         /* make safe to "recopy last two bytes" */ | 
| 197 | 1.25k |   sinfo->code_buf[0] = 0; | 
| 198 | 1.25k |   sinfo->code_buf[1] = 0; | 
| 199 | 1.25k |   sinfo->last_bit = 0;          /* nothing in the buffer */ | 
| 200 | 1.25k |   sinfo->cur_bit = 0;           /* force buffer load on first call */ | 
| 201 | 1.25k |   sinfo->first_time = TRUE; | 
| 202 | 1.25k |   sinfo->out_of_blocks = FALSE; | 
| 203 |  |  | 
| 204 |  |   /* LZWReadByte initialization: */ | 
| 205 |  |   /* compute special code values (note that these do not change later) */ | 
| 206 | 1.25k |   sinfo->clear_code = 1 << sinfo->input_code_size; | 
| 207 | 1.25k |   sinfo->end_code = sinfo->clear_code + 1; | 
| 208 | 1.25k |   ReInitLZW(sinfo); | 
| 209 | 1.25k | } | 
| 210 |  |  | 
| 211 |  |  | 
| 212 |  | LOCAL(int) | 
| 213 |  | GetCode(gif_source_ptr sinfo) | 
| 214 |  | /* Fetch the next code_size bits from the GIF data */ | 
| 215 |  | /* We assume code_size is less than 16 */ | 
| 216 | 153M | { | 
| 217 | 153M |   register int accum; | 
| 218 | 153M |   int offs, count; | 
| 219 |  |  | 
| 220 | 153M |   while (sinfo->cur_bit + sinfo->code_size > sinfo->last_bit) { | 
| 221 |  |     /* Time to reload the buffer */ | 
| 222 |  |     /* First time, share code with Clear case */ | 
| 223 | 152M |     if (sinfo->first_time) { | 
| 224 | 1.15k |       sinfo->first_time = FALSE; | 
| 225 | 1.15k |       return sinfo->clear_code; | 
| 226 | 1.15k |     } | 
| 227 | 152M |     if (sinfo->out_of_blocks) { | 
| 228 | 152M |       WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); | 
| 229 | 152M |       return sinfo->end_code;   /* fake something useful */ | 
| 230 | 152M |     } | 
| 231 |  |     /* preserve last two bytes of what we have -- assume code_size <= 16 */ | 
| 232 | 14.6k |     sinfo->code_buf[0] = sinfo->code_buf[sinfo->last_byte-2]; | 
| 233 | 14.6k |     sinfo->code_buf[1] = sinfo->code_buf[sinfo->last_byte-1]; | 
| 234 |  |     /* Load more bytes; set flag if we reach the terminator block */ | 
| 235 | 14.6k |     if ((count = GetDataBlock(sinfo, &sinfo->code_buf[2])) == 0) { | 
| 236 | 672 |       sinfo->out_of_blocks = TRUE; | 
| 237 | 672 |       WARNMS(sinfo->cinfo, JWRN_GIF_NOMOREDATA); | 
| 238 | 672 |       return sinfo->end_code;   /* fake something useful */ | 
| 239 | 672 |     } | 
| 240 |  |     /* Reset counters */ | 
| 241 | 13.9k |     sinfo->cur_bit = (sinfo->cur_bit - sinfo->last_bit) + 16; | 
| 242 | 13.9k |     sinfo->last_byte = 2 + count; | 
| 243 | 13.9k |     sinfo->last_bit = sinfo->last_byte * 8; | 
| 244 | 13.9k |   } | 
| 245 |  |  | 
| 246 |  |   /* Form up next 24 bits in accum */ | 
| 247 | 1.04M |   offs = sinfo->cur_bit >> 3;   /* byte containing cur_bit */ | 
| 248 | 1.04M |   accum = UCH(sinfo->code_buf[offs + 2]); | 
| 249 | 1.04M |   accum <<= 8; | 
| 250 | 1.04M |   accum |= UCH(sinfo->code_buf[offs + 1]); | 
| 251 | 1.04M |   accum <<= 8; | 
| 252 | 1.04M |   accum |= UCH(sinfo->code_buf[offs]); | 
| 253 |  |  | 
| 254 |  |   /* Right-align cur_bit in accum, then mask off desired number of bits */ | 
| 255 | 1.04M |   accum >>= (sinfo->cur_bit & 7); | 
| 256 | 1.04M |   sinfo->cur_bit += sinfo->code_size; | 
| 257 | 1.04M |   return accum & ((1 << sinfo->code_size) - 1); | 
| 258 | 153M | } | 
| 259 |  |  | 
| 260 |  |  | 
| 261 |  | LOCAL(int) | 
| 262 |  | LZWReadByte(gif_source_ptr sinfo) | 
| 263 |  | /* Read an LZW-compressed byte */ | 
| 264 | 157M | { | 
| 265 | 157M |   register int code;            /* current working code */ | 
| 266 | 157M |   int incode;                   /* saves actual input code */ | 
| 267 |  |  | 
| 268 |  |   /* If any codes are stacked from a previously read symbol, return them */ | 
| 269 | 157M |   if (sinfo->sp > sinfo->symbol_stack) | 
| 270 | 3.87M |     return (int)(*(--sinfo->sp)); | 
| 271 |  |  | 
| 272 |  |   /* Time to read a new symbol */ | 
| 273 | 153M |   code = GetCode(sinfo); | 
| 274 |  |  | 
| 275 | 153M |   if (code == sinfo->clear_code) { | 
| 276 |  |     /* Reinit state, swallow any extra Clear codes, and */ | 
| 277 |  |     /* return next code, which is expected to be a raw byte. */ | 
| 278 | 6.48k |     ReInitLZW(sinfo); | 
| 279 | 8.28k |     do { | 
| 280 | 8.28k |       code = GetCode(sinfo); | 
| 281 | 8.28k |     } while (code == sinfo->clear_code); | 
| 282 | 6.48k |     if (code > sinfo->clear_code) { /* make sure it is a raw byte */ | 
| 283 | 1.08k |       WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); | 
| 284 | 1.08k |       code = 0;                 /* use something valid */ | 
| 285 | 1.08k |     } | 
| 286 |  |     /* make firstcode, oldcode valid! */ | 
| 287 | 6.48k |     sinfo->firstcode = sinfo->oldcode = code; | 
| 288 | 6.48k |     return code; | 
| 289 | 6.48k |   } | 
| 290 |  |  | 
| 291 | 153M |   if (code == sinfo->end_code) { | 
| 292 |  |     /* Skip the rest of the image, unless GetCode already read terminator */ | 
| 293 | 152M |     if (!sinfo->out_of_blocks) { | 
| 294 | 180 |       SkipDataBlocks(sinfo); | 
| 295 | 180 |       sinfo->out_of_blocks = TRUE; | 
| 296 | 180 |     } | 
| 297 |  |     /* Complain that there's not enough data */ | 
| 298 | 152M |     WARNMS(sinfo->cinfo, JWRN_GIF_ENDCODE); | 
| 299 |  |     /* Pad data with 0's */ | 
| 300 | 152M |     return 0;                   /* fake something usable */ | 
| 301 | 152M |   } | 
| 302 |  |  | 
| 303 |  |   /* Got normal raw byte or LZW symbol */ | 
| 304 | 1.02M |   incode = code;                /* save for a moment */ | 
| 305 |  |  | 
| 306 | 1.02M |   if (code >= sinfo->max_code) { /* special case for not-yet-defined symbol */ | 
| 307 |  |     /* code == max_code is OK; anything bigger is bad data */ | 
| 308 | 139k |     if (code > sinfo->max_code) { | 
| 309 | 133k |       WARNMS(sinfo->cinfo, JWRN_GIF_BADDATA); | 
| 310 | 133k |       incode = 0;               /* prevent creation of loops in symbol table */ | 
| 311 | 133k |     } | 
| 312 |  |     /* this symbol will be defined as oldcode/firstcode */ | 
| 313 | 139k |     *(sinfo->sp++) = (UINT8)sinfo->firstcode; | 
| 314 | 139k |     code = sinfo->oldcode; | 
| 315 | 139k |   } | 
| 316 |  |  | 
| 317 |  |   /* If it's a symbol, expand it into the stack */ | 
| 318 | 4.76M |   while (code >= sinfo->clear_code) { | 
| 319 | 3.73M |     *(sinfo->sp++) = sinfo->symbol_tail[code]; /* tail is a byte value */ | 
| 320 | 3.73M |     code = sinfo->symbol_head[code]; /* head is another LZW symbol */ | 
| 321 | 3.73M |   } | 
| 322 |  |   /* At this point code just represents a raw byte */ | 
| 323 | 1.02M |   sinfo->firstcode = code;      /* save for possible future use */ | 
| 324 |  |  | 
| 325 |  |   /* If there's room in table... */ | 
| 326 | 1.02M |   if ((code = sinfo->max_code) < LZW_TABLE_SIZE) { | 
| 327 |  |     /* Define a new symbol = prev sym + head of this sym's expansion */ | 
| 328 | 858k |     sinfo->symbol_head[code] = (UINT16)sinfo->oldcode; | 
| 329 | 858k |     sinfo->symbol_tail[code] = (UINT8)sinfo->firstcode; | 
| 330 | 858k |     sinfo->max_code++; | 
| 331 |  |     /* Is it time to increase code_size? */ | 
| 332 | 858k |     if (sinfo->max_code >= sinfo->limit_code && | 
| 333 | 858k |         sinfo->code_size < MAX_LZW_BITS) { | 
| 334 | 7.60k |       sinfo->code_size++; | 
| 335 | 7.60k |       sinfo->limit_code <<= 1;  /* keep equal to 2^code_size */ | 
| 336 | 7.60k |     } | 
| 337 | 858k |   } | 
| 338 |  |  | 
| 339 | 1.02M |   sinfo->oldcode = incode;      /* save last input symbol for future use */ | 
| 340 | 1.02M |   return sinfo->firstcode;      /* return first byte of symbol's expansion */ | 
| 341 | 153M | } | 
| 342 |  |  | 
| 343 |  |  | 
| 344 |  | LOCAL(void) | 
| 345 |  | ReadColorMap(gif_source_ptr sinfo, int cmaplen, JSAMPARRAY cmap) | 
| 346 |  | /* Read a GIF colormap */ | 
| 347 | 1.01k | { | 
| 348 | 1.01k |   int i, gray = 1; | 
| 349 |  |  | 
| 350 | 7.89k |   for (i = 0; i < cmaplen; i++) { | 
| 351 | 6.88k | #if BITS_IN_JSAMPLE == 8 | 
| 352 | 20.6k | #define UPSCALE(x)  (x) | 
| 353 |  | #else | 
| 354 |  | #define UPSCALE(x)  ((x) << (BITS_IN_JSAMPLE - 8)) | 
| 355 |  | #endif | 
| 356 | 6.88k |     cmap[CM_RED][i]   = (JSAMPLE)UPSCALE(ReadByte(sinfo)); | 
| 357 | 6.88k |     cmap[CM_GREEN][i] = (JSAMPLE)UPSCALE(ReadByte(sinfo)); | 
| 358 | 6.88k |     cmap[CM_BLUE][i]  = (JSAMPLE)UPSCALE(ReadByte(sinfo)); | 
| 359 | 6.88k |     if (cmap[CM_RED][i] != cmap[CM_GREEN][i] || | 
| 360 | 6.88k |         cmap[CM_GREEN][i] != cmap[CM_BLUE][i]) | 
| 361 | 4.27k |       gray = 0; | 
| 362 | 6.88k |   } | 
| 363 |  |  | 
| 364 | 1.01k |   if (sinfo->cinfo->in_color_space == JCS_RGB && gray) { | 
| 365 | 214 |     sinfo->cinfo->in_color_space = JCS_GRAYSCALE; | 
| 366 | 214 |     sinfo->cinfo->input_components = 1; | 
| 367 | 214 |   } | 
| 368 | 1.01k | } | 
| 369 |  |  | 
| 370 |  |  | 
| 371 |  | LOCAL(void) | 
| 372 |  | DoExtension(gif_source_ptr sinfo) | 
| 373 |  | /* Process an extension block */ | 
| 374 |  | /* Currently we ignore 'em all */ | 
| 375 | 388 | { | 
| 376 | 388 |   int extlabel; | 
| 377 |  |  | 
| 378 |  |   /* Read extension label byte */ | 
| 379 | 388 |   extlabel = ReadByte(sinfo); | 
| 380 | 388 |   TRACEMS1(sinfo->cinfo, 1, JTRC_GIF_EXTENSION, extlabel); | 
| 381 |  |   /* Skip the data block(s) associated with the extension */ | 
| 382 | 388 |   SkipDataBlocks(sinfo); | 
| 383 | 388 | } | 
| 384 |  |  | 
| 385 |  |  | 
| 386 |  | /* | 
| 387 |  |  * Read the file header; return image size and component count. | 
| 388 |  |  */ | 
| 389 |  |  | 
| 390 |  | METHODDEF(void) | 
| 391 |  | start_input_gif(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | 
| 392 | 1.88k | { | 
| 393 | 1.88k |   gif_source_ptr source = (gif_source_ptr)sinfo; | 
| 394 | 1.88k |   U_CHAR hdrbuf[10];            /* workspace for reading control blocks */ | 
| 395 | 1.88k |   unsigned int width, height;   /* image dimensions */ | 
| 396 | 1.88k |   int colormaplen, aspectRatio; | 
| 397 | 1.88k |   int c; | 
| 398 |  |  | 
| 399 |  |   /* Read and verify GIF Header */ | 
| 400 | 1.88k |   if (!ReadOK(source->pub.input_file, hdrbuf, 6)) | 
| 401 | 8 |     ERREXIT(cinfo, JERR_GIF_NOT); | 
| 402 | 1.88k |   if (hdrbuf[0] != 'G' || hdrbuf[1] != 'I' || hdrbuf[2] != 'F') | 
| 403 | 50 |     ERREXIT(cinfo, JERR_GIF_NOT); | 
| 404 |  |   /* Check for expected version numbers. | 
| 405 |  |    * If unknown version, give warning and try to process anyway; | 
| 406 |  |    * this is per recommendation in GIF89a standard. | 
| 407 |  |    */ | 
| 408 | 1.88k |   if ((hdrbuf[3] != '8' || hdrbuf[4] != '7' || hdrbuf[5] != 'a') && | 
| 409 | 1.88k |       (hdrbuf[3] != '8' || hdrbuf[4] != '9' || hdrbuf[5] != 'a')) | 
| 410 | 1.88k |     TRACEMS3(cinfo, 1, JTRC_GIF_BADVERSION, hdrbuf[3], hdrbuf[4], hdrbuf[5]); | 
| 411 |  |  | 
| 412 |  |   /* Read and decipher Logical Screen Descriptor */ | 
| 413 | 1.88k |   if (!ReadOK(source->pub.input_file, hdrbuf, 7)) | 
| 414 | 90 |     ERREXIT(cinfo, JERR_INPUT_EOF); | 
| 415 | 1.88k |   width = LM_to_uint(hdrbuf, 0); | 
| 416 | 1.88k |   height = LM_to_uint(hdrbuf, 2); | 
| 417 | 1.88k |   if (width == 0 || height == 0) | 
| 418 | 6 |     ERREXIT(cinfo, JERR_GIF_EMPTY); | 
| 419 | 1.88k | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 
| 420 | 1.88k |   if (sinfo->max_pixels && | 
| 421 | 1.88k |       (unsigned long long)width * height > sinfo->max_pixels) | 
| 422 | 82 |     ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); | 
| 423 | 1.88k | #endif | 
| 424 |  |   /* we ignore the color resolution, sort flag, and background color index */ | 
| 425 | 1.88k |   aspectRatio = UCH(hdrbuf[6]); | 
| 426 | 1.88k |   if (aspectRatio != 0 && aspectRatio != 49) | 
| 427 | 692 |     TRACEMS(cinfo, 1, JTRC_GIF_NONSQUARE); | 
| 428 |  |  | 
| 429 |  |   /* Allocate space to store the colormap */ | 
| 430 | 1.88k |   source->colormap = (*cinfo->mem->alloc_sarray) | 
| 431 | 1.88k |     ((j_common_ptr)cinfo, JPOOL_IMAGE, (JDIMENSION)MAXCOLORMAPSIZE, | 
| 432 | 1.88k |      (JDIMENSION)NUMCOLORS); | 
| 433 | 1.88k |   colormaplen = 0;              /* indicate initialization */ | 
| 434 |  |  | 
| 435 |  |   /* Read global colormap if header indicates it is present */ | 
| 436 | 1.88k |   if (BitSet(hdrbuf[4], COLORMAPFLAG)) { | 
| 437 | 874 |     colormaplen = 2 << (hdrbuf[4] & 0x07); | 
| 438 | 874 |     ReadColorMap(source, colormaplen, source->colormap); | 
| 439 | 874 |   } | 
| 440 |  |  | 
| 441 |  |   /* Scan until we reach start of desired image. | 
| 442 |  |    * We don't currently support skipping images, but could add it easily. | 
| 443 |  |    */ | 
| 444 | 15.7k |   for (;;) { | 
| 445 | 15.7k |     c = ReadByte(source); | 
| 446 |  |  | 
| 447 | 15.7k |     if (c == ';')               /* GIF terminator?? */ | 
| 448 | 2 |       ERREXIT(cinfo, JERR_GIF_IMAGENOTFOUND); | 
| 449 |  |  | 
| 450 | 15.7k |     if (c == '!') {             /* Extension */ | 
| 451 | 388 |       DoExtension(source); | 
| 452 | 388 |       continue; | 
| 453 | 388 |     } | 
| 454 |  |  | 
| 455 | 15.3k |     if (c != ',') {             /* Not an image separator? */ | 
| 456 | 13.9k |       WARNMS1(cinfo, JWRN_GIF_CHAR, c); | 
| 457 | 13.9k |       continue; | 
| 458 | 13.9k |     } | 
| 459 |  |  | 
| 460 |  |     /* Read and decipher Local Image Descriptor */ | 
| 461 | 1.46k |     if (!ReadOK(source->pub.input_file, hdrbuf, 9)) | 
| 462 | 4 |       ERREXIT(cinfo, JERR_INPUT_EOF); | 
| 463 |  |     /* we ignore top/left position info, also sort flag */ | 
| 464 | 1.46k |     width = LM_to_uint(hdrbuf, 4); | 
| 465 | 1.46k |     height = LM_to_uint(hdrbuf, 6); | 
| 466 | 1.46k |     if (width == 0 || height == 0) | 
| 467 | 4 |       ERREXIT(cinfo, JERR_GIF_EMPTY); | 
| 468 | 1.46k | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 
| 469 | 1.46k |     if (sinfo->max_pixels && | 
| 470 | 1.46k |         (unsigned long long)width * height > sinfo->max_pixels) | 
| 471 | 76 |       ERREXIT(cinfo, JERR_WIDTH_OVERFLOW); | 
| 472 | 1.46k | #endif | 
| 473 | 1.46k |     source->is_interlaced = (BitSet(hdrbuf[8], INTERLACE) != 0); | 
| 474 |  |  | 
| 475 |  |     /* Read local colormap if header indicates it is present */ | 
| 476 |  |     /* Note: if we wanted to support skipping images, */ | 
| 477 |  |     /* we'd need to skip rather than read colormap for ignored images */ | 
| 478 | 1.46k |     if (BitSet(hdrbuf[8], COLORMAPFLAG)) { | 
| 479 | 138 |       colormaplen = 2 << (hdrbuf[8] & 0x07); | 
| 480 | 138 |       ReadColorMap(source, colormaplen, source->colormap); | 
| 481 | 138 |     } | 
| 482 |  |  | 
| 483 | 1.46k |     source->input_code_size = ReadByte(source); /* get min-code-size byte */ | 
| 484 | 1.46k |     if (source->input_code_size < 2 || source->input_code_size > 8) | 
| 485 | 12 |       ERREXIT1(cinfo, JERR_GIF_CODESIZE, source->input_code_size); | 
| 486 |  |  | 
| 487 |  |     /* Reached desired image, so break out of loop */ | 
| 488 |  |     /* If we wanted to skip this image, */ | 
| 489 |  |     /* we'd call SkipDataBlocks and then continue the loop */ | 
| 490 | 1.46k |     break; | 
| 491 | 15.3k |   } | 
| 492 |  |  | 
| 493 |  |   /* Prepare to read selected image: first initialize LZW decompressor */ | 
| 494 | 1.88k |   source->symbol_head = (UINT16 *) | 
| 495 | 1.88k |     (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, | 
| 496 | 1.88k |                                 LZW_TABLE_SIZE * sizeof(UINT16)); | 
| 497 | 1.88k |   source->symbol_tail = (UINT8 *) | 
| 498 | 1.88k |     (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, | 
| 499 | 1.88k |                                 LZW_TABLE_SIZE * sizeof(UINT8)); | 
| 500 | 1.88k |   source->symbol_stack = (UINT8 *) | 
| 501 | 1.88k |     (*cinfo->mem->alloc_large) ((j_common_ptr)cinfo, JPOOL_IMAGE, | 
| 502 | 1.88k |                                 LZW_TABLE_SIZE * sizeof(UINT8)); | 
| 503 | 1.88k |   InitLZWCode(source); | 
| 504 |  |  | 
| 505 |  |   /* | 
| 506 |  |    * If image is interlaced, we read it into a full-size sample array, | 
| 507 |  |    * decompressing as we go; then get_interlaced_row selects rows from the | 
| 508 |  |    * sample array in the proper order. | 
| 509 |  |    */ | 
| 510 | 1.88k |   if (source->is_interlaced) { | 
| 511 |  |     /* We request the virtual array now, but can't access it until virtual | 
| 512 |  |      * arrays have been allocated.  Hence, the actual work of reading the | 
| 513 |  |      * image is postponed until the first call to get_pixel_rows. | 
| 514 |  |      */ | 
| 515 | 846 |     source->interlaced_image = (*cinfo->mem->request_virt_sarray) | 
| 516 | 846 |       ((j_common_ptr)cinfo, JPOOL_IMAGE, FALSE, | 
| 517 | 846 |        (JDIMENSION)width, (JDIMENSION)height, (JDIMENSION)1); | 
| 518 | 846 |     if (cinfo->progress != NULL) { | 
| 519 | 0 |       cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; | 
| 520 | 0 |       progress->total_extra_passes++; /* count file input as separate pass */ | 
| 521 | 0 |     } | 
| 522 | 846 |     source->pub.get_pixel_rows = load_interlaced_image; | 
| 523 | 1.03k |   } else { | 
| 524 | 1.03k |     source->pub.get_pixel_rows = get_pixel_rows; | 
| 525 | 1.03k |   } | 
| 526 |  |  | 
| 527 | 1.88k |   if (cinfo->in_color_space != JCS_GRAYSCALE) { | 
| 528 | 1.05k |     cinfo->in_color_space = JCS_RGB; | 
| 529 | 1.05k |     cinfo->input_components = NUMCOLORS; | 
| 530 | 1.05k |   } | 
| 531 |  |  | 
| 532 |  |   /* Create compressor input buffer. */ | 
| 533 | 1.88k |   source->pub.buffer = (*cinfo->mem->alloc_sarray) | 
| 534 | 1.88k |     ((j_common_ptr)cinfo, JPOOL_IMAGE, | 
| 535 | 1.88k |      (JDIMENSION)width * cinfo->input_components, (JDIMENSION)1); | 
| 536 | 1.88k |   source->pub.buffer_height = 1; | 
| 537 |  |  | 
| 538 |  |   /* Pad colormap for safety. */ | 
| 539 | 28.1k |   for (c = colormaplen; c < source->clear_code; c++) { | 
| 540 | 26.2k |     source->colormap[CM_RED][c]   = | 
| 541 | 26.2k |     source->colormap[CM_GREEN][c] = | 
| 542 | 26.2k |     source->colormap[CM_BLUE][c]  = CENTERJSAMPLE; | 
| 543 | 26.2k |   } | 
| 544 |  |  | 
| 545 |  |   /* Return info about the image. */ | 
| 546 | 1.88k |   cinfo->data_precision = BITS_IN_JSAMPLE; /* we always rescale data to this */ | 
| 547 | 1.88k |   cinfo->image_width = width; | 
| 548 | 1.88k |   cinfo->image_height = height; | 
| 549 |  |  | 
| 550 | 1.88k |   TRACEMS3(cinfo, 1, JTRC_GIF, width, height, colormaplen); | 
| 551 | 1.88k | } | 
| 552 |  |  | 
| 553 |  |  | 
| 554 |  | /* | 
| 555 |  |  * Read one row of pixels. | 
| 556 |  |  * This version is used for noninterlaced GIF images: | 
| 557 |  |  * we read directly from the GIF file. | 
| 558 |  |  */ | 
| 559 |  |  | 
| 560 |  | METHODDEF(JDIMENSION) | 
| 561 |  | get_pixel_rows(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | 
| 562 | 1.13M | { | 
| 563 | 1.13M |   gif_source_ptr source = (gif_source_ptr)sinfo; | 
| 564 | 1.13M |   register int c; | 
| 565 | 1.13M |   register JSAMPROW ptr; | 
| 566 | 1.13M |   register JDIMENSION col; | 
| 567 | 1.13M |   register JSAMPARRAY colormap = source->colormap; | 
| 568 |  |  | 
| 569 | 1.13M |   ptr = source->pub.buffer[0]; | 
| 570 | 1.13M |   if (cinfo->in_color_space == JCS_GRAYSCALE) { | 
| 571 | 6.88M |     for (col = cinfo->image_width; col > 0; col--) { | 
| 572 | 6.63M |       c = LZWReadByte(source); | 
| 573 | 6.63M |       *ptr++ = colormap[CM_RED][c]; | 
| 574 | 6.63M |     } | 
| 575 | 887k |   } else { | 
| 576 | 45.8M |     for (col = cinfo->image_width; col > 0; col--) { | 
| 577 | 44.9M |       c = LZWReadByte(source); | 
| 578 | 44.9M |       *ptr++ = colormap[CM_RED][c]; | 
| 579 | 44.9M |       *ptr++ = colormap[CM_GREEN][c]; | 
| 580 | 44.9M |       *ptr++ = colormap[CM_BLUE][c]; | 
| 581 | 44.9M |     } | 
| 582 | 887k |   } | 
| 583 | 1.13M |   return 1; | 
| 584 | 1.13M | } | 
| 585 |  |  | 
| 586 |  |  | 
| 587 |  | /* | 
| 588 |  |  * Read one row of pixels. | 
| 589 |  |  * This version is used for the first call on get_pixel_rows when | 
| 590 |  |  * reading an interlaced GIF file: we read the whole image into memory. | 
| 591 |  |  */ | 
| 592 |  |  | 
| 593 |  | METHODDEF(JDIMENSION) | 
| 594 |  | load_interlaced_image(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | 
| 595 | 798 | { | 
| 596 | 798 |   gif_source_ptr source = (gif_source_ptr)sinfo; | 
| 597 | 798 |   register JSAMPROW sptr; | 
| 598 | 798 |   register JDIMENSION col; | 
| 599 | 798 |   JDIMENSION row; | 
| 600 | 798 |   cd_progress_ptr progress = (cd_progress_ptr)cinfo->progress; | 
| 601 |  |  | 
| 602 |  |   /* Read the interlaced image into the virtual array we've created. */ | 
| 603 | 18.1M |   for (row = 0; row < cinfo->image_height; row++) { | 
| 604 | 18.1M |     if (progress != NULL) { | 
| 605 | 0 |       progress->pub.pass_counter = (long)row; | 
| 606 | 0 |       progress->pub.pass_limit = (long)cinfo->image_height; | 
| 607 | 0 |       (*progress->pub.progress_monitor) ((j_common_ptr)cinfo); | 
| 608 | 0 |     } | 
| 609 | 18.1M |     sptr = *(*cinfo->mem->access_virt_sarray) | 
| 610 | 18.1M |       ((j_common_ptr)cinfo, source->interlaced_image, row, (JDIMENSION)1, | 
| 611 | 18.1M |        TRUE); | 
| 612 | 124M |     for (col = cinfo->image_width; col > 0; col--) { | 
| 613 | 105M |       *sptr++ = (JSAMPLE)LZWReadByte(source); | 
| 614 | 105M |     } | 
| 615 | 18.1M |   } | 
| 616 | 798 |   if (progress != NULL) | 
| 617 | 0 |     progress->completed_extra_passes++; | 
| 618 |  |  | 
| 619 |  |   /* Replace method pointer so subsequent calls don't come here. */ | 
| 620 | 798 |   source->pub.get_pixel_rows = get_interlaced_row; | 
| 621 |  |   /* Initialize for get_interlaced_row, and perform first call on it. */ | 
| 622 | 798 |   source->cur_row_number = 0; | 
| 623 | 798 |   source->pass2_offset = (cinfo->image_height + 7) / 8; | 
| 624 | 798 |   source->pass3_offset = source->pass2_offset + (cinfo->image_height + 3) / 8; | 
| 625 | 798 |   source->pass4_offset = source->pass3_offset + (cinfo->image_height + 1) / 4; | 
| 626 |  |  | 
| 627 | 798 |   return get_interlaced_row(cinfo, sinfo); | 
| 628 | 798 | } | 
| 629 |  |  | 
| 630 |  |  | 
| 631 |  | /* | 
| 632 |  |  * Read one row of pixels. | 
| 633 |  |  * This version is used for interlaced GIF images: | 
| 634 |  |  * we read from the virtual array. | 
| 635 |  |  */ | 
| 636 |  |  | 
| 637 |  | METHODDEF(JDIMENSION) | 
| 638 |  | get_interlaced_row(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | 
| 639 | 18.0M | { | 
| 640 | 18.0M |   gif_source_ptr source = (gif_source_ptr)sinfo; | 
| 641 | 18.0M |   register int c; | 
| 642 | 18.0M |   register JSAMPROW sptr, ptr; | 
| 643 | 18.0M |   register JDIMENSION col; | 
| 644 | 18.0M |   register JSAMPARRAY colormap = source->colormap; | 
| 645 | 18.0M |   JDIMENSION irow; | 
| 646 |  |  | 
| 647 |  |   /* Figure out which row of interlaced image is needed, and access it. */ | 
| 648 | 18.0M |   switch ((int)(source->cur_row_number & 7)) { | 
| 649 | 2.25M |   case 0:                       /* first-pass row */ | 
| 650 | 2.25M |     irow = source->cur_row_number >> 3; | 
| 651 | 2.25M |     break; | 
| 652 | 2.25M |   case 4:                       /* second-pass row */ | 
| 653 | 2.25M |     irow = (source->cur_row_number >> 3) + source->pass2_offset; | 
| 654 | 2.25M |     break; | 
| 655 | 2.25M |   case 2:                       /* third-pass row */ | 
| 656 | 4.50M |   case 6: | 
| 657 | 4.50M |     irow = (source->cur_row_number >> 2) + source->pass3_offset; | 
| 658 | 4.50M |     break; | 
| 659 | 9.00M |   default:                      /* fourth-pass row */ | 
| 660 | 9.00M |     irow = (source->cur_row_number >> 1) + source->pass4_offset; | 
| 661 | 18.0M |   } | 
| 662 | 18.0M |   sptr = *(*cinfo->mem->access_virt_sarray) | 
| 663 | 18.0M |     ((j_common_ptr)cinfo, source->interlaced_image, irow, (JDIMENSION)1, | 
| 664 | 18.0M |      FALSE); | 
| 665 |  |   /* Scan the row, expand colormap, and output */ | 
| 666 | 18.0M |   ptr = source->pub.buffer[0]; | 
| 667 | 18.0M |   if (cinfo->in_color_space == JCS_GRAYSCALE) { | 
| 668 | 9.02M |     for (col = cinfo->image_width; col > 0; col--) { | 
| 669 | 8.49M |       c = *sptr++; | 
| 670 | 8.49M |       *ptr++ = colormap[CM_RED][c]; | 
| 671 | 8.49M |     } | 
| 672 | 17.4M |   } else { | 
| 673 | 114M |     for (col = cinfo->image_width; col > 0; col--) { | 
| 674 | 96.6M |       c = *sptr++; | 
| 675 | 96.6M |       *ptr++ = colormap[CM_RED][c]; | 
| 676 | 96.6M |       *ptr++ = colormap[CM_GREEN][c]; | 
| 677 | 96.6M |       *ptr++ = colormap[CM_BLUE][c]; | 
| 678 | 96.6M |     } | 
| 679 | 17.4M |   } | 
| 680 | 18.0M |   source->cur_row_number++;     /* for next time */ | 
| 681 | 18.0M |   return 1; | 
| 682 | 18.0M | } | 
| 683 |  |  | 
| 684 |  |  | 
| 685 |  | /* | 
| 686 |  |  * Finish up at the end of the file. | 
| 687 |  |  */ | 
| 688 |  |  | 
| 689 |  | METHODDEF(void) | 
| 690 |  | finish_input_gif(j_compress_ptr cinfo, cjpeg_source_ptr sinfo) | 
| 691 | 815 | { | 
| 692 |  |   /* no work */ | 
| 693 | 815 | } | 
| 694 |  |  | 
| 695 |  |  | 
| 696 |  | /* | 
| 697 |  |  * The module selection routine for GIF format input. | 
| 698 |  |  */ | 
| 699 |  |  | 
| 700 |  | GLOBAL(cjpeg_source_ptr) | 
| 701 |  | jinit_read_gif(j_compress_ptr cinfo) | 
| 702 | 1.88k | { | 
| 703 | 1.88k |   gif_source_ptr source; | 
| 704 |  |  | 
| 705 |  |   /* Create module interface object */ | 
| 706 | 1.88k |   source = (gif_source_ptr) | 
| 707 | 1.88k |     (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE, | 
| 708 | 1.88k |                                 sizeof(gif_source_struct)); | 
| 709 | 1.88k |   source->cinfo = cinfo;        /* make back link for subroutines */ | 
| 710 |  |   /* Fill in method ptrs, except get_pixel_rows which start_input sets */ | 
| 711 | 1.88k |   source->pub.start_input = start_input_gif; | 
| 712 | 1.88k |   source->pub.finish_input = finish_input_gif; | 
| 713 | 1.88k | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 
| 714 | 1.88k |   source->pub.max_pixels = 0; | 
| 715 | 1.88k | #endif | 
| 716 |  |  | 
| 717 | 1.88k |   return (cjpeg_source_ptr)source; | 
| 718 | 1.88k | } | 
| 719 |  |  | 
| 720 |  | #endif /* GIF_SUPPORTED */ |