libheif icon indicating copy to clipboard operation
libheif copied to clipboard

Invalid read of size 2 in Op_YCbCr420_to_RRGGBBaa::convert_colorspace

Open novomesk opened this issue 1 month ago • 1 comments

Hello,

I saw a fuzzer report regarding 2 byte read in Op_YCbCr420_to_RRGGBBaa::convert_colorspace

460204593.zip

	READ of size 2 at 0x52800000ff0e thread T0
	    #0 0x5ae3c9b5714e in Op_YCbCr420_to_RRGGBBaa::convert_colorspace(std::__1::shared_ptr<HeifPixelImage const> const&, ColorState const&, ColorState const&, heif_color_conversion_options const&, heif_color_conversion_options_ext const&, heif_security_limits const*) const libheif/libheif/color-conversion/yuv2rgb.cc:674:63
	    #1 0x5ae3c9b19b83 in ColorConversionPipeline::convert_image(std::__1::shared_ptr<HeifPixelImage> const&, heif_security_limits const*) libheif/libheif/color-conversion/colorconversion.cc:447:38
	    #2 0x5ae3c9b1c4a9 in convert_colorspace(std::__1::shared_ptr<HeifPixelImage> const&, heif_colorspace, heif_chroma, nclx_profile const&, int, heif_color_conversion_options const&, heif_color_conversion_options_ext const*, heif_security_limits const*) libheif/libheif/color-conversion/colorconversion.cc:623:21
	    #3 0x5ae3c9c8def1 in HeifContext::convert_to_output_colorspace(std::__1::shared_ptr<HeifPixelImage>, heif_colorspace, heif_chroma, heif_decoding_options const&) const libheif/libheif/context.cc:1388:12
	    #4 0x5ae3c9c8ca21 in HeifContext::decode_image(unsigned int, heif_colorspace, heif_chroma, heif_decoding_options const&, bool, unsigned int, unsigned int) const libheif/libheif/context.cc:1300:21
	    #5 0x5ae3c9a7f6ca in heif_decode_image libheif/libheif/api/libheif/heif_decoding.cc:236:81
	    #6 0x5ae3c9906a29 in HEIFHandler::ensureDecoder() /src/kimageformats/src/imageformats/heif.cpp:599:11
	    #7 0x5ae3c98fef73 in HEIFHandler::ensureParsed() const /src/kimageformats/src/imageformats/heif.cpp:503:26
	    #8 0x5ae3c98fef73 in HEIFHandler::read(QImage*) /src/kimageformats/src/imageformats/heif.cpp:111:10
	    #9 0x5ae3c98fd691 in LLVMFuzzerTestOneInput /src/kimgio_fuzzer.cc:69:14
	    #10 0x5ae3cd4bd5e9 in ExecuteFilesOnyByOne /src/aflplusplus/utils/aflpp_driver/aflpp_driver.c:255:7
	    #11 0x5ae3cd4bd3e5 in LLVMFuzzerRunDriver /src/aflplusplus/utils/aflpp_driver/aflpp_driver.c:0
	    #12 0x5ae3cd4bcf9d in main /src/aflplusplus/utils/aflpp_driver/aflpp_driver.c:311:10
	    #13 0x7ba68bf5e082 in __libc_start_main /build/glibc-LcI20x/glibc-2.31/csu/libc-start.c:308:16
	    #14 0x5ae3c9824d5d in _start

valgrind --leak-check=yes --track-origins=yes heif-dec clusterfuzz-testcase-minimized-kimgio_heif_fuzzer-5427590325403648 outut.png shows following:

==23030== Memcheck, a memory error detector
==23030== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
==23030== Using Valgrind-3.27.0.GIT and LibVEX; rerun with -h for copyright info
==23030== Command: heif-dec clusterfuzz-testcase-minimized-kimgio_heif_fuzzer-5427590325403648 outut.png
==23030== 
==23030== Invalid read of size 1
==23030==    at 0x4961CF8: Op_YCbCr420_to_RRGGBBaa::convert_colorspace(std::shared_ptr<HeifPixelImage const> const&, ColorState const&, ColorState const&, heif_color_conversion_options const&, heif_color_conversion_options_ext const&, heif_security_limits const*) const (yuv2rgb.cc:674)
==23030==    by 0x4950BCD: ColorConversionPipeline::convert_image(std::shared_ptr<HeifPixelImage> const&, heif_security_limits const*) (colorconversion.cc:447)
==23030==    by 0x49521FF: convert_colorspace(std::shared_ptr<HeifPixelImage> const&, heif_colorspace, heif_chroma, nclx_profile const&, int, heif_color_conversion_options const&, heif_color_conversion_options_ext const*, heif_security_limits const*) (colorconversion.cc:623)
==23030==    by 0x48E4777: HeifContext::convert_to_output_colorspace(std::shared_ptr<HeifPixelImage>, heif_colorspace, heif_chroma, heif_decoding_options const&) const (context.cc:1390)
==23030==    by 0x48E64B5: HeifContext::decode_image(unsigned int, heif_colorspace, heif_chroma, heif_decoding_options const&, bool, unsigned int, unsigned int) const (context.cc:1300)
==23030==    by 0x491F10F: heif_decode_image (heif_decoding.cc:240)
==23030==    by 0x4005C3E: decode_single_image(heif_image_handle*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, heif_decoding_options*, std::unique_ptr<Encoder, std::default_delete<Encoder> >&) (heif_dec.cc:241)
==23030==    by 0x400831B: main (heif_dec.cc:1026)
==23030==  Address 0x6989a5f is 0 bytes after a block of size 15,887 alloc'd
==23030==    at 0x485B308: operator new[](unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:851)
==23030==    by 0x48FC2F8: HeifPixelImage::ImagePlane::alloc(unsigned int, unsigned int, heif_channel_datatype, int, int, heif_security_limits const*, MemoryHandle&) (pixelimage.cc:438)
==23030==    by 0x48FDD72: HeifPixelImage::add_plane(heif_channel, unsigned int, unsigned int, int, heif_security_limits const*) (pixelimage.cc:355)
==23030==    by 0x4966CBA: Op_mono_to_YCbCr420::convert_colorspace(std::shared_ptr<HeifPixelImage const> const&, ColorState const&, ColorState const&, heif_color_conversion_options const&, heif_color_conversion_options_ext const&, heif_security_limits const*) const (monochrome.cc:83)
==23030==    by 0x4950BCD: ColorConversionPipeline::convert_image(std::shared_ptr<HeifPixelImage> const&, heif_security_limits const*) (colorconversion.cc:447)
==23030==    by 0x49521FF: convert_colorspace(std::shared_ptr<HeifPixelImage> const&, heif_colorspace, heif_chroma, nclx_profile const&, int, heif_color_conversion_options const&, heif_color_conversion_options_ext const*, heif_security_limits const*) (colorconversion.cc:623)
==23030==    by 0x48E4777: HeifContext::convert_to_output_colorspace(std::shared_ptr<HeifPixelImage>, heif_colorspace, heif_chroma, heif_decoding_options const&) const (context.cc:1390)
==23030==    by 0x48E64B5: HeifContext::decode_image(unsigned int, heif_colorspace, heif_chroma, heif_decoding_options const&, bool, unsigned int, unsigned int) const (context.cc:1300)
==23030==    by 0x491F10F: heif_decode_image (heif_decoding.cc:240)
==23030==    by 0x4005C3E: decode_single_image(heif_image_handle*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, heif_decoding_options*, std::unique_ptr<Encoder, std::default_delete<Encoder> >&) (heif_dec.cc:241)
==23030==    by 0x400831B: main (heif_dec.cc:1026)
==23030== 
==23030== Invalid read of size 2
==23030==    at 0x4961D2D: Op_YCbCr420_to_RRGGBBaa::convert_colorspace(std::shared_ptr<HeifPixelImage const> const&, ColorState const&, ColorState const&, heif_color_conversion_options const&, heif_color_conversion_options_ext const&, heif_security_limits const*) const (yuv2rgb.cc:675)
==23030==    by 0x4950BCD: ColorConversionPipeline::convert_image(std::shared_ptr<HeifPixelImage> const&, heif_security_limits const*) (colorconversion.cc:447)
==23030==    by 0x49521FF: convert_colorspace(std::shared_ptr<HeifPixelImage> const&, heif_colorspace, heif_chroma, nclx_profile const&, int, heif_color_conversion_options const&, heif_color_conversion_options_ext const*, heif_security_limits const*) (colorconversion.cc:623)
==23030==    by 0x48E4777: HeifContext::convert_to_output_colorspace(std::shared_ptr<HeifPixelImage>, heif_colorspace, heif_chroma, heif_decoding_options const&) const (context.cc:1390)
==23030==    by 0x48E64B5: HeifContext::decode_image(unsigned int, heif_colorspace, heif_chroma, heif_decoding_options const&, bool, unsigned int, unsigned int) const (context.cc:1300)
==23030==    by 0x491F10F: heif_decode_image (heif_decoding.cc:240)
==23030==    by 0x4005C3E: decode_single_image(heif_image_handle*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, heif_decoding_options*, std::unique_ptr<Encoder, std::default_delete<Encoder> >&) (heif_dec.cc:241)
==23030==    by 0x400831B: main (heif_dec.cc:1026)
==23030==  Address 0x6989a5e is 15,886 bytes inside a block of size 15,887 alloc'd
==23030==    at 0x485B308: operator new[](unsigned long, std::nothrow_t const&) (vg_replace_malloc.c:851)
==23030==    by 0x48FC2F8: HeifPixelImage::ImagePlane::alloc(unsigned int, unsigned int, heif_channel_datatype, int, int, heif_security_limits const*, MemoryHandle&) (pixelimage.cc:438)
==23030==    by 0x48FDD72: HeifPixelImage::add_plane(heif_channel, unsigned int, unsigned int, int, heif_security_limits const*) (pixelimage.cc:355)
==23030==    by 0x4966CBA: Op_mono_to_YCbCr420::convert_colorspace(std::shared_ptr<HeifPixelImage const> const&, ColorState const&, ColorState const&, heif_color_conversion_options const&, heif_color_conversion_options_ext const&, heif_security_limits const*) const (monochrome.cc:83)
==23030==    by 0x4950BCD: ColorConversionPipeline::convert_image(std::shared_ptr<HeifPixelImage> const&, heif_security_limits const*) (colorconversion.cc:447)
==23030==    by 0x49521FF: convert_colorspace(std::shared_ptr<HeifPixelImage> const&, heif_colorspace, heif_chroma, nclx_profile const&, int, heif_color_conversion_options const&, heif_color_conversion_options_ext const*, heif_security_limits const*) (colorconversion.cc:623)
==23030==    by 0x48E4777: HeifContext::convert_to_output_colorspace(std::shared_ptr<HeifPixelImage>, heif_colorspace, heif_chroma, heif_decoding_options const&) const (context.cc:1390)
==23030==    by 0x48E64B5: HeifContext::decode_image(unsigned int, heif_colorspace, heif_chroma, heif_decoding_options const&, bool, unsigned int, unsigned int) const (context.cc:1300)
==23030==    by 0x491F10F: heif_decode_image (heif_decoding.cc:240)
==23030==    by 0x4005C3E: decode_single_image(heif_image_handle*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, heif_decoding_options*, std::unique_ptr<Encoder, std::default_delete<Encoder> >&) (heif_dec.cc:241)
==23030==    by 0x400831B: main (heif_dec.cc:1026)

Please take a look when you have time.

novomesk avatar Nov 14 '25 19:11 novomesk

Thank you. The image is 16 bit, but has an alpha plane with only 8 bits. The color-conversion expects both to be similar. I've added an error check for this case. Eventually, the color-conversion should convert the alpha bpp to match the main image. This is left for the future (if this case will ever happen in actual use).

farindk avatar Nov 29 '25 21:11 farindk