strukturag / libheif

libheif is an HEIF and AVIF file format decoder and encoder.
Other
1.76k stars 302 forks source link

heap-use-after-free/SEGV/heap-buffer-overflow in UncompressedImageCodec::decode_uncompressed_image #1045

Closed fdu-sec closed 10 months ago

fdu-sec commented 11 months ago

Description

heap-use-after-free/SEGV/heap-buffer-overflow in UncompressedImageCodec::decode_uncompressed_image

Version

commit: 64ece913266609789f5dc70fe7de9eb759badd7f

heif-convert  libheif version: 1.17.5
-------------------------------------------
Usage: heif-convert [options]  <input-image> [output-image]

The program determines the output file format from the output filename suffix.
These suffixes are recognized: jpg, jpeg, png, y4m. If no output filename is specified, 'jpg' is used.

Options:
  -h, --help                     show help
  -v, --version                  show version
  -q, --quality                  quality (for JPEG output)
  -o, --output FILENAME          write output to FILENAME (optional)
  -d, --decoder ID               use a specific decoder (see --list-decoders)
      --with-aux                 also write auxiliary images (e.g. depth images)
      --with-xmp                 write XMP metadata to file (output filename with .xmp suffix)
      --with-exif                write EXIF metadata to file (output filename with .exif suffix)
      --skip-exif-offset         skip EXIF metadata offset bytes
      --no-colons                replace ':' characters in auxiliary image filenames with '_'
      --list-decoders            list all available decoders (built-in and plugins)
      --quiet                    do not output status messages to console
  -C, --chroma-upsampling ALGO   Force chroma upsampling algorithm (nn = nearest-neighbor / bilinear)
      --png-compression-level #  Set to integer between 0 (fastest) and 9 (best). Use -1 for default.

Replay

cd libheif
mkdir build && cd build
CC="gcc -fsanitize=address" CXX="g++ -fsanitize=address" cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_UNCOMPRESSED_CODEC=ON ..
make -j
./examples/heif-convert ./poc test.png

ASAN

I just show the bof case, you can use my poc to reproduce the others.

=================================================================
==88945==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x613000000528 at pc 0x7fd270526821 bp 0x7ffc3ade57f0 sp 0x7ffc3ade57e0
READ of size 1 at 0x613000000528 thread T0
    #0 0x7fd270526820 in UncompressedImageCodec::decode_uncompressed_image(std::shared_ptr<HeifFile const> const&, unsigned int, std::shared_ptr<HeifPixelImage>&, unsigned int, unsigned int, std::vector<unsigned char, std::allocator<unsigned char> > const&) libheif/libheif/uncompressed_image.cc:784
    #1 0x7fd2703e5304 in HeifContext::decode_image_planar(unsigned int, std::shared_ptr<HeifPixelImage>&, heif_colorspace, heif_decoding_options const&, bool) const libheif/libheif/context.cc:1452
    #2 0x7fd2703e22a8 in HeifContext::decode_image_user(unsigned int, std::shared_ptr<HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const&) const libheif/libheif/context.cc:1248
    #3 0x7fd2703a51f4 in heif_decode_image libheif/libheif/heif.cc:1044
    #4 0x5590cf2fca11 in main libheif/examples/heif_convert.cc:484
    #5 0x7fd26fe1d082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
    #6 0x5590cf2f7add in _start (libheif/build/examples/heif-convert+0xbadd)

0x613000000528 is located 30 bytes to the right of 330-byte region [0x6130000003c0,0x61300000050a)
allocated by thread T0 here:
    #0 0x7fd2706f4258 in operator new(unsigned long) (/lib/x86_64-linux-gnu/libasan.so.4+0xe1258)
    #1 0x5590cf2f97b4 in __gnu_cxx::new_allocator<unsigned char>::allocate(unsigned long, void const*) /usr/include/c++/7/ext/new_allocator.h:111
    #2 0x5590cf2f9286 in std::allocator_traits<std::allocator<unsigned char> >::allocate(std::allocator<unsigned char>&, unsigned long) /usr/include/c++/7/bits/alloc_traits.h:436
    #3 0x5590cf2f8fb5 in std::_Vector_base<unsigned char, std::allocator<unsigned char> >::_M_allocate(unsigned long) /usr/include/c++/7/bits/stl_vector.h:172
    #4 0x5590cf2f8864 in std::vector<unsigned char, std::allocator<unsigned char> >::_M_default_append(unsigned long) /usr/include/c++/7/bits/vector.tcc:571
    #5 0x5590cf2f84c6 in std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned long) /usr/include/c++/7/bits/stl_vector.h:692
    #6 0x7fd27032e7ff in Box_iloc::read_data(Box_iloc::Item const&, std::shared_ptr<StreamReader> const&, std::shared_ptr<Box_idat> const&, std::vector<unsigned char, std::allocator<unsigned char> >*) const libheif/libheif/box.cc:1252
    #7 0x7fd2704238bc in HeifFile::get_compressed_image_data(unsigned int, std::vector<unsigned char, std::allocator<unsigned char> >*) const libheif/libheif/file.cc:900
    #8 0x7fd2703e50f9 in HeifContext::decode_image_planar(unsigned int, std::shared_ptr<HeifPixelImage>&, heif_colorspace, heif_decoding_options const&, bool) const libheif/libheif/context.cc:1448
    #9 0x7fd2703e22a8 in HeifContext::decode_image_user(unsigned int, std::shared_ptr<HeifPixelImage>&, heif_colorspace, heif_chroma, heif_decoding_options const&) const libheif/libheif/context.cc:1248
    #10 0x7fd2703a51f4 in heif_decode_image libheif/libheif/heif.cc:1044
    #11 0x5590cf2fca11 in main libheif/examples/heif_convert.cc:484
    #12 0x7fd26fe1d082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082)

POC

Environment

Description:    Ubuntu 22.04.2 LTS
gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0

Credit

Yuchuan Meng (Fudan University)

farindk commented 11 months ago

I can only reproduce the poc-segv and that was fixed with fd5b02aca3e29088bf0a1fc400bd661be4a6ed76. Can this be closed?