Skip to content

[Bug] Protential heap-buffer-overflow crash in genpng.c #777

@ShangzhiXu

Description

@ShangzhiXu

Hi team here is another crash

PoC

./genpng 65536 65536 red 10 line 0 0 10 10 > /dev/null
=================================================================
==211233==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000010 at pc 0x55ce2c69dcfc bp 0x7ffd5dfe9ff0 sp 0x7ffd5dfe9fe8
WRITE of size 2 at 0x602000000010 thread T0
    #0 0x55ce2c69dcfb in pixel /home/z5500277/G2FUZZ/target/libpng/contrib/tools/genpng.c:745:33
    #1 0x55ce2c69dcfb in main /home/z5500277/G2FUZZ/target/libpng/contrib/tools/genpng.c:815:16
    #2 0x7fe7b29347e4 in __libc_start_main (/lib64/libc.so.6+0x3a7e4) (BuildId: 9846edf82646848f2857c47c5a2eb71c288059ec)
    #3 0x55ce2c5dc76d in _start (/home/z5500277/G2FUZZ/target/libpng/contrib/tools/genpng+0x2a76d)

0x602000000011 is located 0 bytes to the right of 1-byte region [0x602000000010,0x602000000011)
allocated by thread T0 here:
    #0 0x55ce2c66132e in __interceptor_malloc /dev/shm/apps/spack-stage/spack-stage-llvm-15.0.4-tf66zkctjzcicavphkm52rhma6rkbt6n/spack-src/compiler-rt/lib/asan/asan_malloc_linux.cpp:69:3
    #1 0x55ce2c69c436 in main /home/z5500277/G2FUZZ/target/libpng/contrib/tools/genpng.c:802:16
    #2 0x7fe7b29347e4 in __libc_start_main (/lib64/libc.so.6+0x3a7e4) (BuildId: 9846edf82646848f2857c47c5a2eb71c288059ec)

Root Cause

In line 802

buffer = malloc(PNG_IMAGE_SIZE(image));

If we dig a little bit deeper, PNG_IMAGE_SIZE is implemented with the follwoing logic

#define PNG_IMAGE_SIZE(image)\
   PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image))

#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
   (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))

#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
   PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt)

define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
   ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)

#define PNG_IMAGE_PIXEL_(test,fmt)\
   (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt))

#define PNG_FORMAT_FLAG_COLORMAP 0x08U

The problem is here, if the user input is large width = 65536, height = 65536, but image.height & image.width are 32 bit,
as we can see in png.h

 png_uint_32  width;     /* Image width in pixels (columns) */
 png_uint_32  height;    /* Image height in pixels (rows) */

During the calculation, an integer overflow occured due to something like width*height and it will cause buffer = malloc(PNG_IMAGE_SIZE(image)); to allocate very small space, leading to further buffer overflow

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions