1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** GUIX Component                                                        */
16 /**                                                                       */
17 /**   Display Management (Display)                                        */
18 /**                                                                       */
19 /**************************************************************************/
20 
21 #define GX_SOURCE_CODE
22 
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_utility.h"
29 #include "gx_image_reader.h"
30 
31 
32 #if defined(GX_SOFTWARE_DECODER_SUPPORT)
33 static UINT _bit_buffer;
34 static UINT _bit_count;
35 
36 /**************************************************************************/
37 /*                                                                        */
38 /*  FUNCTION                                               RELEASE        */
39 /*                                                                        */
40 /*    _gx_image_reader_png_crc_table_make                 PORTABLE C      */
41 /*                                                           6.1          */
42 /*  AUTHOR                                                                */
43 /*                                                                        */
44 /*    Kenneth Maxwell, Microsoft Corporation                              */
45 /*                                                                        */
46 /*  DESCRIPTION                                                           */
47 /*                                                                        */
48 /*    This function creates crc table that speed the crc calculation.     */
49 /*                                                                        */
50 /*  INPUT                                                                 */
51 /*                                                                        */
52 /*    png                                   PNG control block             */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    None                                                                */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    None                                                                */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    _gx_image_reader_png_decode                                         */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
71 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
72 /*                                            resulting in version 6.1    */
73 /*                                                                        */
74 /**************************************************************************/
_gx_image_reader_png_crc_table_make(GX_PNG * png)75 static VOID _gx_image_reader_png_crc_table_make(GX_PNG *png)
76 {
77 UINT crc;
78 UINT n;
79 UINT k;
80 
81     for (n = 0; n < 256; n++)
82     {
83         crc = n;
84         for (k = 0; k < 8; k++)
85         {
86             if (crc & 1)
87             {
88                 crc = 0xedb88320 ^ (crc >> 1);
89             }
90             else
91             {
92                 crc = crc >> 1;
93             }
94         }
95         png -> gx_png_crc_table[n] = crc;
96     }
97 }
98 
99 /**************************************************************************/
100 /*                                                                        */
101 /*  FUNCTION                                               RELEASE        */
102 /*                                                                        */
103 /*    _gx_display_driver_png_crc_get                      PORTABLE C      */
104 /*                                                           6.1          */
105 /*  AUTHOR                                                                */
106 /*                                                                        */
107 /*    Kenneth Maxwell, Microsoft Corporation                              */
108 /*                                                                        */
109 /*  DESCRIPTION                                                           */
110 /*                                                                        */
111 /*    This function calculates Cyclic Redundancy Check of a pecified      */
112 /*    data stream.                                                        */
113 /*                                                                        */
114 /*  INPUT                                                                 */
115 /*                                                                        */
116 /*    png                                   PNG control block             */
117 /*    crc                                   Generated crc value           */
118 /*    len                                   Data length                   */
119 /*                                                                        */
120 /*  OUTPUT                                                                */
121 /*                                                                        */
122 /*    None                                                                */
123 /*                                                                        */
124 /*  CALLS                                                                 */
125 /*                                                                        */
126 /*    None                                                                */
127 /*                                                                        */
128 /*  CALLED BY                                                             */
129 /*                                                                        */
130 /*    _gx_image_reader_png_decode                                         */
131 /*    _gx_image_reader_png_bits_get                                       */
132 /*                                                                        */
133 /*  RELEASE HISTORY                                                       */
134 /*                                                                        */
135 /*    DATE              NAME                      DESCRIPTION             */
136 /*                                                                        */
137 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
138 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
139 /*                                            resulting in version 6.1    */
140 /*                                                                        */
141 /**************************************************************************/
_gx_image_reader_png_crc_get(GX_PNG * png,UINT * crc,UINT len)142 static VOID _gx_image_reader_png_crc_get(GX_PNG *png, UINT *crc, UINT len)
143 {
144 UINT      n;
145 GX_UBYTE *buf = png -> gx_png_data + png -> gx_png_data_index;
146 UINT      crc_cal = (*crc);
147 
148     for (n = 0; n < len; n++)
149     {
150         crc_cal = png -> gx_png_crc_table[(crc_cal ^ buf[n]) & 0xff] ^ (crc_cal >> 8);
151     }
152 
153     (*crc) = crc_cal ^ 0xffffffff;
154 }
155 
156 /**************************************************************************/
157 /*                                                                        */
158 /*  FUNCTION                                               RELEASE        */
159 /*                                                                        */
160 /*    _gx_image_reader_png_4bytes_read                    PORTABLE C      */
161 /*                                                           6.1          */
162 /*  AUTHOR                                                                */
163 /*                                                                        */
164 /*    Kenneth Maxwell, Microsoft Corporation                              */
165 /*                                                                        */
166 /*  DESCRIPTION                                                           */
167 /*                                                                        */
168 /*    This function reads 4 bytes and packed it as an INT value.          */
169 /*                                                                        */
170 /*  INPUT                                                                 */
171 /*                                                                        */
172 /*    png                                   PNG control block             */
173 /*    value                                 Retrieved INT value           */
174 /*                                                                        */
175 /*  OUTPUT                                                                */
176 /*                                                                        */
177 /*    None                                                                */
178 /*                                                                        */
179 /*  CALLS                                                                 */
180 /*                                                                        */
181 /*    None                                                                */
182 /*                                                                        */
183 /*  CALLED BY                                                             */
184 /*                                                                        */
185 /*    _gx_image_reader_png_decode                                         */
186 /*    _gx_image_reader_png_bits_get                                       */
187 /*    _gx_image_reader_png_IHDR_chunk_read                                */
188 /*    _gx_image_reader_png_gAMA_chunk_read                                */
189 /*                                                                        */
190 /*  RELEASE HISTORY                                                       */
191 /*                                                                        */
192 /*    DATE              NAME                      DESCRIPTION             */
193 /*                                                                        */
194 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
195 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
196 /*                                            resulting in version 6.1    */
197 /*                                                                        */
198 /**************************************************************************/
_gx_image_reader_png_4bytes_read(GX_PNG * png,INT * value)199 static VOID _gx_image_reader_png_4bytes_read(GX_PNG *png, INT *value)
200 {
201 INT get_value;
202 
203     get_value = (png -> gx_png_data[png -> gx_png_data_index] << 24);
204     png -> gx_png_data_index++;
205 
206     get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 16);
207     png -> gx_png_data_index++;
208 
209     get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
210     png -> gx_png_data_index++;
211 
212     get_value |= png -> gx_png_data[png -> gx_png_data_index];
213     png -> gx_png_data_index++;
214 
215     (*value) = get_value;
216 }
217 
218 /**************************************************************************/
219 /*                                                                        */
220 /*  FUNCTION                                               RELEASE        */
221 /*                                                                        */
222 /*    _gx_image_reader_png_chunk_type_read                PORTABLE C      */
223 /*                                                           6.1          */
224 /*  AUTHOR                                                                */
225 /*                                                                        */
226 /*    Kenneth Maxwell, Microsoft Corporation                              */
227 /*                                                                        */
228 /*  DESCRIPTION                                                           */
229 /*                                                                        */
230 /*    This function reads the type information of a chunk.                */
231 /*                                                                        */
232 /*  INPUT                                                                 */
233 /*                                                                        */
234 /*    png                                   PNG control block             */
235 /*    chunk_type                            Retrieved chunk type info     */
236 /*                                                                        */
237 /*  OUTPUT                                                                */
238 /*                                                                        */
239 /*    None                                                                */
240 /*                                                                        */
241 /*  CALLS                                                                 */
242 /*                                                                        */
243 /*    None                                                                */
244 /*                                                                        */
245 /*  CALLED BY                                                             */
246 /*                                                                        */
247 /*    _gx_image_reader_png_bits_get                                       */
248 /*    _gx_image_reader_png_decode                                         */
249 /*                                                                        */
250 /*  RELEASE HISTORY                                                       */
251 /*                                                                        */
252 /*    DATE              NAME                      DESCRIPTION             */
253 /*                                                                        */
254 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
255 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
256 /*                                            resulting in version 6.1    */
257 /*                                                                        */
258 /**************************************************************************/
_gx_image_reader_png_chunk_type_read(GX_PNG * png,CHAR * chunk_type)259 static VOID _gx_image_reader_png_chunk_type_read(GX_PNG *png, CHAR *chunk_type)
260 {
261     chunk_type[0] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
262     chunk_type[1] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
263     chunk_type[2] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
264     chunk_type[3] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
265 }
266 
267 /**************************************************************************/
268 /*                                                                        */
269 /*  FUNCTION                                               RELEASE        */
270 /*                                                                        */
271 /*    _gx_image_reader_png_bits_get                       PORTABLE C      */
272 /*                                                           6.1          */
273 /*  AUTHOR                                                                */
274 /*                                                                        */
275 /*    Kenneth Maxwell, Microsoft Corporation                              */
276 /*                                                                        */
277 /*  DESCRIPTION                                                           */
278 /*                                                                        */
279 /*    This function Extract a specified number of bits from PNG data      */
280 /*    stream and advance the read pointer of the PNG data stream.         */
281 /*                                                                        */
282 /*  INPUT                                                                 */
283 /*                                                                        */
284 /*    png                                   PNG control block             */
285 /*    num_of_bits                           number of bits to retrieve    */
286 /*    return_value                          Retrieved bits data           */
287 /*                                                                        */
288 /*  OUTPUT                                                                */
289 /*                                                                        */
290 /*    None                                                                */
291 /*                                                                        */
292 /*  CALLS                                                                 */
293 /*                                                                        */
294 /*    _gx_image_reader_png_4bytes_read      Read 4 bytes and pack it to a */
295 /*                                            INT type value              */
296 /*    _gx_image_reader_png_crc_get          Calculate crc value with      */
297 /*                                            specified data              */
298 /*    _gx_image_reader_png_chunk_type_read  Read type information         */
299 /*                                                                        */
300 /*  CALLED BY                                                             */
301 /*                                                                        */
302 /*    _gx_image_reader_png_clen_huffman_read                              */
303 /*    _gx_image_reader_png_ll_huffman_read                                */
304 /*    _gx_image_reader_png_huffcode_decode                                */
305 /*    _gx_image_reader_png_IDAT_chunk_read                                */
306 /*                                                                        */
307 /*  RELEASE HISTORY                                                       */
308 /*                                                                        */
309 /*    DATE              NAME                      DESCRIPTION             */
310 /*                                                                        */
311 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
312 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
313 /*                                            resulting in version 6.1    */
314 /*                                                                        */
315 /**************************************************************************/
_gx_image_reader_png_bits_get(GX_PNG * png,UINT num_of_bits,UINT * return_value)316 static UINT _gx_image_reader_png_bits_get(GX_PNG *png, UINT num_of_bits, UINT *return_value)
317 {
318 GX_UBYTE get_byte;
319 INT      checksum;
320 CHAR     chunk_type[4];
321 INT      index = png -> gx_png_trunk_end_index;
322 
323     while (_bit_count < num_of_bits)
324     {
325         if (png -> gx_png_data_index >= png -> gx_png_data_size)
326         {
327             return GX_FAILURE;
328         }
329 
330         get_byte = png -> gx_png_data[png -> gx_png_data_index++];
331 
332         _bit_buffer |= (UINT)(get_byte << (UINT)_bit_count);
333         _bit_count += 8;
334 
335         if (png -> gx_png_data_index >= index)
336         {
337             /* data_len*/
338             _gx_image_reader_png_4bytes_read(png, &checksum);
339 
340             if (png -> gx_png_trunk_crc != (UINT)checksum)
341             {
342                 return GX_FAILURE;
343             }
344 
345             _gx_image_reader_png_4bytes_read(png, &index);
346 
347             png -> gx_png_trunk_crc = 0xffffffff;
348 
349             _gx_image_reader_png_crc_get(png, &png -> gx_png_trunk_crc, (UINT)(4 + index));
350 
351             _gx_image_reader_png_chunk_type_read(png, chunk_type);
352 
353             if (strncmp(chunk_type, "IDAT", 4) == 0)
354             {
355                 index += png -> gx_png_data_index;
356                 png -> gx_png_trunk_end_index = index;
357             }
358         }
359     }
360 
361     (*return_value) = _bit_buffer;
362 
363     return GX_SUCCESS;
364 }
365 
366 /**************************************************************************/
367 /*                                                                        */
368 /*  FUNCTION                                               RELEASE        */
369 /*                                                                        */
370 /*    _gx_image_reader_png_bits_revert                    PORTABLE C      */
371 /*                                                           6.1          */
372 /*  AUTHOR                                                                */
373 /*                                                                        */
374 /*    Kenneth Maxwell, Microsoft Corporation                              */
375 /*                                                                        */
376 /*  DESCRIPTION                                                           */
377 /*                                                                        */
378 /*    This function reorders bits stream in opposite order.               */
379 /*                                                                        */
380 /*  INPUT                                                                 */
381 /*                                                                        */
382 /*    bits                                  Variable contain bits stream  */
383 /*    bits_len                              The number of bits to revert  */
384 /*                                                                        */
385 /*  OUTPUT                                                                */
386 /*                                                                        */
387 /*    None                                                                */
388 /*                                                                        */
389 /*  CALLS                                                                 */
390 /*                                                                        */
391 /*    None                                                                */
392 /*                                                                        */
393 /*  CALLED BY                                                             */
394 /*                                                                        */
395 /*    _gx_image_reader_png_dynamic_huffman_code_find                      */
396 /*    _gx_image_reader_png_fixed_ll_huffman_code_find                     */
397 /*    _gx_image_reader_png_huffcode_decode                                */
398 /*                                                                        */
399 /*  RELEASE HISTORY                                                       */
400 /*                                                                        */
401 /*    DATE              NAME                      DESCRIPTION             */
402 /*                                                                        */
403 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
404 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
405 /*                                            resulting in version 6.1    */
406 /*                                                                        */
407 /**************************************************************************/
_gx_image_reader_png_bits_revert(UINT * bits,UINT bits_len)408 static void _gx_image_reader_png_bits_revert(UINT *bits, UINT bits_len)
409 {
410 UINT reverted = 0;
411 UINT i;
412 
413     for (i = 0; i < bits_len; i++)
414     {
415         reverted |= ((*bits) & 0x1) << (bits_len - i - 1);
416         (*bits) >>= 1;
417     }
418 
419     (*bits) = reverted;
420 }
421 
422 /**************************************************************************/
423 /*                                                                        */
424 /*  FUNCTION                                               RELEASE        */
425 /*                                                                        */
426 /*    _gx_image_reader_png_bits_skip                      PORTABLE C      */
427 /*                                                           6.1          */
428 /*  AUTHOR                                                                */
429 /*                                                                        */
430 /*    Kenneth Maxwell, Microsoft Corporation                              */
431 /*                                                                        */
432 /*  DESCRIPTION                                                           */
433 /*                                                                        */
434 /*    This function skips bits from tempory PNG data buffer.              */
435 /*                                                                        */
436 /*  INPUT                                                                 */
437 /*                                                                        */
438 /*    num_of_skip_bits                      The number of bits to skip    */
439 /*                                                                        */
440 /*  OUTPUT                                                                */
441 /*                                                                        */
442 /*    None                                                                */
443 /*                                                                        */
444 /*  CALLS                                                                 */
445 /*                                                                        */
446 /*    None                                                                */
447 /*                                                                        */
448 /*  CALLED BY                                                             */
449 /*                                                                        */
450 /*    _gx_image_reader_png_clen_huffman_read                              */
451 /*    _gx_image_reader_png_huffcode_decode                                */
452 /*    _gx_image_reader_png_tRNS_chunk_read                                */
453 /*    _gx_image_reader_png_IDAT_chunk_read                                */
454 /*                                                                        */
455 /*  RELEASE HISTORY                                                       */
456 /*                                                                        */
457 /*    DATE              NAME                      DESCRIPTION             */
458 /*                                                                        */
459 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
460 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
461 /*                                            resulting in version 6.1    */
462 /*                                                                        */
463 /**************************************************************************/
_gx_image_reader_png_bits_skip(UINT num_of_skip_bits)464 static VOID _gx_image_reader_png_bits_skip(UINT num_of_skip_bits)
465 {
466     _bit_buffer >>= num_of_skip_bits;
467 
468     _bit_count -= num_of_skip_bits;
469 }
470 
471 /**************************************************************************/
472 /*                                                                        */
473 /*  FUNCTION                                               RELEASE        */
474 /*                                                                        */
475 /*    _gx_image_reader_png_IHDR_chunk_read                PORTABLE C      */
476 /*                                                           6.2.0        */
477 /*  AUTHOR                                                                */
478 /*                                                                        */
479 /*    Kenneth Maxwell, Microsoft Corporation                              */
480 /*                                                                        */
481 /*  DESCRIPTION                                                           */
482 /*                                                                        */
483 /*    This function reads in IHDR chunk information.                      */
484 /*                                                                        */
485 /*  INPUT                                                                 */
486 /*                                                                        */
487 /*    png                                   PNG control block             */
488 /*                                                                        */
489 /*  OUTPUT                                                                */
490 /*                                                                        */
491 /*    status                                Completion status             */
492 /*                                                                        */
493 /*  CALLS                                                                 */
494 /*                                                                        */
495 /*    _gx_display_driver_png_4bytes_read    Read 4 bytes and pack it to a */
496 /*                                            INT type value              */
497 /*                                                                        */
498 /*  CALLED BY                                                             */
499 /*                                                                        */
500 /*    _gx_image_reader_png_decode                                         */
501 /*                                                                        */
502 /*  RELEASE HISTORY                                                       */
503 /*                                                                        */
504 /*    DATE              NAME                      DESCRIPTION             */
505 /*                                                                        */
506 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
507 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
508 /*                                            added data boundary check,  */
509 /*                                            resulting in version 6.1    */
510 /*  10-31-2022     Ting Zhu                 Modified comment(s),          */
511 /*                                            added invalid value check,  */
512 /*                                            resulting in version 6.2.0  */
513 /*                                                                        */
514 /**************************************************************************/
_gx_image_reader_png_IHDR_chunk_read(GX_PNG * png)515 static UINT _gx_image_reader_png_IHDR_chunk_read(GX_PNG *png)
516 {
517     /* The IHDR chunk contains:
518         Width: 4 bytes
519         Height: 4 bytes
520         Bit depth: 1 byte
521         Color type: 1 byte
522         Compression method: 1 byte
523         Filter method: 1 byte
524         Interlace method: 1 byte */
525 
526     if (png -> gx_png_data_index + 13 > png -> gx_png_trunk_end_index)
527     {
528         return GX_INVALID_SIZE;
529     }
530 
531     _gx_image_reader_png_4bytes_read(png, &png -> gx_png_width);
532     _gx_image_reader_png_4bytes_read(png, &png -> gx_png_height);
533 
534     /* Limited max png width to 14 bits. */
535     if ((png -> gx_png_width < 0) || (png -> gx_png_width > GX_MAX_PIXELMAP_RESOLUTION))
536     {
537         return GX_INVALID_WIDTH;
538     }
539 
540     /* Limited max png height to 14 bits. */
541     if ((png -> gx_png_height < 0) || (png -> gx_png_height > GX_MAX_PIXELMAP_RESOLUTION))
542     {
543         return GX_INVALID_HEIGHT;
544     }
545 
546     /* Bits per sample or per palette index, valid values are 1, 2 ,4, 8, 16. */
547     png -> gx_png_bit_depth = png -> gx_png_data[png -> gx_png_data_index++];
548 
549     switch (png -> gx_png_bit_depth)
550     {
551     case 1:
552     case 2:
553     case 4:
554     case 8:
555     case 16:
556         break;
557 
558     default:
559         return GX_INVALID_FORMAT;
560     }
561 
562     /* 0 gray sample
563        2 RGB tripple
564        3 palette index
565        4 gray sample followed by an alpha sample
566        6 RGB triple followed by an alpha sample */
567     png -> gx_png_color_type = png -> gx_png_data[png -> gx_png_data_index++];
568 
569     switch (png -> gx_png_color_type)
570     {
571     case 0:
572     /* Each pixel is agrayscale sample. */
573     case 3:
574         /* Each pixel is a palette index, a PLTE chunk must appear. */
575         png -> gx_png_bpp = png -> gx_png_bit_depth;
576         break;
577     case 2:
578         /* Each pixel is an RGB triple. */
579         png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 3);
580         break;
581 
582     case 4:
583         /* Each pixel is a grayscale sample, followed by an alpha sample. */
584         png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 2);
585         break;
586     case 6:
587         /* Each pixel is an R,G,B triple, followed by an alpha sample. */
588         png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 4);
589         break;
590 
591     default:
592         return GX_FAILURE;
593     }
594 
595     /* At present, only method 0 is defined. */
596     png -> gx_png_compression_method = png -> gx_png_data[png -> gx_png_data_index++];
597 
598     /* At present, only method 0 is defined. */
599     png -> gx_png_filter_method = png -> gx_png_data[png -> gx_png_data_index++];
600 
601     if ((png -> gx_png_compression_method != 0) || (png -> gx_png_filter_method != 0))
602     {
603         /* Invalid value. */
604         return GX_FAILURE;
605     }
606 
607     /* 0 no interlace
608        1 Adam7 interlace */
609     png -> gx_png_interlace_method = png -> gx_png_data[png -> gx_png_data_index++];
610 
611     return GX_SUCCESS;
612 }
613 
614 /**************************************************************************/
615 /*                                                                        */
616 /*  FUNCTION                                               RELEASE        */
617 /*                                                                        */
618 /*    _gx_image_reader_png_dynamic_huffman_code_find      PORTABLE C      */
619 /*                                                           6.1          */
620 /*  AUTHOR                                                                */
621 /*                                                                        */
622 /*    Kenneth Maxwell, Microsoft Corporation                              */
623 /*                                                                        */
624 /*  DESCRIPTION                                                           */
625 /*                                                                        */
626 /*    This function retrieves code value from dynamic huffman table.      */
627 /*                                                                        */
628 /*  INPUT                                                                 */
629 /*                                                                        */
630 /*    png                                   PNG control block             */
631 /*    huffman_bits_count                    Array records codes number for*/
632 /*                                          every code len                */
633 /*    scan_buffer                           Buffer to search from         */
634 /*    bit_len                               Retrieved Huffman Code Length */
635 /*    code_value                            Retrieved Huffman Code        */
636 /*                                                                        */
637 /*  OUTPUT                                                                */
638 /*                                                                        */
639 /*    Status code                                                         */
640 /*                                                                        */
641 /*  CALLS                                                                 */
642 /*                                                                        */
643 /*    _gx_image_reader_png_bits_revert      Reorder bits stream in        */
644 /*                                            opposite order              */
645 /*                                                                        */
646 /*  CALLED BY                                                             */
647 /*                                                                        */
648 /*    _gx_image_reader_png_huffcode_decode                                */
649 /*    _gx_image_reader_png_ll_huffman_read                                */
650 /*                                                                        */
651 /*  RELEASE HISTORY                                                       */
652 /*                                                                        */
653 /*    DATE              NAME                      DESCRIPTION             */
654 /*                                                                        */
655 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
656 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
657 /*                                            resulting in version 6.1    */
658 /*                                                                        */
659 /**************************************************************************/
_gx_image_reader_png_dynamic_huffman_code_find(INT * huffman_table,UINT * huffman_bits_count,UINT scan_buffer,UINT * bit_len,UINT * code_value)660 static UINT _gx_image_reader_png_dynamic_huffman_code_find(INT  *huffman_table,
661                                                            UINT  *huffman_bits_count,
662                                                            UINT   scan_buffer,
663                                                            UINT  *bit_len,
664                                                            UINT *code_value)
665 {
666 UINT i_bit;
667 UINT bit_count;
668 UINT code;
669 UINT code_cal = 0;
670 UINT code_index = 0;
671 
672     for (i_bit = 1; i_bit < 16; i_bit++)
673     {
674         bit_count = huffman_bits_count[i_bit] - huffman_bits_count[i_bit - 1];
675 
676         if (bit_count)
677         {
678             code = (scan_buffer) << (32 - i_bit);
679             code = (code) >> (32 - i_bit);
680 
681             _gx_image_reader_png_bits_revert(&code, i_bit);
682 
683             if (code <= code_cal + bit_count - 1)
684             {
685                 *bit_len = i_bit;
686                 *code_value = (UINT)huffman_table[code_index + code - code_cal];
687 
688                 return GX_SUCCESS;
689             }
690             else
691             {
692                 code_index += bit_count;
693                 code_cal += bit_count;
694             }
695         }
696 
697         code_cal <<= 1;
698     }
699 
700     return GX_NOT_FOUND;
701 }
702 
703 /**************************************************************************/
704 /*                                                                        */
705 /*  FUNCTION                                               RELEASE        */
706 /*                                                                        */
707 /*    _gx_image_reader_png_fixed_ll_huffman_code_find     PORTABLE C      */
708 /*                                                           6.1          */
709 /*  AUTHOR                                                                */
710 /*                                                                        */
711 /*    Kenneth Maxwell, Microsoft Corporation                              */
712 /*                                                                        */
713 /*  DESCRIPTION                                                           */
714 /*                                                                        */
715 /*    This function retrieves code value from fixed huffman table.        */
716 /*                                                                        */
717 /*  INPUT                                                                 */
718 /*                                                                        */
719 /*    scan_buffer                           Buffer that contains Huffman  */
720 /*                                          code                          */
721 /*    bit_len                               Retrieved Huffman Code length */
722 /*    code_value                            Retrieved code value of the   */
723 /*                                          matched Huffman Code          */
724 /*                                                                        */
725 /*  OUTPUT                                                                */
726 /*                                                                        */
727 /*    status                                Completion status             */
728 /*                                                                        */
729 /*  CALLS                                                                 */
730 /*                                                                        */
731 /*    _gx_image_reader_png_bits_revert      Reorder bits stream in        */
732 /*                                            opposite order              */
733 /*                                                                        */
734 /*  CALLED BY                                                             */
735 /*                                                                        */
736 /*    _gx_image_reader_png_huffcode_decode                                */
737 /*                                                                        */
738 /*  RELEASE HISTORY                                                       */
739 /*                                                                        */
740 /*    DATE              NAME                      DESCRIPTION             */
741 /*                                                                        */
742 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
743 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
744 /*                                            resulting in version 6.1    */
745 /*                                                                        */
746 /**************************************************************************/
_gx_image_reader_png_fixed_ll_huffman_code_find(UINT scan_buffer,UINT * bit_len,UINT * code_value)747 static UINT _gx_image_reader_png_fixed_ll_huffman_code_find(UINT scan_buffer,
748                                                             UINT *bit_len,
749                                                             UINT *code_value)
750 {
751 UINT i_bit;
752 UINT code;
753 
754     for (i_bit = 7; i_bit <= 9; i_bit++)
755     {
756         code = scan_buffer << (32 - i_bit);
757         code = code >> (32 - i_bit);
758 
759         _gx_image_reader_png_bits_revert(&code, i_bit);
760 
761         if (i_bit == 7)
762         {
763             if (code <= 0x17)
764             {
765                 *bit_len = 7;
766                 *code_value = 256 + code;
767                 break;
768             }
769         }
770         else if (i_bit == 8)
771         {
772             if (code <= 0xbf)
773             {
774                 /* code >= 0x30. */
775                 *bit_len = 8;
776                 *code_value = code - 0x30;
777                 break;
778             }
779             else if (code <= 0xc7)
780             {
781                 /* code >= 0xc0. */
782                 *bit_len = 8;
783                 *code_value = 280 + code - 0xc0;
784                 break;
785             }
786         }
787         else
788         {
789             /* code >= 0x190 && code <= 0x1ff. */
790             *bit_len = 9;
791             *code_value = 144 + code - 0x190;
792         }
793     }
794 
795     return GX_SUCCESS;
796 }
797 
798 /**************************************************************************/
799 /*                                                                        */
800 /*  FUNCTION                                               RELEASE        */
801 /*                                                                        */
802 /*    _gx_image_reader_png_clen_huffman_read              PORTABLE C      */
803 /*                                                           6.1          */
804 /*  AUTHOR                                                                */
805 /*                                                                        */
806 /*    Kenneth Maxwell, Microsoft Corporation                              */
807 /*                                                                        */
808 /*  DESCRIPTION                                                           */
809 /*                                                                        */
810 /*    This function reads code length huffman table.                      */
811 /*                                                                        */
812 /*  INPUT                                                                 */
813 /*                                                                        */
814 /*    png                                   PNG control block             */
815 /*    hclen                                 The number of "length" codes  */
816 /*                                                                        */
817 /*  OUTPUT                                                                */
818 /*                                                                        */
819 /*    None                                                                */
820 /*                                                                        */
821 /*  CALLS                                                                 */
822 /*                                                                        */
823 /*    _gx_image_reader_png_bits_get         Extract bits from PNG data    */
824 /*                                            stream                      */
825 /*    _gx_image_reader_png_bits_skip        Skip bits from PNG data stream*/
826 /*                                                                        */
827 /*  CALLED BY                                                             */
828 /*                                                                        */
829 /*    _gx_image_reader_png_IDAT_chunk_read                                */
830 /*                                                                        */
831 /*  RELEASE HISTORY                                                       */
832 /*                                                                        */
833 /*    DATE              NAME                      DESCRIPTION             */
834 /*                                                                        */
835 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
836 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
837 /*                                            resulting in version 6.1    */
838 /*                                                                        */
839 /**************************************************************************/
_gx_image_reader_png_clen_huffman_read(GX_PNG * png,UINT hclen)840 static UINT _gx_image_reader_png_clen_huffman_read(GX_PNG *png, UINT hclen)
841 {
842 
843 INT  code_value[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
844 INT  code_len[19] = {0};
845 UINT len;
846 UINT i;
847 INT  pos[16];
848 
849     for (i = 0; i < hclen; i++)
850     {
851         if (_gx_image_reader_png_bits_get(png, 3, &len) != GX_SUCCESS)
852         {
853             return GX_FAILURE;
854         }
855         _gx_image_reader_png_bits_skip(3);
856         len &= 0x7;
857 
858         /* record code len for code len alphabet */
859         code_len[code_value[i]] = (INT)len;
860 
861         /* record codes number for every code len */
862         if (len)
863         {
864             png -> gx_png_huffman_clen_bits_count[len]++;
865         }
866     }
867 
868     for (i = 1; i < 16; i++)
869     {
870         png -> gx_png_huffman_clen_bits_count[i] += png -> gx_png_huffman_clen_bits_count[i - 1];
871     }
872 
873     memset(pos, -1, 16 * sizeof(INT));
874 
875     for (i = 0; i < 19; i++)
876     {
877         if (code_len[i])
878         {
879             if (pos[code_len[i]] == -1)
880             {
881                 pos[code_len[i]] = png -> gx_png_huffman_clen_bits_count[code_len[i] - 1];
882             }
883             png -> gx_png_huffman_clen_table[pos[code_len[i]]++] = (INT)i;
884         }
885     }
886 
887     return GX_SUCCESS;
888 }
889 
890 /**************************************************************************/
891 /*                                                                        */
892 /*  FUNCTION                                               RELEASE        */
893 /*                                                                        */
894 /*    _gx_image_reader_png_ll_huffman_read                PORTABLE C      */
895 /*                                                           6.2.0        */
896 /*  AUTHOR                                                                */
897 /*                                                                        */
898 /*    Kenneth Maxwell, Microsoft Corporation                              */
899 /*                                                                        */
900 /*  DESCRIPTION                                                           */
901 /*                                                                        */
902 /*    This function reads in literal and length huffman table.            */
903 /*                                                                        */
904 /*  INPUT                                                                 */
905 /*                                                                        */
906 /*    png                                   PNG control block.            */
907 /*    hlit                                  The number of "literal" codes */
908 /*    hdist                                 The number of "distance" codes*/
909 /*                                                                        */
910 /*  OUTPUT                                                                */
911 /*                                                                        */
912 /*    None                                                                */
913 /*                                                                        */
914 /*  CALLS                                                                 */
915 /*                                                                        */
916 /*    _gx_image_reader_png_bits_get         Extract bits from PNG data    */
917 /*                                            stream                      */
918 /*    _gx_image_reader_png_bits_skip        Skip bits from PNG data stream*/
919 /*    _gx_image_reader_png_dynamic_huffman_code_find                      */
920 /*                                          Retrieve code value from      */
921 /*                                            dynamic huffman table       */
922 /*                                                                        */
923 /*  CALLED BY                                                             */
924 /*                                                                        */
925 /*    _gx_image_reader_png_IDAT_chunk_read                                */
926 /*                                                                        */
927 /*  RELEASE HISTORY                                                       */
928 /*                                                                        */
929 /*    DATE              NAME                      DESCRIPTION             */
930 /*                                                                        */
931 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
932 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
933 /*                                            resulting in version 6.1    */
934 /*  06-02-2021     Ting Zhu                 Modified comment(s),          */
935 /*                                            added invalid value check,  */
936 /*                                            resulting in version 6.1.7  */
937 /*  10-31-2022     Ting Zhu                 Modified comment(s),          */
938 /*                                            added invalid value check,  */
939 /*                                            resulting in version 6.2.0  */
940 /*                                                                        */
941 /**************************************************************************/
_gx_image_reader_png_ll_huffman_read(GX_PNG * png,UINT hlit,UINT hdist)942 static UINT _gx_image_reader_png_ll_huffman_read(GX_PNG *png, UINT hlit, UINT hdist)
943 {
944 UINT scan_buffer;
945 UINT bit_len;
946 UINT code_value;
947 UINT repeat;
948 UINT i;
949 UINT count = 0;
950 INT  pos[16];
951 INT  index;
952 
953     memset(png -> gx_png_huffman_lit_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE);
954     memset(png -> gx_png_huffman_dist_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE);
955 
956     for (i = 0; i < hlit + hdist;)
957     {
958         count++;
959         if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS)
960         {
961             return GX_FAILURE;
962         }
963 
964         if (_gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_clen_table,
965                                                            (UINT *)png -> gx_png_huffman_clen_bits_count,
966                                                            scan_buffer,
967                                                            &bit_len,
968                                                            &code_value) == 0)
969         {
970             _gx_image_reader_png_bits_skip(bit_len);
971 
972             if (code_value <= 15)
973             {
974                 /* Represent code lengths of 0-15 */
975                 if (i < hlit)
976                 {
977                     png -> gx_png_huffman_lit_code_len[i] = (INT)code_value;
978 
979                     png -> gx_png_huffman_lit_bits_count[code_value]++;
980                 }
981                 else
982                 {
983                     png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value;
984                     png -> gx_png_huffman_dist_bits_count[code_value]++;
985                 }
986 
987                 i++;
988             }
989             else
990             {
991                 if (code_value == 16)
992                 {
993                     /* repeat previous */
994                     /* 2 bits repeat length*/
995                     _gx_image_reader_png_bits_get(png, 2, &repeat);
996                     _gx_image_reader_png_bits_skip(2);
997                     repeat &= 0x3;
998                     repeat += 3;
999 
1000                     if (i < 1)
1001                     {
1002                         return GX_FALSE;
1003                     }
1004                     else if ((i - 1) < hlit)
1005                     {
1006                         code_value = (UINT)png -> gx_png_huffman_lit_code_len[i - 1];
1007                     }
1008                     else
1009                     {
1010                         code_value = (UINT)png -> gx_png_huffman_dist_code_len[i - 1 - hlit];
1011                     }
1012 
1013                     if (i < hlit)
1014                     {
1015                         png -> gx_png_huffman_lit_bits_count[code_value] += (INT)repeat;
1016 
1017                         while (repeat--)
1018                         {
1019                             png -> gx_png_huffman_lit_code_len[i++] = (INT)code_value;
1020                         }
1021                     }
1022                     else
1023                     {
1024                         png -> gx_png_huffman_dist_bits_count[code_value] += (INT)repeat;
1025 
1026                         while (repeat--)
1027                         {
1028                             png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value;
1029                             i++;
1030                         }
1031                     }
1032                 }
1033                 else
1034                 {
1035                     if (code_value == 17)
1036                     {
1037                         /* repeat 0 */
1038                         /* 3 bits repeat length */
1039                         _gx_image_reader_png_bits_get(png, 3, &repeat);
1040                         _gx_image_reader_png_bits_skip(3);
1041                         repeat &= 0x7;
1042                         repeat += 3;
1043                     }
1044                     else
1045                     {
1046                         /* code_value = 18. */
1047                         /* repeat 0*/
1048                         /* 7 bits repeat length */
1049                         _gx_image_reader_png_bits_get(png, 7, &repeat);
1050                         _gx_image_reader_png_bits_skip(7);
1051                         repeat &= 0x7f;
1052                         repeat += 11;
1053                     }
1054 
1055                     if (i < hlit)
1056                     {
1057                         memset(png -> gx_png_huffman_lit_code_len + i, 0, repeat * sizeof(INT));
1058                     }
1059                     else
1060                     {
1061                         memset(png -> gx_png_huffman_dist_code_len + i - hlit, 0, repeat * sizeof(INT));
1062                     }
1063 
1064                     i += repeat;
1065                 }
1066             }
1067         }
1068         else
1069         {
1070             /*error*/
1071             return GX_FAILURE;
1072         }
1073     }
1074 
1075     png -> gx_png_huffman_lit_bits_count[0] = 0;
1076     png -> gx_png_huffman_dist_bits_count[0] = 0;
1077 
1078     for (i = 2; i <= 16; i++)
1079     {
1080         png -> gx_png_huffman_lit_bits_count[i] += png -> gx_png_huffman_lit_bits_count[i - 1];
1081         png -> gx_png_huffman_dist_bits_count[i] += png -> gx_png_huffman_dist_bits_count[i - 1];
1082     }
1083 
1084     memset(pos, -1, 16 * sizeof(INT));
1085 
1086     for (i = 0; i < hlit; i++)
1087     {
1088         index = png -> gx_png_huffman_lit_code_len[i];
1089         if (index)
1090         {
1091             if (pos[index] == -1)
1092             {
1093                 pos[index] = png -> gx_png_huffman_lit_bits_count[index - 1];
1094             }
1095             png -> gx_png_huffman_lit_table[pos[index]++] = (INT)i;
1096         }
1097     }
1098 
1099     memset(pos, -1, 16 * sizeof(INT));
1100 
1101     for (i = 0; i < hdist; i++)
1102     {
1103         index = png -> gx_png_huffman_dist_code_len[i];
1104         if (index)
1105         {
1106             if (pos[index] == -1)
1107             {
1108                 pos[index] = png -> gx_png_huffman_dist_bits_count[index - 1];
1109             }
1110 
1111             if (pos[index] >= GX_PNG_HUFFMAN_DIST_TABLE_SIZE)
1112             {
1113                 /* Invalid data. */
1114                 return GX_FAILURE;
1115             }
1116 
1117             png -> gx_png_huffman_dist_table[pos[index]++] = (INT)i;
1118         }
1119     }
1120 
1121     return GX_SUCCESS;
1122 }
1123 
1124 /**************************************************************************/
1125 /*                                                                        */
1126 /*  FUNCTION                                               RELEASE        */
1127 /*                                                                        */
1128 /*    _gx_image_reader_png_huffcode_decode                PORTABLE C      */
1129 /*                                                           6.1          */
1130 /*  AUTHOR                                                                */
1131 /*                                                                        */
1132 /*    Kenneth Maxwell, Microsoft Corporation                              */
1133 /*                                                                        */
1134 /*  DESCRIPTION                                                           */
1135 /*                                                                        */
1136 /*    This function decodes the Huffman codes.                            */
1137 /*                                                                        */
1138 /*  INPUT                                                                 */
1139 /*                                                                        */
1140 /*    png                                   PNG control block.            */
1141 /*    dynamic                               True, use dynamic huff table  */
1142 /*                                          False, use fixed huff table   */
1143 /*    decoded_data_size                     Expected decoded data size    */
1144 /*                                                                        */
1145 /*  OUTPUT                                                                */
1146 /*                                                                        */
1147 /*    None                                                                */
1148 /*                                                                        */
1149 /*  CALLS                                                                 */
1150 /*                                                                        */
1151 /*    _gx_image_reader_png_bits_get         Extract bits from PNG data    */
1152 /*                                            stream                      */
1153 /*    _gx_image_reader_png_bits_skip        Skip bits from PNG data stream*/
1154 /*    _gx_image_reader_png_dynamic_huffman_code_find                      */
1155 /*                                          Retrieve code value from      */
1156 /*                                            dynamic huffman table       */
1157 /*    _gx_image_reader_png_fixed_ll_huffman_code_find                     */
1158 /*                                          Retrieve code value from      */
1159 /*                                            fixed huffman table         */
1160 /*                                                                        */
1161 /*  CALLED BY                                                             */
1162 /*                                                                        */
1163 /*    _gx_image_reader_png_IDAT_chunk_read                                */
1164 /*                                                                        */
1165 /*  RELEASE HISTORY                                                       */
1166 /*                                                                        */
1167 /*    DATE              NAME                      DESCRIPTION             */
1168 /*                                                                        */
1169 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1170 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1171 /*                                            added data boundary check,  */
1172 /*                                            fixed gcc compile warning,  */
1173 /*                                            resulting in version 6.1    */
1174 /*                                                                        */
1175 /**************************************************************************/
_gx_image_reader_png_huffcode_decode(GX_PNG * png,GX_BOOL dynamic,UINT decoded_data_size)1176 static UINT _gx_image_reader_png_huffcode_decode(GX_PNG *png, GX_BOOL dynamic, UINT decoded_data_size)
1177 {
1178 UINT scan_buffer;
1179 UINT bit_len = 0;
1180 UINT code_value = 300;
1181 UINT length;
1182 UINT distance;
1183 UINT extra_bits;
1184 UINT copy_len;
1185 
1186     while (1)
1187     {
1188         if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS)
1189         {
1190             return GX_FAILURE;
1191         }
1192 
1193         /* Decode literal/length value from input stream */
1194         if (dynamic)
1195         {
1196             _gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_lit_table,
1197                                                            (UINT *)png -> gx_png_huffman_lit_bits_count,
1198                                                            scan_buffer,
1199                                                            &bit_len,
1200                                                            &code_value);
1201         }
1202         else
1203         {
1204             _gx_image_reader_png_fixed_ll_huffman_code_find(scan_buffer, &bit_len, &code_value);
1205         }
1206 
1207         _gx_image_reader_png_bits_skip(bit_len);
1208 
1209         if (code_value < 256)
1210         {
1211             if ((UINT)(png -> gx_png_decoded_data_len + 1) > decoded_data_size)
1212             {
1213                 /* Decoded data size exceed allocated buffer size. */
1214                 return GX_FAILURE;
1215             }
1216 
1217             png -> gx_png_decoded_data[png -> gx_png_decoded_data_len++] = (GX_UBYTE)code_value;
1218         }
1219         else if (code_value == 256)
1220         {
1221             /* End of the block */
1222             break;
1223         }
1224         else
1225         {
1226             if (code_value < 265)
1227             {
1228                 /* 0 extra bits */
1229                 length = 3 + code_value - 257;
1230             }
1231             else if (code_value < 285)
1232             {
1233                 extra_bits = 1 + (code_value - 265) / 4;
1234                 _gx_image_reader_png_bits_get(png, extra_bits, &length);
1235                 _gx_image_reader_png_bits_skip(extra_bits);
1236                 length <<= (32 - extra_bits);
1237                 length >>= (32 - extra_bits);
1238 
1239                 length += 3u + (1u << (extra_bits + 2)) + ((1u << extra_bits) * ((code_value - 265) & 0x3));
1240             }
1241             else if (code_value == 285)
1242             {
1243                 /* 0 extra bits */
1244                 length = 258;
1245             }
1246             else
1247             {
1248                 /* This should not happen. */
1249                 return GX_FAILURE;
1250             }
1251 
1252             if (dynamic)
1253             {
1254                 _gx_image_reader_png_bits_get(png, 16, &scan_buffer);
1255 
1256                 /*decode distance from input stream */
1257                 _gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_dist_table,
1258                                                                (UINT *)png -> gx_png_huffman_dist_bits_count,
1259                                                                scan_buffer,
1260                                                                &bit_len,
1261                                                                &code_value);
1262 
1263                 _gx_image_reader_png_bits_skip(bit_len);
1264             }
1265             else
1266             {
1267                 /* Decodes 5-bits distance codes. */
1268                 _gx_image_reader_png_bits_get(png, 5, &scan_buffer);
1269                 _gx_image_reader_png_bits_skip(5);
1270                 code_value = scan_buffer & 0x1f;
1271                 _gx_image_reader_png_bits_revert(&code_value, 5);
1272             }
1273 
1274             if (code_value < 4)
1275             {
1276                 distance = 1 + code_value;
1277             }
1278             else if (code_value < 30)
1279             {
1280                 extra_bits = 1 + (code_value - 4) / 2;
1281 
1282                 _gx_image_reader_png_bits_get(png, extra_bits, &distance);
1283                 _gx_image_reader_png_bits_skip(extra_bits);
1284 
1285                 distance <<= (32 - extra_bits);
1286                 distance >>= (32 - extra_bits);
1287 
1288                 distance += 1u + (1u << (extra_bits + 1)) + (1u << extra_bits) * ((code_value - 4) & 0x1);
1289             }
1290             else
1291             {
1292                 /* This should not happen. */
1293                 return GX_FALSE;
1294             }
1295 
1296             /* move backwards distance bytes in the output stream, and copy
1297                length bytes from this position to the output stream. */
1298 
1299             while (length)
1300             {
1301                 if (length > distance)
1302                 {
1303                     copy_len = distance;
1304                     length -= distance;
1305                 }
1306                 else
1307                 {
1308                     copy_len = length;
1309                     length = 0;
1310                 }
1311 
1312                 if ((distance > (UINT)png -> gx_png_decoded_data_len) ||
1313                     ((UINT)png -> gx_png_decoded_data_len + copy_len > decoded_data_size))
1314                 {
1315 
1316                     /* Distance exceed current decoded data length or copied length exceed remaining buffer size. */
1317                     return GX_FAILURE;
1318                 }
1319 
1320                 memcpy(png -> gx_png_decoded_data + png -> gx_png_decoded_data_len, /* Use case of memcpy is verified. */
1321                        png -> gx_png_decoded_data + png -> gx_png_decoded_data_len - distance,
1322                        copy_len * sizeof(GX_UBYTE));
1323                 png -> gx_png_decoded_data_len += (INT)copy_len;
1324             }
1325         }
1326     }
1327 
1328     return GX_SUCCESS;
1329 }
1330 
1331 /**************************************************************************/
1332 /*                                                                        */
1333 /*  FUNCTION                                               RELEASE        */
1334 /*                                                                        */
1335 /*    _gx_image_reader_png_tRNS_chunk_read                PORTABLE C      */
1336 /*                                                           6.1          */
1337 /*  AUTHOR                                                                */
1338 /*                                                                        */
1339 /*    Kenneth Maxwell, Microsoft Corporation                              */
1340 /*                                                                        */
1341 /*  DESCRIPTION                                                           */
1342 /*                                                                        */
1343 /*    This function reads in the tRNS chunk information.                  */
1344 /*                                                                        */
1345 /*  INPUT                                                                 */
1346 /*                                                                        */
1347 /*    png                                   PNG control block.            */
1348 /*                                                                        */
1349 /*  OUTPUT                                                                */
1350 /*                                                                        */
1351 /*    status                                Completion status             */
1352 /*                                                                        */
1353 /*  CALLS                                                                 */
1354 /*                                                                        */
1355 /*    _gx_system_memory_allocator           Application defined memory    */
1356 /*                                            allocation function         */
1357 /*                                                                        */
1358 /*  CALLED BY                                                             */
1359 /*                                                                        */
1360 /*    _gx_image_reader_png_decode                                         */
1361 /*                                                                        */
1362 /*  RELEASE HISTORY                                                       */
1363 /*                                                                        */
1364 /*    DATE              NAME                      DESCRIPTION             */
1365 /*                                                                        */
1366 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1367 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1368 /*                                            resulting in version 6.1    */
1369 /*                                                                        */
1370 /**************************************************************************/
_gx_image_reader_png_tRNS_chunk_read(GX_PNG * png)1371 static UINT _gx_image_reader_png_tRNS_chunk_read(GX_PNG *png)
1372 {
1373 INT index;
1374 
1375     if ((png -> gx_png_color_type == 4) || (png -> gx_png_color_type == 6))
1376     {
1377         /* tRNS is prohibited for the other color types. */
1378         return GX_FAILURE;
1379     }
1380 
1381     if (png -> gx_png_color_type == 3)
1382     {
1383         /* Contains a series of one-byte alpha values.  */
1384         png -> gx_png_trans_num = png -> gx_png_trunk_end_index - png -> gx_png_data_index;
1385 
1386         /* For color type 3, tRNS can contain fewer values than there are palette entries. */
1387         if (png -> gx_png_trans_num > 256)
1388         {
1389             return GX_INVALID_VALUE;
1390         }
1391     }
1392     else
1393     {
1394         /* For color type 0, the tRNS chunk contains a single two-bytes gray level value.
1395            For color type 2, the tRNS chunk contains a single two-bytes RGB color value. */
1396         png -> gx_png_trans_num = (png -> gx_png_trunk_end_index - png -> gx_png_data_index) >> 1;
1397 
1398         if (png -> gx_png_trans_num > 3)
1399         {
1400             return GX_INVALID_VALUE;
1401         }
1402     }
1403 
1404     /* Then trans num is no bigger than 256, multiplication will not overflow. */
1405     png -> gx_png_trans = (GX_COLOR *)_gx_system_memory_allocator((ULONG)png -> gx_png_trans_num * sizeof(GX_COLOR));
1406 
1407     if (png -> gx_png_trans == GX_NULL)
1408     {
1409         return GX_SYSTEM_MEMORY_ERROR;
1410     }
1411 
1412     for (index = 0; index < png -> gx_png_trans_num; index++)
1413     {
1414         png -> gx_png_trans[index] = png -> gx_png_data[png -> gx_png_data_index++];
1415 
1416         if (png -> gx_png_color_type != 3)
1417         {
1418             png -> gx_png_trans[index] <<= 8;
1419             png -> gx_png_trans[index] |= png -> gx_png_data[png -> gx_png_data_index++];
1420         }
1421     }
1422 
1423     return GX_SUCCESS;
1424 }
1425 
1426 /**************************************************************************/
1427 /*                                                                        */
1428 /*  FUNCTION                                               RELEASE        */
1429 /*                                                                        */
1430 /*    _gx_image_reader_png_IDAT_chunk_read                PORTABLE C      */
1431 /*                                                           6.1          */
1432 /*  AUTHOR                                                                */
1433 /*                                                                        */
1434 /*    Kenneth Maxwell, Microsoft Corporation                              */
1435 /*                                                                        */
1436 /*  DESCRIPTION                                                           */
1437 /*                                                                        */
1438 /*    This function reads in the IDAT chunk information and start         */
1439 /*    decoding.                                                           */
1440 /*                                                                        */
1441 /*  INPUT                                                                 */
1442 /*                                                                        */
1443 /*    png                                   PNG control block.            */
1444 /*                                                                        */
1445 /*  OUTPUT                                                                */
1446 /*                                                                        */
1447 /*    status                                Completion status             */
1448 /*                                                                        */
1449 /*  CALLS                                                                 */
1450 /*                                                                        */
1451 /*    _gx_image_reader_png_bits_get         Extract bits from PNG data    */
1452 /*                                            stream                      */
1453 /*    _gx_image_reader_png_bits_skip        Skip bits from PNG data stream*/
1454 /*    _gx_image_reader_png_clen_huffman_read                              */
1455 /*                                          Read code length huffman table*/
1456 /*    _gx_image_reader_png_ll_huffman_read  Read literal and length       */
1457 /*                                            huffman table               */
1458 /*    _gx_image_reader_png_huffcode_decode  Decode huffman codes          */
1459 /*                                                                        */
1460 /*  CALLED BY                                                             */
1461 /*                                                                        */
1462 /*    _gx_image_reader_png_decode                                         */
1463 /*                                                                        */
1464 /*  RELEASE HISTORY                                                       */
1465 /*                                                                        */
1466 /*    DATE              NAME                      DESCRIPTION             */
1467 /*                                                                        */
1468 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1469 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1470 /*                                            added data boundary check,  */
1471 /*                                            resulting in version 6.1    */
1472 /*                                                                        */
1473 /**************************************************************************/
_gx_image_reader_png_IDAT_chunk_read(GX_PNG * png)1474 static UINT _gx_image_reader_png_IDAT_chunk_read(GX_PNG *png)
1475 {
1476 /*zlib format
1477    +---+---+
1478    |CMF|FLG|
1479    +---+---+
1480    if FLG.FDICT set
1481    +---+---+---+---+
1482    |     DTCTID    |
1483    +---+---+---+---+
1484    +=====================+---+---+---+---+
1485    |...compressed data...| 32bit checksum|
1486    +=====================+---+---+---+---+
1487 */
1488 UINT CMF;
1489 UINT FLG;
1490 INT  compress_method;
1491 INT  window_size;
1492 INT  fdict;
1493 UINT header;
1494 INT  hlit;
1495 INT  hdist;
1496 INT  hclen;
1497 UINT alloc_size;
1498 INT  len;
1499 INT  nlen;
1500 
1501     if (_gx_image_reader_png_bits_get(png, 8, &CMF) != GX_SUCCESS)
1502     {
1503         return GX_FAILURE;
1504     }
1505 
1506     _gx_image_reader_png_bits_skip(8);
1507 
1508     if (_gx_image_reader_png_bits_get(png, 8, &FLG) != GX_SUCCESS)
1509     {
1510         return GX_FAILURE;
1511     }
1512 
1513     _gx_image_reader_png_bits_skip(8);
1514 
1515     compress_method = CMF & 0x0f;
1516     window_size = 2 << (((CMF & 0xf0) >> 4) + 8);
1517     fdict = FLG & 0x20;
1518 
1519     if ((fdict != 0) ||
1520         (window_size > 65536) ||
1521         (compress_method != 8))
1522     {
1523         return GX_FAILURE;
1524     }
1525 
1526     /* Safe int math is not required here, calling function limits max width, height to 14 bits so
1527        overflow cannot occur. */
1528     alloc_size = (UINT)(png -> gx_png_height * ((png -> gx_png_width * png -> gx_png_bpp + 7) / 8));
1529     alloc_size = alloc_size + (UINT)png -> gx_png_height;
1530     png -> gx_png_decoded_data = (GX_UBYTE *)_gx_system_memory_allocator(alloc_size);
1531     png -> gx_png_decoded_data_len = 0;
1532 
1533     if (png -> gx_png_decoded_data == GX_NULL)
1534     {
1535         return GX_SYSTEM_MEMORY_ERROR;
1536     }
1537 
1538     do
1539     {
1540         /* The header of one block */
1541         if (_gx_image_reader_png_bits_get(png, 8, &header) != GX_SUCCESS)
1542         {
1543             return GX_FAILURE;
1544         }
1545 
1546         if ((header & 0x6) == 0x00)
1547         {
1548             _gx_image_reader_png_bits_skip(3);
1549 
1550             /* no compression */
1551             _gx_image_reader_png_bits_skip(_bit_count & 0x7);
1552             if (_bit_count)
1553             {
1554                 png -> gx_png_data_index -= (INT)(_bit_count / 8);
1555                 _gx_image_reader_png_bits_skip(_bit_count);
1556             }
1557 
1558             /* 4 = 2 bytes len + 2 bytes nlen. */
1559             if (png -> gx_png_data_index + 4 > png -> gx_png_data_size)
1560             {
1561                 return GX_INVALID_SIZE;
1562             }
1563 
1564             /* Read "LEN".  */
1565             len = png -> gx_png_data[png -> gx_png_data_index];
1566             png -> gx_png_data_index++;
1567             len |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
1568             png -> gx_png_data_index++;
1569 
1570             /* Read "NLEN".  */
1571             nlen = png -> gx_png_data[png -> gx_png_data_index];
1572             png -> gx_png_data_index++;
1573             nlen |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
1574             png -> gx_png_data_index++;
1575 
1576             if (len + nlen != 65535)
1577             {
1578                 /* NLEN is not one's complement of LEN. */
1579                 return GX_FAILURE;
1580             }
1581 
1582             /* Read data to outbuffer directly */
1583             if (len)
1584             {
1585                 if ((UINT)(png -> gx_png_decoded_data_len + len) > alloc_size)
1586                 {
1587                     /* Copied size exceed remaining buffer size. */
1588                     return GX_FAILURE;
1589                 }
1590 
1591                 if (png -> gx_png_data_index + len > png -> gx_png_data_size)
1592                 {
1593                     return GX_INVALID_SIZE;
1594                 }
1595 
1596                 memcpy(png -> gx_png_decoded_data + png -> gx_png_decoded_data_len, png -> gx_png_data + png -> gx_png_data_index, (UINT)len); /* Use case of memcpy is verified. */
1597                 png -> gx_png_data_index += len;
1598                 png -> gx_png_decoded_data_len += len;
1599             }
1600         }
1601         else if ((header & 0x6) == 0x2)
1602         {
1603             _gx_image_reader_png_bits_skip(3);
1604 
1605             /* compressed with fixed Huffman codes */
1606             if (_gx_image_reader_png_huffcode_decode(png, GX_FALSE, alloc_size) != GX_SUCCESS)
1607             {
1608                 return GX_FAILURE;
1609             }
1610         }
1611         else if ((header & 0x6) == 0x4)
1612         {
1613             /* compressed with dynamic Huffman codes */
1614             _gx_image_reader_png_bits_skip(3);
1615 
1616             /* # of Literal/Length codes */
1617             _gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hlit);
1618 
1619             _gx_image_reader_png_bits_skip(5);
1620             hlit = (hlit & 0x1f) + 257;
1621 
1622             /* # of Distance codes */
1623             if (_gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hdist) != GX_SUCCESS)
1624             {
1625                 return GX_FAILURE;
1626             }
1627             _gx_image_reader_png_bits_skip(5);
1628             hdist = (hdist & 0x1f) + 1;
1629 
1630             /* # of Code Length codes */
1631             if (_gx_image_reader_png_bits_get(png, 4, (unsigned int *)&hclen) != GX_SUCCESS)
1632             {
1633                 return GX_FAILURE;
1634             }
1635             _gx_image_reader_png_bits_skip(4);
1636             hclen = (hclen & 0xf) + 4;
1637 
1638             memset(png -> gx_png_huffman_clen_bits_count, 0, 17 * sizeof(INT));
1639             memset(png -> gx_png_huffman_clen_table, 0, 20 * sizeof(INT));
1640             memset(png -> gx_png_huffman_lit_bits_count, 0, 17 * sizeof(INT));
1641             memset(png -> gx_png_huffman_lit_table, 0, GX_PNG_HUFFMAN_LIT_TABLE_SIZE * sizeof(int));
1642             memset(png -> gx_png_huffman_dist_bits_count, 0, 17 * sizeof(INT));
1643             memset(png -> gx_png_huffman_dist_table, 0, 30 * sizeof(INT));
1644 
1645             if (_gx_image_reader_png_clen_huffman_read(png, (UINT)hclen) != GX_SUCCESS)
1646             {
1647                 return GX_FAILURE;
1648             }
1649 
1650             if (_gx_image_reader_png_ll_huffman_read(png, (UINT)hlit, (UINT)hdist) != GX_SUCCESS)
1651             {
1652                 return GX_FAILURE;
1653             }
1654 
1655             if (_gx_image_reader_png_huffcode_decode(png, GX_TRUE, alloc_size) != GX_SUCCESS)
1656             {
1657                 return GX_FAILURE;
1658             }
1659         }
1660         else
1661         {
1662             /* error */
1663             return GX_FAILURE;
1664         }
1665     } while ((header & 0x1) != 0x1);
1666 
1667     /* Skip checksum */
1668     png -> gx_png_data_index = png -> gx_png_trunk_end_index;
1669     _gx_image_reader_png_bits_skip(_bit_count);
1670 
1671     if (alloc_size != (UINT)png -> gx_png_decoded_data_len)
1672     {
1673         /* Decoded data size doesn't match prediction. */
1674         return GX_FAILURE;
1675     }
1676 
1677     return GX_SUCCESS;
1678 }
1679 
1680 /**************************************************************************/
1681 /*                                                                        */
1682 /*  FUNCTION                                               RELEASE        */
1683 /*                                                                        */
1684 /*    _gx_image_reader_png_gAMA_chunk_read                PORTABLE C      */
1685 /*                                                           6.1          */
1686 /*  AUTHOR                                                                */
1687 /*                                                                        */
1688 /*    Kenneth Maxwell, Microsoft Corporation                              */
1689 /*                                                                        */
1690 /*  DESCRIPTION                                                           */
1691 /*                                                                        */
1692 /*    This function reads in the gAMA chunk information.                  */
1693 /*                                                                        */
1694 /*  INPUT                                                                 */
1695 /*                                                                        */
1696 /*    png                                   PNG control block.            */
1697 /*                                                                        */
1698 /*  OUTPUT                                                                */
1699 /*                                                                        */
1700 /*    status                                Completion status             */
1701 /*                                                                        */
1702 /*  CALLS                                                                 */
1703 /*                                                                        */
1704 /*    _gx_image_reader_png_4bytes_read      Read 4 bytes and pact it to   */
1705 /*                                            an INT value                */
1706 /*                                                                        */
1707 /*  CALLED BY                                                             */
1708 /*                                                                        */
1709 /*    _gx_image_reader_png_decode                                         */
1710 /*                                                                        */
1711 /*  RELEASE HISTORY                                                       */
1712 /*                                                                        */
1713 /*    DATE              NAME                      DESCRIPTION             */
1714 /*                                                                        */
1715 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1716 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1717 /*                                            added data boundary check,  */
1718 /*                                            resulting in version 6.1    */
1719 /*                                                                        */
1720 /**************************************************************************/
_gx_image_reader_png_gAMA_chunk_read(GX_PNG * png)1721 static UINT _gx_image_reader_png_gAMA_chunk_read(GX_PNG *png)
1722 {
1723     if (png -> gx_png_data_index + 4 > png -> gx_png_trunk_end_index)
1724     {
1725         return GX_INVALID_SIZE;
1726     }
1727 
1728     /* Specifies the gamma of the camera that produced the image. */
1729 
1730     /* A gamma of 0.45 would be stored as teh integer 45000. */
1731     _gx_image_reader_png_4bytes_read(png, &png -> gx_png_gamma);
1732 
1733     return GX_SUCCESS;
1734 }
1735 
1736 /**************************************************************************/
1737 /*                                                                        */
1738 /*  FUNCTION                                               RELEASE        */
1739 /*                                                                        */
1740 /*    _gx_image_reader_png_PLTE_chunk_read                PORTABLE C      */
1741 /*                                                           6.1          */
1742 /*  AUTHOR                                                                */
1743 /*                                                                        */
1744 /*    Kenneth Maxwell, Microsoft Corporation                              */
1745 /*                                                                        */
1746 /*  DESCRIPTION                                                           */
1747 /*                                                                        */
1748 /*    This function reads in the PLTE chunk information.                  */
1749 /*                                                                        */
1750 /*  INPUT                                                                 */
1751 /*                                                                        */
1752 /*    png                                   PNG control block.            */
1753 /*                                                                        */
1754 /*  OUTPUT                                                                */
1755 /*                                                                        */
1756 /*    status                                Completion status             */
1757 /*                                                                        */
1758 /*  CALLS                                                                 */
1759 /*                                                                        */
1760 /*    None                                                                */
1761 /*                                                                        */
1762 /*  CALLED BY                                                             */
1763 /*                                                                        */
1764 /*    _gx_image_reader_png_decode                                         */
1765 /*                                                                        */
1766 /*  RELEASE HISTORY                                                       */
1767 /*                                                                        */
1768 /*    DATE              NAME                      DESCRIPTION             */
1769 /*                                                                        */
1770 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1771 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1772 /*                                            resulting in version 6.1    */
1773 /*                                                                        */
1774 /**************************************************************************/
_gx_image_reader_png_PLTE_chunk_read(GX_PNG * png)1775 static UINT _gx_image_reader_png_PLTE_chunk_read(GX_PNG *png)
1776 {
1777 INT      index;
1778 GX_UBYTE red;
1779 GX_UBYTE green;
1780 GX_UBYTE blue;
1781 
1782     png -> gx_png_palette_table_size = (png -> gx_png_trunk_end_index - png -> gx_png_data_index) / 3;
1783 
1784     /* The PLTE chunk contains from 1 to 256 palette entries. */
1785     if (png -> gx_png_palette_table_size > 256)
1786     {
1787         return GX_INVALID_VALUE;
1788     }
1789 
1790     for (index = 0; index < png -> gx_png_palette_table_size; index++)
1791     {
1792         red = png -> gx_png_data[png -> gx_png_data_index++];
1793         green = png -> gx_png_data[png -> gx_png_data_index++];
1794         blue = png -> gx_png_data[png -> gx_png_data_index++];
1795 
1796         png -> gx_png_palette_table[index] = (GX_COLOR)((red << 16) | (green << 8) | blue);
1797     }
1798 
1799     return GX_SUCCESS;
1800 }
1801 
1802 /**************************************************************************/
1803 /*                                                                        */
1804 /*  FUNCTION                                               RELEASE        */
1805 /*                                                                        */
1806 /*    _gx_image_reader_png_paeth_predictor                PORTABLE C      */
1807 /*                                                           6.1.8        */
1808 /*  AUTHOR                                                                */
1809 /*                                                                        */
1810 /*    Kenneth Maxwell, Microsoft Corporation                              */
1811 /*                                                                        */
1812 /*  DESCRIPTION                                                           */
1813 /*                                                                        */
1814 /*    This function performs Paeth filter algorithm.                      */
1815 /*                                                                        */
1816 /*  INPUT                                                                 */
1817 /*                                                                        */
1818 /*    a                                     Byte of left pixel.           */
1819 /*    b                                     Byte of above pixel.          */
1820 /*    c                                     Byte of upper left pixel.     */
1821 /*                                                                        */
1822 /*  OUTPUT                                                                */
1823 /*                                                                        */
1824 /*    status                                The nearest of a, b, c.       */
1825 /*                                                                        */
1826 /*  CALLS                                                                 */
1827 /*                                                                        */
1828 /*    None                                                                */
1829 /*                                                                        */
1830 /*  CALLED BY                                                             */
1831 /*                                                                        */
1832 /*    _gx_image_reader_png_unfilter                                       */
1833 /*                                                                        */
1834 /*  RELEASE HISTORY                                                       */
1835 /*                                                                        */
1836 /*    DATE              NAME                      DESCRIPTION             */
1837 /*                                                                        */
1838 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1839 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1840 /*                                            resulting in version 6.1    */
1841 /*  08-02-2021     Kenneth Maxwell          Modified comment(s),          */
1842 /*                                            replaced abs with GX_ABS,   */
1843 /*                                            resulting in version 6.1.8  */
1844 /*                                                                        */
1845 /**************************************************************************/
_gx_image_reader_png_paeth_predictor(GX_UBYTE a,GX_UBYTE b,GX_UBYTE c)1846 static GX_UBYTE _gx_image_reader_png_paeth_predictor(GX_UBYTE a, GX_UBYTE b, GX_UBYTE c)
1847 {
1848 INT p;
1849 INT pa, pb, pc;
1850 
1851     p = a + b - c;
1852     pa = GX_ABS(p - a);
1853     pb = GX_ABS(p - b);
1854     pc = GX_ABS(p - c);
1855 
1856     /*return nearest of a, b, c */
1857 
1858     if ((pa <= pb) && (pa <= pc))
1859     {
1860         return a;
1861     }
1862     else if (pb <= pc)
1863     {
1864         return b;
1865     }
1866     else
1867     {
1868         return c;
1869     }
1870 }
1871 
1872 /**************************************************************************/
1873 /*                                                                        */
1874 /*  FUNCTION                                               RELEASE        */
1875 /*                                                                        */
1876 /*    _gx_image_reader_png_unfilter                       PORTABLE C      */
1877 /*                                                           6.2.0        */
1878 /*  AUTHOR                                                                */
1879 /*                                                                        */
1880 /*    Kenneth Maxwell, Microsoft Corporation                              */
1881 /*                                                                        */
1882 /*  DESCRIPTION                                                           */
1883 /*                                                                        */
1884 /*    This function reverts the effect of filter.                         */
1885 /*                                                                        */
1886 /*  INPUT                                                                 */
1887 /*                                                                        */
1888 /*    png                                   PNG control block.            */
1889 /*                                                                        */
1890 /*  OUTPUT                                                                */
1891 /*                                                                        */
1892 /*    None                                                                */
1893 /*                                                                        */
1894 /*  CALLS                                                                 */
1895 /*                                                                        */
1896 /*    memmove                                                             */
1897 /*    _gx_image_reader_png_paeth_predictor  Perform Paeth filter algorithm*/
1898 /*                                                                        */
1899 /*  CALLED BY                                                             */
1900 /*                                                                        */
1901 /*    _gx_image_reader_png_decode                                         */
1902 /*                                                                        */
1903 /*  RELEASE HISTORY                                                       */
1904 /*                                                                        */
1905 /*    DATE              NAME                      DESCRIPTION             */
1906 /*                                                                        */
1907 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
1908 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
1909 /*                                            resulting in version 6.1    */
1910 /*  10-31-2022     Kenneth Maxwell          Modified comment(s),          */
1911 /*                                            added null pointer check,   */
1912 /*                                            resulting in version 6.2.0  */
1913 /*                                                                        */
1914 /**************************************************************************/
_gx_image_reader_png_unfilter(GX_PNG * png)1915 static UINT _gx_image_reader_png_unfilter(GX_PNG *png)
1916 {
1917 INT filter_type;
1918 INT byte_width;
1919 INT pos;
1920 INT bpp = png -> gx_png_bpp;
1921 INT x;
1922 INT y;
1923 
1924     if (png -> gx_png_decoded_data == GX_NULL)
1925     {
1926         /* This happens when IDAT chunk is missing. */
1927         return GX_FAILURE;
1928     }
1929 
1930     byte_width = (png -> gx_png_width * bpp + 7) >> 3;
1931     bpp = (bpp + 7) >> 3;
1932 
1933     for (y = 0; y < png -> gx_png_height; y++)
1934     {
1935         filter_type = png -> gx_png_decoded_data[y * byte_width + y];
1936 
1937         pos = y * byte_width;
1938         memmove(png -> gx_png_decoded_data + pos, png -> gx_png_decoded_data + pos + y + 1, (UINT)byte_width);
1939 
1940         switch (filter_type)
1941         {
1942         case 0:
1943             break;
1944         case 1:
1945             /* sub(x) + raw(x-bpp)*/
1946             for (x = bpp; x < byte_width; x++)
1947             {
1948                 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - bpp]);
1949             }
1950             break;
1951         case 2:
1952             /*up(x) + prior(x)*/
1953             if (y == 0)
1954             {
1955                 break;
1956             }
1957 
1958             for (x = 0; x < byte_width; x++)
1959             {
1960                 png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - byte_width]);
1961             }
1962             break;
1963         case 3:
1964             /* average(x) + floor((raw(x-bpp)+prior(x))/2 */
1965             if (y == 0)
1966             {
1967                 for (x = bpp; x < byte_width; x++)
1968                 {
1969                     png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + (png -> gx_png_decoded_data[pos + x - bpp] >> 1));
1970                 }
1971             }
1972             else
1973             {
1974                 for (x = 0; x < bpp; x++)
1975                 {
1976                     png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + (png -> gx_png_decoded_data[pos + x - byte_width] >> 1));
1977                 }
1978 
1979                 for (x = bpp; x < byte_width; x++)
1980                 {
1981                     png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + ((png -> gx_png_decoded_data[pos + x - bpp] +
1982                                                                                                              png -> gx_png_decoded_data[pos + x - byte_width]) >> 1));
1983                 }
1984             }
1985             break;
1986         case 4:
1987             /* paeth(x) + paethpredictor(raw(x-bpp), prior(x), prior(x-bpp)) */
1988             if (y == 0)
1989             {
1990                 for (x = bpp; x < byte_width; x++)
1991                 {
1992                     png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - bpp]);
1993                 }
1994             }
1995             else
1996             {
1997                 for (x = 0; x < bpp; x++)
1998                 {
1999                     png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + png -> gx_png_decoded_data[pos + x - byte_width]);
2000                 }
2001 
2002                 for (x = bpp; x < byte_width; x++)
2003                 {
2004                     png -> gx_png_decoded_data[pos + x] = (GX_UBYTE)(png -> gx_png_decoded_data[pos + x] + _gx_image_reader_png_paeth_predictor(png -> gx_png_decoded_data[pos + x - bpp],
2005                                                                                                                                                 png -> gx_png_decoded_data[pos + x - byte_width],
2006                                                                                                                                                 png -> gx_png_decoded_data[pos + x - byte_width - bpp]));
2007                 }
2008             }
2009             break;
2010         default:
2011             return GX_FAILURE;
2012         }
2013     }
2014 
2015     png -> gx_png_decoded_data_len -= png -> gx_png_height;
2016 
2017     return GX_SUCCESS;
2018 }
2019 
2020 /**************************************************************************/
2021 /*                                                                        */
2022 /*  FUNCTION                                               RELEASE        */
2023 /*                                                                        */
2024 /*    _gx_image_reader_png_decode                         PORTABLE C      */
2025 /*                                                           6.2.0        */
2026 /*  AUTHOR                                                                */
2027 /*                                                                        */
2028 /*    Kenneth Maxwell, Microsoft Corporation                              */
2029 /*                                                                        */
2030 /*  DESCRIPTION                                                           */
2031 /*                                                                        */
2032 /*    This function decode a PNG format image.                            */
2033 /*                                                                        */
2034 /*  INPUT                                                                 */
2035 /*                                                                        */
2036 /*    inmap                                 Input pixelmap                */
2037 /*    outmap                                Output pixelmap               */
2038 /*                                                                        */
2039 /*  OUTPUT                                                                */
2040 /*                                                                        */
2041 /*    status                                Completion status             */
2042 /*                                                                        */
2043 /*  CALLS                                                                 */
2044 /*                                                                        */
2045 /*    strncmp                                                             */
2046 /*    _gx_system_memory_allocator           Application defined memory    */
2047 /*                                            allocation function         */
2048 /*    _gx_system_memory_free                Application defined memory    */
2049 /*                                            free function               */
2050 /*    _gx_image_reader_png_crc_table_make   Create a crc table            */
2051 /*    _gx_image_reader_png_crc_get          Calculate crc value of        */
2052 /*                                            specified data              */
2053 /*    _gx_image_reader_png_4bytes_read      Read 4 bytes and pack it to   */
2054 /*                                            INT type value              */
2055 /*    _gx_image_reader_png_chunk_type_read  Read chunk type information   */
2056 /*    _gx_image_reader_png_IDAT_chunk_read  Read IDAT chunk information   */
2057 /*                                            and start decoding          */
2058 /*    _gx_image_reader_png_IHDR_chunk_read  Read IHDR chunk information   */
2059 /*    _gx_image_reader_png_gAMA_chunk_read  Read gAMA chunk information   */
2060 /*    _gx_image_reader_png_PLTE_chunk_read  Read PLTE chunk information   */
2061 /*    _gx_image_reader_png_tRNS_chunk_read  Read tRNS chunk information   */
2062 /*    _gx_image_reader_png_unfilter         Revert effect of filter       */
2063 /*                                                                        */
2064 /*  CALLED BY                                                             */
2065 /*                                                                        */
2066 /*    _gx_image_reader_image_decode                                       */
2067 /*                                                                        */
2068 /*  RELEASE HISTORY                                                       */
2069 /*                                                                        */
2070 /*    DATE              NAME                      DESCRIPTION             */
2071 /*                                                                        */
2072 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
2073 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
2074 /*                                            added data boundary check,  */
2075 /*                                            resulting in version 6.1    */
2076 /*  06-02-2021     Ting Zhu                 Modified comment(s), and      */
2077 /*                                            improved png decoding       */
2078 /*                                            performance,                */
2079 /*                                            resulting in version 6.1.7  */
2080 /*  10-31-2022     Ting Zhu                 Modified comment(s), and      */
2081 /*                                            added invalid value check,  */
2082 /*                                            resulting in version 6.2.0  */
2083 /*                                                                        */
2084 /**************************************************************************/
_gx_image_reader_png_decode(GX_CONST GX_UBYTE * read_data,ULONG data_size,GX_PIXELMAP * outmap)2085 UINT _gx_image_reader_png_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size, GX_PIXELMAP *outmap)
2086 {
2087 UINT    status = GX_SUCCESS;
2088 GX_PNG  png;
2089 INT     data_len;
2090 CHAR    chunk_type[4];
2091 INT     checksum;
2092 GX_BOOL idat_done = GX_FALSE;
2093 INT    *scratch_buffer;
2094 INT     scratch_index = 0;
2095 GX_BOOL decoded_done = GX_FALSE;
2096 
2097     if (data_size < 8)
2098     {
2099         return GX_INVALID_SIZE;
2100     }
2101 
2102     if ((read_data[0] == 137) &&
2103         (read_data[1] == 80) &&
2104         (read_data[2] == 78) &&
2105         (read_data[3] == 71) &&
2106         (read_data[4] == 13) &&
2107         (read_data[5] == 10) &&
2108         (read_data[6] == 26) &&
2109         (read_data[7] == 10))
2110     {
2111         if (!_gx_system_memory_allocator)
2112         {
2113             return GX_SYSTEM_MEMORY_ERROR;
2114         }
2115 
2116         memset(&png, 0, sizeof(GX_PNG));
2117         scratch_buffer = (INT *)_gx_system_memory_allocator(GX_PNG_SCRATCH_BUFFER_SIZE * sizeof(ULONG));
2118 
2119         if (scratch_buffer == GX_NULL)
2120         {
2121             return GX_SYSTEM_MEMORY_ERROR;
2122         }
2123 
2124         png.gx_png_crc_table = (UINT *)scratch_buffer;
2125         scratch_index += GX_PNG_CRC_TABLE_SIZE;
2126         png.gx_png_huffman_lit_table = scratch_buffer + scratch_index;
2127         scratch_index += GX_PNG_HUFFMAN_LIT_TABLE_SIZE;
2128         png.gx_png_huffman_lit_code_len = scratch_buffer + scratch_index;
2129         scratch_index += GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE;
2130         png.gx_png_huffman_dist_code_len = scratch_buffer + scratch_index;
2131         scratch_index += GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE;
2132         png.gx_png_palette_table = (GX_COLOR *)scratch_buffer + scratch_index;
2133 
2134         png.gx_png_data = (GX_UBYTE *)read_data;
2135         png.gx_png_data_size = (INT)data_size;
2136         png.gx_png_data_index = 8;
2137 
2138         _gx_image_reader_png_crc_table_make(&png);
2139 
2140         _bit_buffer = 0;
2141         _bit_count = 0;
2142 
2143         while (png.gx_png_data_index < png.gx_png_data_size - 4)
2144         {
2145             /* data_len*/
2146             _gx_image_reader_png_4bytes_read(&png, &data_len);
2147 
2148             png.gx_png_trunk_crc = 0xffffffff;
2149 
2150             if ((data_len < 0) ||
2151                 (data_len > png.gx_png_data_size - png.gx_png_data_index - 4))
2152             {
2153                 status = GX_INVALID_SIZE;
2154                 break;
2155             }
2156 
2157             /* Calculate checksum of the chunk data.  */
2158             _gx_image_reader_png_crc_get(&png, &png.gx_png_trunk_crc, (UINT)(4 + data_len));
2159 
2160             /* Read chunk type.  */
2161             _gx_image_reader_png_chunk_type_read(&png, chunk_type);
2162 
2163             png.gx_png_trunk_end_index = png.gx_png_data_index + data_len;
2164 
2165             if ((strncmp(chunk_type, "IDAT", 4) == 0) && (!idat_done))
2166             {
2167                 idat_done = GX_TRUE;
2168 
2169                 status = _gx_image_reader_png_IDAT_chunk_read(&png);
2170             }
2171             else if (strncmp(chunk_type, "IHDR", 4) == 0)
2172             {
2173                 status = _gx_image_reader_png_IHDR_chunk_read(&png);
2174             }
2175             else if (strncmp(chunk_type, "gAMA", 4) == 0)
2176             {
2177                 status = _gx_image_reader_png_gAMA_chunk_read(&png);
2178             }
2179             else if (strncmp(chunk_type, "PLTE", 4) == 0)
2180             {
2181                 status = _gx_image_reader_png_PLTE_chunk_read(&png);
2182             }
2183             else if ((strncmp(chunk_type, "tRNS", 4) == 0) && (png.gx_png_trans == GX_NULL))
2184             {
2185                 /* Read transparent information. */
2186                 status = _gx_image_reader_png_tRNS_chunk_read(&png);
2187             }
2188             else if (strncmp(chunk_type, "IEND", 4) == GX_SUCCESS)
2189             {
2190                 /* End */
2191                 decoded_done = GX_TRUE;
2192                 break;
2193             }
2194             else
2195             {
2196                 /* Ignore chunk */
2197                 png.gx_png_data_index += data_len;
2198             }
2199 
2200             if (status != GX_SUCCESS)
2201             {
2202                 break;
2203             }
2204 
2205             _gx_image_reader_png_4bytes_read(&png, &checksum);
2206 
2207             if (checksum != (INT)png.gx_png_trunk_crc)
2208             {
2209                 status = GX_FAILURE;
2210                 break;
2211             }
2212         }
2213 
2214         if(status == GX_SUCCESS && (!decoded_done))
2215         {
2216             status = GX_FAILURE;
2217         }
2218 
2219         if (status == GX_SUCCESS)
2220         {
2221             /* revert filter */
2222             status = _gx_image_reader_png_unfilter(&png);
2223         }
2224 
2225         if (status == GX_SUCCESS)
2226         {
2227             outmap -> gx_pixelmap_data = png.gx_png_decoded_data;
2228             outmap -> gx_pixelmap_data_size = (ULONG)png.gx_png_decoded_data_len;
2229             outmap -> gx_pixelmap_width = (GX_VALUE)png.gx_png_width;
2230             outmap -> gx_pixelmap_height = (GX_VALUE)png.gx_png_height;
2231             outmap -> gx_pixelmap_flags = GX_PIXELMAP_RAW_FORMAT;
2232 
2233             if (png.gx_png_trans_num)
2234             {
2235                 outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2236                 outmap -> gx_pixelmap_transparent_color = (ULONG)png.gx_png_trans;
2237             }
2238 
2239             switch (png.gx_png_color_type)
2240             {
2241             case 6:
2242                 /* Each pixel is an RGB triple, followed by an alpha sample. */
2243                 if (png.gx_png_bit_depth == 8)
2244                 {
2245                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP;
2246                 }
2247                 else
2248                 {
2249                     /* Bit depth = 16. */
2250                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_64BPP;
2251                 }
2252                 outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2253                 break;
2254             case 4:
2255                 /* Each pixel is a grayscale sample followed by an alpha sample. */
2256                 if (png.gx_png_bit_depth == 8)
2257                 {
2258                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY_ALPHA;
2259                 }
2260                 else
2261                 {
2262                     /* Bit depth = 16. */
2263                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP_GRAY_ALPHA;
2264                 }
2265                 outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2266                 break;
2267             case 3:
2268                 /* Each pixel is a palette index */
2269                 switch (png.gx_png_bit_depth)
2270                 {
2271                 case 1:
2272                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP;
2273                     break;
2274                 case 2:
2275                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP;
2276                     break;
2277                 case 4:
2278                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP;
2279                     break;
2280                 default:
2281                     /* Bit depth = 8. */
2282                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP;
2283                     break;
2284                 }
2285 
2286                 /* Palette table size is no bigger than 256, aux data size will not overflow. */
2287                 outmap -> gx_pixelmap_aux_data_size = (ULONG)(png.gx_png_palette_table_size) * sizeof(GX_COLOR);
2288                 outmap -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(outmap -> gx_pixelmap_aux_data_size);
2289 
2290                 if (!outmap -> gx_pixelmap_aux_data)
2291                 {
2292                     return GX_SYSTEM_MEMORY_ERROR;
2293                 }
2294 
2295                 memcpy((GX_UBYTE *)outmap -> gx_pixelmap_aux_data, png.gx_png_palette_table, outmap -> gx_pixelmap_aux_data_size); /* Use case of memcpy is verified. */
2296                 break;
2297             case 2:
2298                 /* Each pixel is an RGB triple. */
2299                 if (png.gx_png_bit_depth == 8)
2300                 {
2301                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_24BPP;
2302                 }
2303                 else
2304                 {
2305                     /* Bit depth = 16. */
2306                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_48BPP;
2307                 }
2308                 break;
2309             default:
2310                 /* Each pixel is a grayscale sample. */
2311                 switch (png.gx_png_bit_depth)
2312                 {
2313                 case 16:
2314                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY;
2315                     break;
2316                 case 8:
2317                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP;
2318                     break;
2319                 case 4:
2320                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP;
2321                     break;
2322                 case 2:
2323                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP;
2324                     break;
2325                 default:
2326                     /* Bit depth = 1. */
2327                     outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP;
2328                     break;
2329                 }
2330                 break;
2331             }
2332         }
2333 
2334         if (status != GX_SUCCESS)
2335         {
2336             if (png.gx_png_decoded_data)
2337             {
2338                 _gx_system_memory_free(png.gx_png_decoded_data);
2339             }
2340 
2341             if (png.gx_png_trans)
2342             {
2343                 _gx_system_memory_free(png.gx_png_trans);
2344             }
2345         }
2346 
2347         /* Free scratch buffer. */
2348         _gx_system_memory_free(scratch_buffer);
2349     }
2350     else
2351     {
2352         return GX_FAILURE;
2353     }
2354 
2355     return status;
2356 }
2357 #endif
2358 
2359