GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: gx_image_reader_png_decode.c Lines: 612 612 100.0 %
Date: 2024-12-05 08:52:37 Branches: 338 339 99.7 %

Line Branch Exec Source
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
/**************************************************************************/
75
666
static VOID _gx_image_reader_png_crc_table_make(GX_PNG *png)
76
{
77
UINT crc;
78
UINT n;
79
UINT k;
80
81
171162
    for (n = 0; n < 256; n++)
82
    {
83
170496
        crc = n;
84
1534464
        for (k = 0; k < 8; k++)
85
        {
86
1363968
            if (crc & 1)
87
            {
88
681984
                crc = 0xedb88320 ^ (crc >> 1);
89
            }
90
            else
91
            {
92
681984
                crc = crc >> 1;
93
            }
94
        }
95
170496
        png -> gx_png_crc_table[n] = crc;
96
    }
97
666
}
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
/**************************************************************************/
142
4274
static VOID _gx_image_reader_png_crc_get(GX_PNG *png, UINT *crc, UINT len)
143
{
144
UINT      n;
145
4274
GX_UBYTE *buf = png -> gx_png_data + png -> gx_png_data_index;
146
4274
UINT      crc_cal = (*crc);
147
148
15393491
    for (n = 0; n < len; n++)
149
    {
150
15389217
        crc_cal = png -> gx_png_crc_table[(crc_cal ^ buf[n]) & 0xff] ^ (crc_cal >> 8);
151
    }
152
153
4274
    (*crc) = crc_cal ^ 0xffffffff;
154
4274
}
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
/**************************************************************************/
199
9786
static VOID _gx_image_reader_png_4bytes_read(GX_PNG *png, INT *value)
200
{
201
INT get_value;
202
203
9786
    get_value = (png -> gx_png_data[png -> gx_png_data_index] << 24);
204
9786
    png -> gx_png_data_index++;
205
206
9786
    get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 16);
207
9786
    png -> gx_png_data_index++;
208
209
9786
    get_value |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
210
9786
    png -> gx_png_data_index++;
211
212
9786
    get_value |= png -> gx_png_data[png -> gx_png_data_index];
213
9786
    png -> gx_png_data_index++;
214
215
9786
    (*value) = get_value;
216
9786
}
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
/**************************************************************************/
259
4274
static VOID _gx_image_reader_png_chunk_type_read(GX_PNG *png, CHAR *chunk_type)
260
{
261
4274
    chunk_type[0] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
262
4274
    chunk_type[1] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
263
4274
    chunk_type[2] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
264
4274
    chunk_type[3] = (CHAR)png -> gx_png_data[png -> gx_png_data_index++];
265
4274
}
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
/**************************************************************************/
316
19950045
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
19950045
INT      index = png -> gx_png_trunk_end_index;
322
323
35070328
    while (_bit_count < num_of_bits)
324
    {
325
15120296
        if (png -> gx_png_data_index >= png -> gx_png_data_size)
326
        {
327
1
            return GX_FAILURE;
328
        }
329
330
15120295
        get_byte = png -> gx_png_data[png -> gx_png_data_index++];
331
332
15120295
        _bit_buffer |= (UINT)(get_byte << (UINT)_bit_count);
333
15120295
        _bit_count += 8;
334
335
15120295
        if (png -> gx_png_data_index >= index)
336
        {
337
            /* data_len*/
338
700
            _gx_image_reader_png_4bytes_read(png, &checksum);
339
340
700
            if (png -> gx_png_trunk_crc != (UINT)checksum)
341
            {
342
12
                return GX_FAILURE;
343
            }
344
345
688
            _gx_image_reader_png_4bytes_read(png, &index);
346
347
688
            png -> gx_png_trunk_crc = 0xffffffff;
348
349
688
            _gx_image_reader_png_crc_get(png, &png -> gx_png_trunk_crc, (UINT)(4 + index));
350
351
688
            _gx_image_reader_png_chunk_type_read(png, chunk_type);
352
353
688
            if (strncmp(chunk_type, "IDAT", 4) == 0)
354
            {
355
687
                index += png -> gx_png_data_index;
356
687
                png -> gx_png_trunk_end_index = index;
357
            }
358
        }
359
    }
360
361
19950032
    (*return_value) = _bit_buffer;
362
363
19950032
    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
/**************************************************************************/
408
43287405
static void _gx_image_reader_png_bits_revert(UINT *bits, UINT bits_len)
409
{
410
43287405
UINT reverted = 0;
411
UINT i;
412
413
245522840
    for (i = 0; i < bits_len; i++)
414
    {
415
202235435
        reverted |= ((*bits) & 0x1) << (bits_len - i - 1);
416
202235435
        (*bits) >>= 1;
417
    }
418
419
43287405
    (*bits) = reverted;
420
43287405
}
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
/**************************************************************************/
464
19950650
static VOID _gx_image_reader_png_bits_skip(UINT num_of_skip_bits)
465
{
466
19950650
    _bit_buffer >>= num_of_skip_bits;
467
468
19950650
    _bit_count -= num_of_skip_bits;
469
19950650
}
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
/**************************************************************************/
515
661
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
661
    if (png -> gx_png_data_index + 13 > png -> gx_png_trunk_end_index)
527
    {
528
1
        return GX_INVALID_SIZE;
529
    }
530
531
660
    _gx_image_reader_png_4bytes_read(png, &png -> gx_png_width);
532
660
    _gx_image_reader_png_4bytes_read(png, &png -> gx_png_height);
533
534
    /* Limited max png width to 14 bits. */
535

660
    if ((png -> gx_png_width < 0) || (png -> gx_png_width > GX_MAX_PIXELMAP_RESOLUTION))
536
    {
537
2
        return GX_INVALID_WIDTH;
538
    }
539
540
    /* Limited max png height to 14 bits. */
541

658
    if ((png -> gx_png_height < 0) || (png -> gx_png_height > GX_MAX_PIXELMAP_RESOLUTION))
542
    {
543
1
        return GX_INVALID_HEIGHT;
544
    }
545
546
    /* Bits per sample or per palette index, valid values are 1, 2 ,4, 8, 16. */
547
657
    png -> gx_png_bit_depth = png -> gx_png_data[png -> gx_png_data_index++];
548
549
657
    switch (png -> gx_png_bit_depth)
550
    {
551
656
    case 1:
552
    case 2:
553
    case 4:
554
    case 8:
555
    case 16:
556
656
        break;
557
558
1
    default:
559
1
        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
656
    png -> gx_png_color_type = png -> gx_png_data[png -> gx_png_data_index++];
568
569

656
    switch (png -> gx_png_color_type)
570
    {
571
147
    case 0:
572
    /* Each pixel is agrayscale sample. */
573
    case 3:
574
        /* Each pixel is a palette index, a PLTE chunk must appear. */
575
147
        png -> gx_png_bpp = png -> gx_png_bit_depth;
576
147
        break;
577
178
    case 2:
578
        /* Each pixel is an RGB triple. */
579
178
        png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 3);
580
178
        break;
581
582
13
    case 4:
583
        /* Each pixel is a grayscale sample, followed by an alpha sample. */
584
13
        png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 2);
585
13
        break;
586
317
    case 6:
587
        /* Each pixel is an R,G,B triple, followed by an alpha sample. */
588
317
        png -> gx_png_bpp = (GX_UBYTE)(png -> gx_png_bit_depth * 4);
589
317
        break;
590
591
1
    default:
592
1
        return GX_FAILURE;
593
    }
594
595
    /* At present, only method 0 is defined. */
596
655
    png -> gx_png_compression_method = png -> gx_png_data[png -> gx_png_data_index++];
597
598
    /* At present, only method 0 is defined. */
599
655
    png -> gx_png_filter_method = png -> gx_png_data[png -> gx_png_data_index++];
600
601

655
    if ((png -> gx_png_compression_method != 0) || (png -> gx_png_filter_method != 0))
602
    {
603
        /* Invalid value. */
604
2
        return GX_FAILURE;
605
    }
606
607
    /* 0 no interlace
608
       1 Adam7 interlace */
609
653
    png -> gx_png_interlace_method = png -> gx_png_data[png -> gx_png_data_index++];
610
611
653
    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
/**************************************************************************/
660
14684099
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
14684099
UINT code_cal = 0;
670
14684099
UINT code_index = 0;
671
672
73050056
    for (i_bit = 1; i_bit < 16; i_bit++)
673
    {
674
73050035
        bit_count = huffman_bits_count[i_bit] - huffman_bits_count[i_bit - 1];
675
676
73050035
        if (bit_count)
677
        {
678
43269969
            code = (scan_buffer) << (32 - i_bit);
679
43269969
            code = (code) >> (32 - i_bit);
680
681
43269969
            _gx_image_reader_png_bits_revert(&code, i_bit);
682
683
43269969
            if (code <= code_cal + bit_count - 1)
684
            {
685
14684078
                *bit_len = i_bit;
686
14684078
                *code_value = (UINT)huffman_table[code_index + code - code_cal];
687
688
14684078
                return GX_SUCCESS;
689
            }
690
            else
691
            {
692
28585891
                code_index += bit_count;
693
28585891
                code_cal += bit_count;
694
            }
695
        }
696
697
58365957
        code_cal <<= 1;
698
    }
699
700
21
    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
/**************************************************************************/
747
8151
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
16781
    for (i_bit = 7; i_bit <= 9; i_bit++)
755
    {
756
15646
        code = scan_buffer << (32 - i_bit);
757
15646
        code = code >> (32 - i_bit);
758
759
15646
        _gx_image_reader_png_bits_revert(&code, i_bit);
760
761
15646
        if (i_bit == 7)
762
        {
763
8151
            if (code <= 0x17)
764
            {
765
1791
                *bit_len = 7;
766
1791
                *code_value = 256 + code;
767
1791
                break;
768
            }
769
        }
770
7495
        else if (i_bit == 8)
771
        {
772
6360
            if (code <= 0xbf)
773
            {
774
                /* code >= 0x30. */
775
5114
                *bit_len = 8;
776
5114
                *code_value = code - 0x30;
777
5114
                break;
778
            }
779
1246
            else if (code <= 0xc7)
780
            {
781
                /* code >= 0xc0. */
782
111
                *bit_len = 8;
783
111
                *code_value = 280 + code - 0xc0;
784
111
                break;
785
            }
786
        }
787
        else
788
        {
789
            /* code >= 0x190 && code <= 0x1ff. */
790
1135
            *bit_len = 9;
791
1135
            *code_value = 144 + code - 0x190;
792
        }
793
    }
794
795
8151
    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
/**************************************************************************/
840
1018
static UINT _gx_image_reader_png_clen_huffman_read(GX_PNG *png, UINT hclen)
841
{
842
843
1018
INT  code_value[19] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
844
1018
INT  code_len[19] = {0};
845
UINT len;
846
UINT i;
847
INT  pos[16];
848
849
17631
    for (i = 0; i < hclen; i++)
850
    {
851
16614
        if (_gx_image_reader_png_bits_get(png, 3, &len) != GX_SUCCESS)
852
        {
853
1
            return GX_FAILURE;
854
        }
855
16613
        _gx_image_reader_png_bits_skip(3);
856
16613
        len &= 0x7;
857
858
        /* record code len for code len alphabet */
859
16613
        code_len[code_value[i]] = (INT)len;
860
861
        /* record codes number for every code len */
862
16613
        if (len)
863
        {
864
13493
            png -> gx_png_huffman_clen_bits_count[len]++;
865
        }
866
    }
867
868
16272
    for (i = 1; i < 16; i++)
869
    {
870
15255
        png -> gx_png_huffman_clen_bits_count[i] += png -> gx_png_huffman_clen_bits_count[i - 1];
871
    }
872
873
1017
    memset(pos, -1, 16 * sizeof(INT));
874
875
20340
    for (i = 0; i < 19; i++)
876
    {
877
19323
        if (code_len[i])
878
        {
879
13492
            if (pos[code_len[i]] == -1)
880
            {
881
4941
                pos[code_len[i]] = png -> gx_png_huffman_clen_bits_count[code_len[i] - 1];
882
            }
883
13492
            png -> gx_png_huffman_clen_table[pos[code_len[i]]++] = (INT)i;
884
        }
885
    }
886
887
1017
    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
/**************************************************************************/
942
1017
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
1017
UINT count = 0;
950
INT  pos[16];
951
INT  index;
952
953
1017
    memset(png -> gx_png_huffman_lit_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE);
954
1017
    memset(png -> gx_png_huffman_dist_code_len, 0, sizeof(INT) * GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE);
955
956
238594
    for (i = 0; i < hlit + hdist;)
957
    {
958
237583
        count++;
959
237583
        if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS)
960
        {
961
1
            return GX_FAILURE;
962
        }
963
964
237582
        if (_gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_clen_table,
965
237582
                                                           (UINT *)png -> gx_png_huffman_clen_bits_count,
966
                                                           scan_buffer,
967
                                                           &bit_len,
968
                                                           &code_value) == 0)
969
        {
970
237578
            _gx_image_reader_png_bits_skip(bit_len);
971
972
237578
            if (code_value <= 15)
973
            {
974
                /* Represent code lengths of 0-15 */
975
221291
                if (i < hlit)
976
                {
977
202460
                    png -> gx_png_huffman_lit_code_len[i] = (INT)code_value;
978
979
202460
                    png -> gx_png_huffman_lit_bits_count[code_value]++;
980
                }
981
                else
982
                {
983
18831
                    png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value;
984
18831
                    png -> gx_png_huffman_dist_bits_count[code_value]++;
985
                }
986
987
221291
                i++;
988
            }
989
            else
990
            {
991
16287
                if (code_value == 16)
992
                {
993
                    /* repeat previous */
994
                    /* 2 bits repeat length*/
995
10127
                    _gx_image_reader_png_bits_get(png, 2, &repeat);
996
10127
                    _gx_image_reader_png_bits_skip(2);
997
10127
                    repeat &= 0x3;
998
10127
                    repeat += 3;
999
1000
10127
                    if (i < 1)
1001
                    {
1002
1
                        return GX_FALSE;
1003
                    }
1004
10126
                    else if ((i - 1) < hlit)
1005
                    {
1006
8191
                        code_value = (UINT)png -> gx_png_huffman_lit_code_len[i - 1];
1007
                    }
1008
                    else
1009
                    {
1010
1935
                        code_value = (UINT)png -> gx_png_huffman_dist_code_len[i - 1 - hlit];
1011
                    }
1012
1013
10126
                    if (i < hlit)
1014
                    {
1015
8191
                        png -> gx_png_huffman_lit_bits_count[code_value] += (INT)repeat;
1016
1017
41370
                        while (repeat--)
1018
                        {
1019
33179
                            png -> gx_png_huffman_lit_code_len[i++] = (INT)code_value;
1020
                        }
1021
                    }
1022
                    else
1023
                    {
1024
1935
                        png -> gx_png_huffman_dist_bits_count[code_value] += (INT)repeat;
1025
1026
9793
                        while (repeat--)
1027
                        {
1028
7858
                            png -> gx_png_huffman_dist_code_len[i - hlit] = (INT)code_value;
1029
7858
                            i++;
1030
                        }
1031
                    }
1032
                }
1033
                else
1034
                {
1035
6160
                    if (code_value == 17)
1036
                    {
1037
                        /* repeat 0 */
1038
                        /* 3 bits repeat length */
1039
5593
                        _gx_image_reader_png_bits_get(png, 3, &repeat);
1040
5593
                        _gx_image_reader_png_bits_skip(3);
1041
5593
                        repeat &= 0x7;
1042
5593
                        repeat += 3;
1043
                    }
1044
                    else
1045
                    {
1046
                        /* code_value = 18. */
1047
                        /* repeat 0*/
1048
                        /* 7 bits repeat length */
1049
567
                        _gx_image_reader_png_bits_get(png, 7, &repeat);
1050
567
                        _gx_image_reader_png_bits_skip(7);
1051
567
                        repeat &= 0x7f;
1052
567
                        repeat += 11;
1053
                    }
1054
1055
6160
                    if (i < hlit)
1056
                    {
1057
5972
                        memset(png -> gx_png_huffman_lit_code_len + i, 0, repeat * sizeof(INT));
1058
                    }
1059
                    else
1060
                    {
1061
188
                        memset(png -> gx_png_huffman_dist_code_len + i - hlit, 0, repeat * sizeof(INT));
1062
                    }
1063
1064
6160
                    i += repeat;
1065
                }
1066
            }
1067
        }
1068
        else
1069
        {
1070
            /*error*/
1071
4
            return GX_FAILURE;
1072
        }
1073
    }
1074
1075
1011
    png -> gx_png_huffman_lit_bits_count[0] = 0;
1076
1011
    png -> gx_png_huffman_dist_bits_count[0] = 0;
1077
1078
16176
    for (i = 2; i <= 16; i++)
1079
    {
1080
15165
        png -> gx_png_huffman_lit_bits_count[i] += png -> gx_png_huffman_lit_bits_count[i - 1];
1081
15165
        png -> gx_png_huffman_dist_bits_count[i] += png -> gx_png_huffman_dist_bits_count[i - 1];
1082
    }
1083
1084
1011
    memset(pos, -1, 16 * sizeof(INT));
1085
1086
286378
    for (i = 0; i < hlit; i++)
1087
    {
1088
285367
        index = png -> gx_png_huffman_lit_code_len[i];
1089
285367
        if (index)
1090
        {
1091
206147
            if (pos[index] == -1)
1092
            {
1093
10074
                pos[index] = png -> gx_png_huffman_lit_bits_count[index - 1];
1094
            }
1095
206147
            png -> gx_png_huffman_lit_table[pos[index]++] = (INT)i;
1096
        }
1097
    }
1098
1099
1011
    memset(pos, -1, 16 * sizeof(INT));
1100
1101
28582
    for (i = 0; i < hdist; i++)
1102
    {
1103
27572
        index = png -> gx_png_huffman_dist_code_len[i];
1104
27572
        if (index)
1105
        {
1106
25320
            if (pos[index] == -1)
1107
            {
1108
6642
                pos[index] = png -> gx_png_huffman_dist_bits_count[index - 1];
1109
            }
1110
1111
25320
            if (pos[index] >= GX_PNG_HUFFMAN_DIST_TABLE_SIZE)
1112
            {
1113
                /* Invalid data. */
1114
1
                return GX_FAILURE;
1115
            }
1116
1117
25319
            png -> gx_png_huffman_dist_table[pos[index]++] = (INT)i;
1118
        }
1119
    }
1120
1121
1010
    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
/**************************************************************************/
1176
1126
static UINT _gx_image_reader_png_huffcode_decode(GX_PNG *png, GX_BOOL dynamic, UINT decoded_data_size)
1177
{
1178
UINT scan_buffer;
1179
1126
UINT bit_len = 0;
1180
1126
UINT code_value = 300;
1181
UINT length;
1182
UINT distance;
1183
UINT extra_bits;
1184
UINT copy_len;
1185
1186
    while (1)
1187
    {
1188
9600917
        if (_gx_image_reader_png_bits_get(png, 16, &scan_buffer) != GX_SUCCESS)
1189
        {
1190
4
            return GX_FAILURE;
1191
        }
1192
1193
        /* Decode literal/length value from input stream */
1194
9600913
        if (dynamic)
1195
        {
1196
9592762
            _gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_lit_table,
1197
9592762
                                                           (UINT *)png -> gx_png_huffman_lit_bits_count,
1198
                                                           scan_buffer,
1199
                                                           &bit_len,
1200
                                                           &code_value);
1201
        }
1202
        else
1203
        {
1204
8151
            _gx_image_reader_png_fixed_ll_huffman_code_find(scan_buffer, &bit_len, &code_value);
1205
        }
1206
1207
9600913
        _gx_image_reader_png_bits_skip(bit_len);
1208
1209
9600913
        if (code_value < 256)
1210
        {
1211
4744250
            if ((UINT)(png -> gx_png_decoded_data_len + 1) > decoded_data_size)
1212
            {
1213
                /* Decoded data size exceed allocated buffer size. */
1214
1
                return GX_FAILURE;
1215
            }
1216
1217
4744249
            png -> gx_png_decoded_data[png -> gx_png_decoded_data_len++] = (GX_UBYTE)code_value;
1218
        }
1219
4856663
        else if (code_value == 256)
1220
        {
1221
            /* End of the block */
1222
1116
            break;
1223
        }
1224
        else
1225
        {
1226
4855547
            if (code_value < 265)
1227
            {
1228
                /* 0 extra bits */
1229
4349963
                length = 3 + code_value - 257;
1230
            }
1231
505584
            else if (code_value < 285)
1232
            {
1233
474693
                extra_bits = 1 + (code_value - 265) / 4;
1234
474693
                _gx_image_reader_png_bits_get(png, extra_bits, &length);
1235
474693
                _gx_image_reader_png_bits_skip(extra_bits);
1236
474693
                length <<= (32 - extra_bits);
1237
474693
                length >>= (32 - extra_bits);
1238
1239
474693
                length += 3u + (1u << (extra_bits + 2)) + ((1u << extra_bits) * ((code_value - 265) & 0x3));
1240
            }
1241
30891
            else if (code_value == 285)
1242
            {
1243
                /* 0 extra bits */
1244
30889
                length = 258;
1245
            }
1246
            else
1247
            {
1248
                /* This should not happen. */
1249
2
                return GX_FAILURE;
1250
            }
1251
1252
4855545
            if (dynamic)
1253
            {
1254
4853755
                _gx_image_reader_png_bits_get(png, 16, &scan_buffer);
1255
1256
                /*decode distance from input stream */
1257
4853755
                _gx_image_reader_png_dynamic_huffman_code_find(png -> gx_png_huffman_dist_table,
1258
4853755
                                                               (UINT *)png -> gx_png_huffman_dist_bits_count,
1259
                                                               scan_buffer,
1260
                                                               &bit_len,
1261
                                                               &code_value);
1262
1263
4853755
                _gx_image_reader_png_bits_skip(bit_len);
1264
            }
1265
            else
1266
            {
1267
                /* Decodes 5-bits distance codes. */
1268
1790
                _gx_image_reader_png_bits_get(png, 5, &scan_buffer);
1269
1790
                _gx_image_reader_png_bits_skip(5);
1270
1790
                code_value = scan_buffer & 0x1f;
1271
1790
                _gx_image_reader_png_bits_revert(&code_value, 5);
1272
            }
1273
1274
4855545
            if (code_value < 4)
1275
            {
1276
112633
                distance = 1 + code_value;
1277
            }
1278
4742912
            else if (code_value < 30)
1279
            {
1280
4742911
                extra_bits = 1 + (code_value - 4) / 2;
1281
1282
4742911
                _gx_image_reader_png_bits_get(png, extra_bits, &distance);
1283
4742911
                _gx_image_reader_png_bits_skip(extra_bits);
1284
1285
4742911
                distance <<= (32 - extra_bits);
1286
4742911
                distance >>= (32 - extra_bits);
1287
1288
4742911
                distance += 1u + (1u << (extra_bits + 1)) + (1u << extra_bits) * ((code_value - 4) & 0x1);
1289
            }
1290
            else
1291
            {
1292
                /* This should not happen. */
1293
1
                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
14626075
            while (length)
1300
            {
1301
9770533
                if (length > distance)
1302
                {
1303
4914989
                    copy_len = distance;
1304
4914989
                    length -= distance;
1305
                }
1306
                else
1307
                {
1308
4855544
                    copy_len = length;
1309
4855544
                    length = 0;
1310
                }
1311
1312
9770533
                if ((distance > (UINT)png -> gx_png_decoded_data_len) ||
1313
9770532
                    ((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
2
                    return GX_FAILURE;
1318
                }
1319
1320
9770531
                memcpy(png -> gx_png_decoded_data + png -> gx_png_decoded_data_len, /* Use case of memcpy is verified. */
1321
9770531
                       png -> gx_png_decoded_data + png -> gx_png_decoded_data_len - distance,
1322
                       copy_len * sizeof(GX_UBYTE));
1323
9770531
                png -> gx_png_decoded_data_len += (INT)copy_len;
1324
            }
1325
        }
1326
    }
1327
1328
1116
    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
/**************************************************************************/
1371
55
static UINT _gx_image_reader_png_tRNS_chunk_read(GX_PNG *png)
1372
{
1373
INT index;
1374
1375

55
    if ((png -> gx_png_color_type == 4) || (png -> gx_png_color_type == 6))
1376
    {
1377
        /* tRNS is prohibited for the other color types. */
1378
2
        return GX_FAILURE;
1379
    }
1380
1381
53
    if (png -> gx_png_color_type == 3)
1382
    {
1383
        /* Contains a series of one-byte alpha values.  */
1384
17
        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
17
        if (png -> gx_png_trans_num > 256)
1388
        {
1389
1
            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
36
        png -> gx_png_trans_num = (png -> gx_png_trunk_end_index - png -> gx_png_data_index) >> 1;
1397
1398
36
        if (png -> gx_png_trans_num > 3)
1399
        {
1400
1
            return GX_INVALID_VALUE;
1401
        }
1402
    }
1403
1404
    /* Then trans num is no bigger than 256, multiplication will not overflow. */
1405
51
    png -> gx_png_trans = (GX_COLOR *)_gx_system_memory_allocator((ULONG)png -> gx_png_trans_num * sizeof(GX_COLOR));
1406
1407
51
    if (png -> gx_png_trans == GX_NULL)
1408
    {
1409
1
        return GX_SYSTEM_MEMORY_ERROR;
1410
    }
1411
1412
140
    for (index = 0; index < png -> gx_png_trans_num; index++)
1413
    {
1414
90
        png -> gx_png_trans[index] = png -> gx_png_data[png -> gx_png_data_index++];
1415
1416
90
        if (png -> gx_png_color_type != 3)
1417
        {
1418
74
            png -> gx_png_trans[index] <<= 8;
1419
74
            png -> gx_png_trans[index] |= png -> gx_png_data[png -> gx_png_data_index++];
1420
        }
1421
    }
1422
1423
50
    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
/**************************************************************************/
1474
644
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
644
    if (_gx_image_reader_png_bits_get(png, 8, &CMF) != GX_SUCCESS)
1502
    {
1503
2
        return GX_FAILURE;
1504
    }
1505
1506
642
    _gx_image_reader_png_bits_skip(8);
1507
1508
642
    if (_gx_image_reader_png_bits_get(png, 8, &FLG) != GX_SUCCESS)
1509
    {
1510
1
        return GX_FAILURE;
1511
    }
1512
1513
641
    _gx_image_reader_png_bits_skip(8);
1514
1515
641
    compress_method = CMF & 0x0f;
1516
641
    window_size = 2 << (((CMF & 0xf0) >> 4) + 8);
1517
641
    fdict = FLG & 0x20;
1518
1519

641
    if ((fdict != 0) ||
1520
639
        (window_size > 65536) ||
1521
        (compress_method != 8))
1522
    {
1523
4
        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
637
    alloc_size = (UINT)(png -> gx_png_height * ((png -> gx_png_width * png -> gx_png_bpp + 7) / 8));
1529
637
    alloc_size = alloc_size + (UINT)png -> gx_png_height;
1530
637
    png -> gx_png_decoded_data = (GX_UBYTE *)_gx_system_memory_allocator(alloc_size);
1531
637
    png -> gx_png_decoded_data_len = 0;
1532
1533
637
    if (png -> gx_png_decoded_data == GX_NULL)
1534
    {
1535
2
        return GX_SYSTEM_MEMORY_ERROR;
1536
    }
1537
1538
    do
1539
    {
1540
        /* The header of one block */
1541
1150
        if (_gx_image_reader_png_bits_get(png, 8, &header) != GX_SUCCESS)
1542
        {
1543
1
            return GX_FAILURE;
1544
        }
1545
1546
1149
        if ((header & 0x6) == 0x00)
1547
        {
1548
13
            _gx_image_reader_png_bits_skip(3);
1549
1550
            /* no compression */
1551
13
            _gx_image_reader_png_bits_skip(_bit_count & 0x7);
1552
13
            if (_bit_count)
1553
            {
1554
1
                png -> gx_png_data_index -= (INT)(_bit_count / 8);
1555
1
                _gx_image_reader_png_bits_skip(_bit_count);
1556
            }
1557
1558
            /* 4 = 2 bytes len + 2 bytes nlen. */
1559
13
            if (png -> gx_png_data_index + 4 > png -> gx_png_data_size)
1560
            {
1561
1
                return GX_INVALID_SIZE;
1562
            }
1563
1564
            /* Read "LEN".  */
1565
12
            len = png -> gx_png_data[png -> gx_png_data_index];
1566
12
            png -> gx_png_data_index++;
1567
12
            len |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
1568
12
            png -> gx_png_data_index++;
1569
1570
            /* Read "NLEN".  */
1571
12
            nlen = png -> gx_png_data[png -> gx_png_data_index];
1572
12
            png -> gx_png_data_index++;
1573
12
            nlen |= (png -> gx_png_data[png -> gx_png_data_index] << 8);
1574
12
            png -> gx_png_data_index++;
1575
1576
12
            if (len + nlen != 65535)
1577
            {
1578
                /* NLEN is not one's complement of LEN. */
1579
4
                return GX_FAILURE;
1580
            }
1581
1582
            /* Read data to outbuffer directly */
1583
8
            if (len)
1584
            {
1585
7
                if ((UINT)(png -> gx_png_decoded_data_len + len) > alloc_size)
1586
                {
1587
                    /* Copied size exceed remaining buffer size. */
1588
1
                    return GX_FAILURE;
1589
                }
1590
1591
6
                if (png -> gx_png_data_index + len > png -> gx_png_data_size)
1592
                {
1593
1
                    return GX_INVALID_SIZE;
1594
                }
1595
1596
5
                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
5
                png -> gx_png_data_index += len;
1598
5
                png -> gx_png_decoded_data_len += len;
1599
            }
1600
        }
1601
1136
        else if ((header & 0x6) == 0x2)
1602
        {
1603
115
            _gx_image_reader_png_bits_skip(3);
1604
1605
            /* compressed with fixed Huffman codes */
1606
115
            if (_gx_image_reader_png_huffcode_decode(png, GX_FALSE, alloc_size) != GX_SUCCESS)
1607
            {
1608
3
                return GX_FAILURE;
1609
            }
1610
        }
1611
1021
        else if ((header & 0x6) == 0x4)
1612
        {
1613
            /* compressed with dynamic Huffman codes */
1614
1020
            _gx_image_reader_png_bits_skip(3);
1615
1616
            /* # of Literal/Length codes */
1617
1020
            _gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hlit);
1618
1619
1020
            _gx_image_reader_png_bits_skip(5);
1620
1020
            hlit = (hlit & 0x1f) + 257;
1621
1622
            /* # of Distance codes */
1623
1020
            if (_gx_image_reader_png_bits_get(png, 5, (unsigned int *)&hdist) != GX_SUCCESS)
1624
            {
1625
1
                return GX_FAILURE;
1626
            }
1627
1019
            _gx_image_reader_png_bits_skip(5);
1628
1019
            hdist = (hdist & 0x1f) + 1;
1629
1630
            /* # of Code Length codes */
1631
1019
            if (_gx_image_reader_png_bits_get(png, 4, (unsigned int *)&hclen) != GX_SUCCESS)
1632
            {
1633
1
                return GX_FAILURE;
1634
            }
1635
1018
            _gx_image_reader_png_bits_skip(4);
1636
1018
            hclen = (hclen & 0xf) + 4;
1637
1638
1018
            memset(png -> gx_png_huffman_clen_bits_count, 0, 17 * sizeof(INT));
1639
1018
            memset(png -> gx_png_huffman_clen_table, 0, 20 * sizeof(INT));
1640
1018
            memset(png -> gx_png_huffman_lit_bits_count, 0, 17 * sizeof(INT));
1641
1018
            memset(png -> gx_png_huffman_lit_table, 0, GX_PNG_HUFFMAN_LIT_TABLE_SIZE * sizeof(int));
1642
1018
            memset(png -> gx_png_huffman_dist_bits_count, 0, 17 * sizeof(INT));
1643
1018
            memset(png -> gx_png_huffman_dist_table, 0, 30 * sizeof(INT));
1644
1645
1018
            if (_gx_image_reader_png_clen_huffman_read(png, (UINT)hclen) != GX_SUCCESS)
1646
            {
1647
1
                return GX_FAILURE;
1648
            }
1649
1650
1017
            if (_gx_image_reader_png_ll_huffman_read(png, (UINT)hlit, (UINT)hdist) != GX_SUCCESS)
1651
            {
1652
6
                return GX_FAILURE;
1653
            }
1654
1655
1011
            if (_gx_image_reader_png_huffcode_decode(png, GX_TRUE, alloc_size) != GX_SUCCESS)
1656
            {
1657
6
                return GX_FAILURE;
1658
            }
1659
        }
1660
        else
1661
        {
1662
            /* error */
1663
1
            return GX_FAILURE;
1664
        }
1665
1123
    } while ((header & 0x1) != 0x1);
1666
1667
    /* Skip checksum */
1668
608
    png -> gx_png_data_index = png -> gx_png_trunk_end_index;
1669
608
    _gx_image_reader_png_bits_skip(_bit_count);
1670
1671
608
    if (alloc_size != (UINT)png -> gx_png_decoded_data_len)
1672
    {
1673
        /* Decoded data size doesn't match prediction. */
1674
4
        return GX_FAILURE;
1675
    }
1676
1677
604
    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
/**************************************************************************/
1721
565
static UINT _gx_image_reader_png_gAMA_chunk_read(GX_PNG *png)
1722
{
1723
565
    if (png -> gx_png_data_index + 4 > png -> gx_png_trunk_end_index)
1724
    {
1725
1
        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
564
    _gx_image_reader_png_4bytes_read(png, &png -> gx_png_gamma);
1732
1733
564
    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
/**************************************************************************/
1775
66
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
66
    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
66
    if (png -> gx_png_palette_table_size > 256)
1786
    {
1787
1
        return GX_INVALID_VALUE;
1788
    }
1789
1790
8862
    for (index = 0; index < png -> gx_png_palette_table_size; index++)
1791
    {
1792
8797
        red = png -> gx_png_data[png -> gx_png_data_index++];
1793
8797
        green = png -> gx_png_data[png -> gx_png_data_index++];
1794
8797
        blue = png -> gx_png_data[png -> gx_png_data_index++];
1795
1796
8797
        png -> gx_png_palette_table[index] = (GX_COLOR)((red << 16) | (green << 8) | blue);
1797
    }
1798
1799
65
    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
/**************************************************************************/
1846
17536220
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
17536220
    p = a + b - c;
1852
17536220
    pa = GX_ABS(p - a);
1853
17536220
    pb = GX_ABS(p - b);
1854
17536220
    pc = GX_ABS(p - c);
1855
1856
    /*return nearest of a, b, c */
1857
1858

17536220
    if ((pa <= pb) && (pa <= pc))
1859
    {
1860
12176556
        return a;
1861
    }
1862
5359664
    else if (pb <= pc)
1863
    {
1864
4272738
        return b;
1865
    }
1866
    else
1867
    {
1868
1086926
        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
/**************************************************************************/
1915
605
static UINT _gx_image_reader_png_unfilter(GX_PNG *png)
1916
{
1917
INT filter_type;
1918
INT byte_width;
1919
INT pos;
1920
605
INT bpp = png -> gx_png_bpp;
1921
INT x;
1922
INT y;
1923
1924
605
    if (png -> gx_png_decoded_data == GX_NULL)
1925
    {
1926
        /* This happens when IDAT chunk is missing. */
1927
1
        return GX_FAILURE;
1928
    }
1929
1930
604
    byte_width = (png -> gx_png_width * bpp + 7) >> 3;
1931
604
    bpp = (bpp + 7) >> 3;
1932
1933
76766
    for (y = 0; y < png -> gx_png_height; y++)
1934
    {
1935
76164
        filter_type = png -> gx_png_decoded_data[y * byte_width + y];
1936
1937
76164
        pos = y * byte_width;
1938
76164
        memmove(png -> gx_png_decoded_data + pos, png -> gx_png_decoded_data + pos + y + 1, (UINT)byte_width);
1939
1940

76164
        switch (filter_type)
1941
        {
1942
2595
        case 0:
1943
2595
            break;
1944
19998
        case 1:
1945
            /* sub(x) + raw(x-bpp)*/
1946
15937009
            for (x = bpp; x < byte_width; x++)
1947
            {
1948
15917011
                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
19998
            break;
1951
26536
        case 2:
1952
            /*up(x) + prior(x)*/
1953
26536
            if (y == 0)
1954
            {
1955
4
                break;
1956
            }
1957
1958
20764736
            for (x = 0; x < byte_width; x++)
1959
            {
1960
20738204
                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
26532
            break;
1963
1090
        case 3:
1964
            /* average(x) + floor((raw(x-bpp)+prior(x))/2 */
1965
1090
            if (y == 0)
1966
            {
1967
376
                for (x = bpp; x < byte_width; x++)
1968
                {
1969
372
                    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
4813
                for (x = 0; x < bpp; x++)
1975
                {
1976
3727
                    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
830655
                for (x = bpp; x < byte_width; x++)
1980
                {
1981
829569
                    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
829569
                                                                                                             png -> gx_png_decoded_data[pos + x - byte_width]) >> 1));
1983
                }
1984
            }
1985
1090
            break;
1986
25943
        case 4:
1987
            /* paeth(x) + paethpredictor(raw(x-bpp), prior(x), prior(x-bpp)) */
1988
25943
            if (y == 0)
1989
            {
1990
376
                for (x = bpp; x < byte_width; x++)
1991
                {
1992
372
                    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
128535
                for (x = 0; x < bpp; x++)
1998
                {
1999
102596
                    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
17562159
                for (x = bpp; x < byte_width; x++)
2003
                {
2004
17536220
                    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
17536220
                                                                                                                                                png -> gx_png_decoded_data[pos + x - byte_width],
2006
17536220
                                                                                                                                                png -> gx_png_decoded_data[pos + x - byte_width - bpp]));
2007
                }
2008
            }
2009
25943
            break;
2010
2
        default:
2011
2
            return GX_FAILURE;
2012
        }
2013
    }
2014
2015
602
    png -> gx_png_decoded_data_len -= png -> gx_png_height;
2016
2017
602
    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
/**************************************************************************/
2085
677
UINT _gx_image_reader_png_decode(GX_CONST GX_UBYTE *read_data, ULONG data_size, GX_PIXELMAP *outmap)
2086
{
2087
677
UINT    status = GX_SUCCESS;
2088
GX_PNG  png;
2089
INT     data_len;
2090
CHAR    chunk_type[4];
2091
INT     checksum;
2092
677
GX_BOOL idat_done = GX_FALSE;
2093
INT    *scratch_buffer;
2094
677
INT     scratch_index = 0;
2095
677
GX_BOOL decoded_done = GX_FALSE;
2096
2097
677
    if (data_size < 8)
2098
    {
2099
1
        return GX_INVALID_SIZE;
2100
    }
2101
2102
676
    if ((read_data[0] == 137) &&
2103
675
        (read_data[1] == 80) &&
2104
674
        (read_data[2] == 78) &&
2105
673
        (read_data[3] == 71) &&
2106
672
        (read_data[4] == 13) &&
2107
671
        (read_data[5] == 10) &&
2108
670
        (read_data[6] == 26) &&
2109
669
        (read_data[7] == 10))
2110
    {
2111
668
        if (!_gx_system_memory_allocator)
2112
        {
2113
1
            return GX_SYSTEM_MEMORY_ERROR;
2114
        }
2115
2116
667
        memset(&png, 0, sizeof(GX_PNG));
2117
667
        scratch_buffer = (INT *)_gx_system_memory_allocator(GX_PNG_SCRATCH_BUFFER_SIZE * sizeof(ULONG));
2118
2119
667
        if (scratch_buffer == GX_NULL)
2120
        {
2121
1
            return GX_SYSTEM_MEMORY_ERROR;
2122
        }
2123
2124
666
        png.gx_png_crc_table = (UINT *)scratch_buffer;
2125
666
        scratch_index += GX_PNG_CRC_TABLE_SIZE;
2126
666
        png.gx_png_huffman_lit_table = scratch_buffer + scratch_index;
2127
666
        scratch_index += GX_PNG_HUFFMAN_LIT_TABLE_SIZE;
2128
666
        png.gx_png_huffman_lit_code_len = scratch_buffer + scratch_index;
2129
666
        scratch_index += GX_PNG_HUFFMAN_LIT_CODE_LEN_TABLE_SIZE;
2130
666
        png.gx_png_huffman_dist_code_len = scratch_buffer + scratch_index;
2131
666
        scratch_index += GX_PNG_HUFFMAN_DIST_CODE_LEN_TABLE_SIZE;
2132
666
        png.gx_png_palette_table = (GX_COLOR *)scratch_buffer + scratch_index;
2133
2134
666
        png.gx_png_data = (GX_UBYTE *)read_data;
2135
666
        png.gx_png_data_size = (INT)data_size;
2136
666
        png.gx_png_data_index = 8;
2137
2138
666
        _gx_image_reader_png_crc_table_make(&png);
2139
2140
666
        _bit_buffer = 0;
2141
666
        _bit_count = 0;
2142
2143
3589
        while (png.gx_png_data_index < png.gx_png_data_size - 4)
2144
        {
2145
            /* data_len*/
2146
3588
            _gx_image_reader_png_4bytes_read(&png, &data_len);
2147
2148
3588
            png.gx_png_trunk_crc = 0xffffffff;
2149
2150
3588
            if ((data_len < 0) ||
2151
3587
                (data_len > png.gx_png_data_size - png.gx_png_data_index - 4))
2152
            {
2153
2
                status = GX_INVALID_SIZE;
2154
2
                break;
2155
            }
2156
2157
            /* Calculate checksum of the chunk data.  */
2158
3586
            _gx_image_reader_png_crc_get(&png, &png.gx_png_trunk_crc, (UINT)(4 + data_len));
2159
2160
            /* Read chunk type.  */
2161
3586
            _gx_image_reader_png_chunk_type_read(&png, chunk_type);
2162
2163
3586
            png.gx_png_trunk_end_index = png.gx_png_data_index + data_len;
2164
2165

3586
            if ((strncmp(chunk_type, "IDAT", 4) == 0) && (!idat_done))
2166
            {
2167
644
                idat_done = GX_TRUE;
2168
2169
644
                status = _gx_image_reader_png_IDAT_chunk_read(&png);
2170
            }
2171
2942
            else if (strncmp(chunk_type, "IHDR", 4) == 0)
2172
            {
2173
661
                status = _gx_image_reader_png_IHDR_chunk_read(&png);
2174
            }
2175
2281
            else if (strncmp(chunk_type, "gAMA", 4) == 0)
2176
            {
2177
565
                status = _gx_image_reader_png_gAMA_chunk_read(&png);
2178
            }
2179
1716
            else if (strncmp(chunk_type, "PLTE", 4) == 0)
2180
            {
2181
66
                status = _gx_image_reader_png_PLTE_chunk_read(&png);
2182
            }
2183

1650
            else if ((strncmp(chunk_type, "tRNS", 4) == 0) && (png.gx_png_trans == GX_NULL))
2184
            {
2185
                /* Read transparent information. */
2186
55
                status = _gx_image_reader_png_tRNS_chunk_read(&png);
2187
            }
2188
1595
            else if (strncmp(chunk_type, "IEND", 4) == GX_SUCCESS)
2189
            {
2190
                /* End */
2191
605
                decoded_done = GX_TRUE;
2192
605
                break;
2193
            }
2194
            else
2195
            {
2196
                /* Ignore chunk */
2197
990
                png.gx_png_data_index += data_len;
2198
            }
2199
2200
2981
            if (status != GX_SUCCESS)
2201
            {
2202
55
                break;
2203
            }
2204
2205
2926
            _gx_image_reader_png_4bytes_read(&png, &checksum);
2206
2207
2926
            if (checksum != (INT)png.gx_png_trunk_crc)
2208
            {
2209
3
                status = GX_FAILURE;
2210
3
                break;
2211
            }
2212
        }
2213
2214

666
        if(status == GX_SUCCESS && (!decoded_done))
2215
        {
2216
1
            status = GX_FAILURE;
2217
        }
2218
2219
666
        if (status == GX_SUCCESS)
2220
        {
2221
            /* revert filter */
2222
605
            status = _gx_image_reader_png_unfilter(&png);
2223
        }
2224
2225
666
        if (status == GX_SUCCESS)
2226
        {
2227
602
            outmap -> gx_pixelmap_data = png.gx_png_decoded_data;
2228
602
            outmap -> gx_pixelmap_data_size = (ULONG)png.gx_png_decoded_data_len;
2229
602
            outmap -> gx_pixelmap_width = (GX_VALUE)png.gx_png_width;
2230
602
            outmap -> gx_pixelmap_height = (GX_VALUE)png.gx_png_height;
2231
602
            outmap -> gx_pixelmap_flags = GX_PIXELMAP_RAW_FORMAT;
2232
2233
602
            if (png.gx_png_trans_num)
2234
            {
2235
49
                outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2236
49
                outmap -> gx_pixelmap_transparent_color = (ULONG)png.gx_png_trans;
2237
            }
2238
2239

602
            switch (png.gx_png_color_type)
2240
            {
2241
312
            case 6:
2242
                /* Each pixel is an RGB triple, followed by an alpha sample. */
2243
312
                if (png.gx_png_bit_depth == 8)
2244
                {
2245
308
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP;
2246
                }
2247
                else
2248
                {
2249
                    /* Bit depth = 16. */
2250
4
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_64BPP;
2251
                }
2252
312
                outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2253
312
                break;
2254
12
            case 4:
2255
                /* Each pixel is a grayscale sample followed by an alpha sample. */
2256
12
                if (png.gx_png_bit_depth == 8)
2257
                {
2258
8
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY_ALPHA;
2259
                }
2260
                else
2261
                {
2262
                    /* Bit depth = 16. */
2263
4
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_32BPP_GRAY_ALPHA;
2264
                }
2265
12
                outmap -> gx_pixelmap_flags |= GX_PIXELMAP_ALPHA;
2266
12
                break;
2267
53
            case 3:
2268
                /* Each pixel is a palette index */
2269

53
                switch (png.gx_png_bit_depth)
2270
                {
2271
6
                case 1:
2272
6
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP;
2273
6
                    break;
2274
6
                case 2:
2275
6
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP;
2276
6
                    break;
2277
10
                case 4:
2278
10
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP;
2279
10
                    break;
2280
31
                default:
2281
                    /* Bit depth = 8. */
2282
31
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP;
2283
31
                    break;
2284
                }
2285
2286
                /* Palette table size is no bigger than 256, aux data size will not overflow. */
2287
53
                outmap -> gx_pixelmap_aux_data_size = (ULONG)(png.gx_png_palette_table_size) * sizeof(GX_COLOR);
2288
53
                outmap -> gx_pixelmap_aux_data = (GX_UBYTE *)_gx_system_memory_allocator(outmap -> gx_pixelmap_aux_data_size);
2289
2290
53
                if (!outmap -> gx_pixelmap_aux_data)
2291
                {
2292
1
                    return GX_SYSTEM_MEMORY_ERROR;
2293
                }
2294
2295
52
                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
52
                break;
2297
172
            case 2:
2298
                /* Each pixel is an RGB triple. */
2299
172
                if (png.gx_png_bit_depth == 8)
2300
                {
2301
138
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_24BPP;
2302
                }
2303
                else
2304
                {
2305
                    /* Bit depth = 16. */
2306
34
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_48BPP;
2307
                }
2308
172
                break;
2309
53
            default:
2310
                /* Each pixel is a grayscale sample. */
2311

53
                switch (png.gx_png_bit_depth)
2312
                {
2313
16
                case 16:
2314
16
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_16BPP_GRAY;
2315
16
                    break;
2316
16
                case 8:
2317
16
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_8BPP;
2318
16
                    break;
2319
8
                case 4:
2320
8
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_4BPP;
2321
8
                    break;
2322
6
                case 2:
2323
6
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_2BPP;
2324
6
                    break;
2325
7
                default:
2326
                    /* Bit depth = 1. */
2327
7
                    outmap -> gx_pixelmap_format = GX_IMAGE_FORMAT_1BPP;
2328
7
                    break;
2329
                }
2330
53
                break;
2331
            }
2332
        }
2333
2334
665
        if (status != GX_SUCCESS)
2335
        {
2336
64
            if (png.gx_png_decoded_data)
2337
            {
2338
33
                _gx_system_memory_free(png.gx_png_decoded_data);
2339
            }
2340
2341
64
            if (png.gx_png_trans)
2342
            {
2343
1
                _gx_system_memory_free(png.gx_png_trans);
2344
            }
2345
        }
2346
2347
        /* Free scratch buffer. */
2348
665
        _gx_system_memory_free(scratch_buffer);
2349
    }
2350
    else
2351
    {
2352
8
        return GX_FAILURE;
2353
    }
2354
2355
665
    return status;
2356
}
2357
#endif
2358