We discovered a heap overflow bug in src/include/OpenImageIO/fmath.h:983 while fuzzing oiiotool.
The latest version also has this vulnerability.
=================================================================
==660139==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6020000546f8 at pc 0x7f85c4197284 bp 0x7ffe23c547b0 sp 0x7ffe23c547a0
READ of size 4 at 0x6020000546f8 thread T0
#0 0x7f85c4197283 in float OpenImageIO_v3_1_0::convert_type<float, float>(float const&) /openimageio/src/include/OpenImageIO/fmath.h:983
#1 0x7f85c4197283 in OpenImageIO_v3_1_0::ConstDataArrayProxy<float, float>::operator[](int) const /openimageio/src/include/OpenImageIO/fmath.h:1218
#2 0x7f85c4197283 in OpenImageIO_v3_1_0::ImageBuf::ConstIterator<float, float>::operator[](int) const /openimageio/src/include/OpenImageIO/imagebuf.h:1883
#3 0x7f85c4197283 in operator() /openimageio/src/libOpenImageIO/imagebufalgo_compare.cpp:169
#4 0x7f85c37043f0 in std::function<void (long, long)>::operator()(long, long) const /usr/include/c++/11/bits/std_function.h:590
#5 0x7f85c37043f0 in operator() /openimageio/src/libutil/thread.cpp:647
#6 0x7f85c37043f0 in __invoke_impl<void, OpenImageIO_v3_1_0::parallel_for_chunked(int64_t, int64_t, int64_t, std::function<void(long int, long int)>&&, OpenImageIO_v3_1_0::paropt)::<lambda(int, int64_t, int64_t)>&, int, long int, long int> /usr/include/c++/11/bits/invoke.h:61
#7 0x7f85c37043f0 in __invoke_r<void, OpenImageIO_v3_1_0::parallel_for_chunked(int64_t, int64_t, int64_t, std::function<void(long int, long int)>&&, OpenImageIO_v3_1_0::paropt)::<lambda(int, int64_t, int64_t)>&, int, long int, long int> /usr/include/c++/11/bits/invoke.h:111
#8 0x7f85c37043f0 in _M_invoke /usr/include/c++/11/bits/std_function.h:290
#9 0x7f85c37117e5 in std::function<void (int, long, long)>::operator()(int, long, long) const /usr/include/c++/11/bits/std_function.h:590
#10 0x7f85c37117e5 in OpenImageIO_v3_1_0::parallel_for_chunked_id(long, long, long, std::function<void (int, long, long)>&&, OpenImageIO_v3_1_0::paropt) /openimageio/src/libutil/thread.cpp:632
#11 0x7f85c3713b49 in OpenImageIO_v3_1_0::parallel_for_chunked(long, long, long, std::function<void (long, long)>&&, OpenImageIO_v3_1_0::paropt) /openimageio/src/libutil/thread.cpp:648
#12 0x7f85c41f1957 in computePixelStats_<float> /openimageio/src/libOpenImageIO/imagebufalgo_compare.cpp:161
#13 0x7f85c41f1957 in OpenImageIO_v3_1_0::ImageBufAlgo::computePixelStats(OpenImageIO_v3_1_0::ImageBuf const&, OpenImageIO_v3_1_0::ROI, int) /openimageio/src/libOpenImageIO/imagebufalgo_compare.cpp:203
#14 0x7f85c4b7ca1a in OpenImageIO_v3_1_0::pvt::print_stats(std::ostream&, OpenImageIO_v3_1_0::basic_string_view<char, std::char_traits<char> >, OpenImageIO_v3_1_0::ImageBuf const&, OpenImageIO_v3_1_0::ImageSpec const&, OpenImageIO_v3_1_0::ROI, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) /openimageio/src/libOpenImageIO/printinfo.cpp:324
#15 0x5644114bd151 in print_info_subimage /openimageio/src/oiiotool/printinfo.cpp:470
#16 0x5644114c72a7 in OpenImageIO_v3_1_0::OiioTool::print_info(std::ostream&, OpenImageIO_v3_1_0::OiioTool::Oiiotool&, OpenImageIO_v3_1_0::OiioTool::ImageRec*, OpenImageIO_v3_1_0::pvt::print_info_options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) /openimageio/src/oiiotool/printinfo.cpp:529
#17 0x5644112ad943 in action_printstats /openimageio/src/oiiotool/oiiotool.cpp:5820
#18 0x564411388f93 in std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>::operator()(OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>) const /usr/include/c++/11/bits/std_function.h:590
#19 0x564411388f93 in OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}::operator()(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>) const /openimageio/src/include/OpenImageIO/argparse.h:536
#20 0x564411388f93 in void std::__invoke_impl<void, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul> >(std::__invoke_other, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>&&) /usr/include/c++/11/bits/invoke.h:61
#21 0x564411388f93 in std::enable_if<is_invocable_r_v<void, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul> >, void>::type std::__invoke_r<void, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul> >(OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>&&) /usr/include/c++/11/bits/invoke.h:111
#22 0x564411388f93 in std::_Function_handler<void (OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>), OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}>::_M_invoke(std::_Any_data const&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>&&) /usr/include/c++/11/bits/std_function.h:290
#23 0x7f85c34e0abc in std::function<void (OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>::operator()(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>) const /usr/include/c++/11/bits/std_function.h:590
#24 0x7f85c34e0abc in OpenImageIO_v3_1_0::ArgParse::Impl::parse_args(int, char const**) /openimageio/src/libutil/argparse.cpp:514
#25 0x7f85c34e42db in OpenImageIO_v3_1_0::ArgParse::parse_args(int, char const**) /openimageio/src/libutil/argparse.cpp:429
#26 0x56441137a01b in OpenImageIO_v3_1_0::OiioTool::Oiiotool::getargs(int, char**) /openimageio/src/oiiotool/oiiotool.cpp:6979
#27 0x5644110ff5a1 in main /openimageio/src/oiiotool/oiiotool.cpp:7338
#28 0x7f85c2f43d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
#29 0x7f85c2f43e3f in __libc_start_main_impl ../csu/libc-start.c:392
#30 0x564411104b34 in _start (/openimageio/build1/bin/oiiotool+0x89b34)
0x6020000546f9 is located 0 bytes to the right of 9-byte region [0x6020000546f0,0x6020000546f9)
allocated by thread T0 here:
#0 0x7f85c75c4357 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:102
#1 0x7f85c4808f77 in OpenImageIO_v3_1_0::ImageBufImpl::new_pixels(unsigned long, void const*) /openimageio/src/libOpenImageIO/imagebuf.cpp:682
#2 0x7f85c480b273 in OpenImageIO_v3_1_0::ImageBufImpl::realloc() /openimageio/src/libOpenImageIO/imagebuf.cpp:998
#3 0x7f85c481b613 in OpenImageIO_v3_1_0::ImageBufImpl::read(int, int, int, int, bool, OpenImageIO_v3_1_0::TypeDesc, bool (*)(void*, float), void*, OpenImageIO_v3_1_0::DoLock) /openimageio/src/libOpenImageIO/imagebuf.cpp:1333
#4 0x7f85c493bd31 in OpenImageIO_v3_1_0::ImageBufImpl::validate_pixels(OpenImageIO_v3_1_0::DoLock) const /openimageio/src/libOpenImageIO/imagebuf.cpp:263
#5 0x7f85c4824645 in OpenImageIO_v3_1_0::ImageBufImpl::pixeladdr(int, int, int, int) /openimageio/src/libOpenImageIO/imagebuf.cpp:3004
#6 0x7f85c4824645 in OpenImageIO_v3_1_0::ImageBuf::pixeladdr(int, int, int, int) const /openimageio/src/libOpenImageIO/imagebuf.cpp:3020
#7 0x7f85c484c78d in OpenImageIO_v3_1_0::ImageBuf::IteratorBase::pos(int, int, int) /openimageio/src/libOpenImageIO/imagebuf.cpp:3405
#8 0x7f85c484fe72 in OpenImageIO_v3_1_0::ImageBuf::IteratorBase::IteratorBase(OpenImageIO_v3_1_0::ImageBuf const&, OpenImageIO_v3_1_0::ROI const&, OpenImageIO_v3_1_0::ImageBuf::WrapMode, bool) /openimageio/src/libOpenImageIO/imagebuf.cpp:3254
#9 0x7f85c41961fb in OpenImageIO_v3_1_0::ImageBuf::ConstIterator<float, float>::ConstIterator(OpenImageIO_v3_1_0::ImageBuf const&, OpenImageIO_v3_1_0::ROI const&, OpenImageIO_v3_1_0::ImageBuf::WrapMode) /openimageio/src/include/OpenImageIO/imagebuf.h:1857
#10 0x7f85c41961fb in operator() /openimageio/src/libOpenImageIO/imagebufalgo_compare.cpp:166
#11 0x7f85c37043f0 in std::function<void (long, long)>::operator()(long, long) const /usr/include/c++/11/bits/std_function.h:590
#12 0x7f85c37043f0 in operator() /openimageio/src/libutil/thread.cpp:647
#13 0x7f85c37043f0 in __invoke_impl<void, OpenImageIO_v3_1_0::parallel_for_chunked(int64_t, int64_t, int64_t, std::function<void(long int, long int)>&&, OpenImageIO_v3_1_0::paropt)::<lambda(int, int64_t, int64_t)>&, int, long int, long int> /usr/include/c++/11/bits/invoke.h:61
#14 0x7f85c37043f0 in __invoke_r<void, OpenImageIO_v3_1_0::parallel_for_chunked(int64_t, int64_t, int64_t, std::function<void(long int, long int)>&&, OpenImageIO_v3_1_0::paropt)::<lambda(int, int64_t, int64_t)>&, int, long int, long int> /usr/include/c++/11/bits/invoke.h:111
#15 0x7f85c37043f0 in _M_invoke /usr/include/c++/11/bits/std_function.h:290
#16 0x7f85c37117e5 in std::function<void (int, long, long)>::operator()(int, long, long) const /usr/include/c++/11/bits/std_function.h:590
#17 0x7f85c37117e5 in OpenImageIO_v3_1_0::parallel_for_chunked_id(long, long, long, std::function<void (int, long, long)>&&, OpenImageIO_v3_1_0::paropt) /openimageio/src/libutil/thread.cpp:632
#18 0x7f85c3713b49 in OpenImageIO_v3_1_0::parallel_for_chunked(long, long, long, std::function<void (long, long)>&&, OpenImageIO_v3_1_0::paropt) /openimageio/src/libutil/thread.cpp:648
#19 0x7f85c41f1957 in computePixelStats_<float> /openimageio/src/libOpenImageIO/imagebufalgo_compare.cpp:161
#20 0x7f85c41f1957 in OpenImageIO_v3_1_0::ImageBufAlgo::computePixelStats(OpenImageIO_v3_1_0::ImageBuf const&, OpenImageIO_v3_1_0::ROI, int) /openimageio/src/libOpenImageIO/imagebufalgo_compare.cpp:203
#21 0x7f85c4b7ca1a in OpenImageIO_v3_1_0::pvt::print_stats(std::ostream&, OpenImageIO_v3_1_0::basic_string_view<char, std::char_traits<char> >, OpenImageIO_v3_1_0::ImageBuf const&, OpenImageIO_v3_1_0::ImageSpec const&, OpenImageIO_v3_1_0::ROI, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) /openimageio/src/libOpenImageIO/printinfo.cpp:324
#22 0x5644114bd151 in print_info_subimage /openimageio/src/oiiotool/printinfo.cpp:470
#23 0x5644114c72a7 in OpenImageIO_v3_1_0::OiioTool::print_info(std::ostream&, OpenImageIO_v3_1_0::OiioTool::Oiiotool&, OpenImageIO_v3_1_0::OiioTool::ImageRec*, OpenImageIO_v3_1_0::pvt::print_info_options const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&) /openimageio/src/oiiotool/printinfo.cpp:529
#24 0x5644112ad943 in action_printstats /openimageio/src/oiiotool/oiiotool.cpp:5820
#25 0x564411388f93 in std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>::operator()(OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>) const /usr/include/c++/11/bits/std_function.h:590
#26 0x564411388f93 in OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}::operator()(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>) const /openimageio/src/include/OpenImageIO/argparse.h:536
#27 0x564411388f93 in void std::__invoke_impl<void, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul> >(std::__invoke_other, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>&&) /usr/include/c++/11/bits/invoke.h:61
#28 0x564411388f93 in std::enable_if<is_invocable_r_v<void, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul> >, void>::type std::__invoke_r<void, OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul> >(OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>&&) /usr/include/c++/11/bits/invoke.h:111
#29 0x564411388f93 in std::_Function_handler<void (OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>), OpenImageIO_v3_1_0::ArgParse::Arg::action(std::function<void (OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>&&)::{lambda(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)#1}>::_M_invoke(std::_Any_data const&, OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>&&) /usr/include/c++/11/bits/std_function.h:290
#30 0x7f85c34e0abc in std::function<void (OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>)>::operator()(OpenImageIO_v3_1_0::ArgParse::Arg&, OpenImageIO_v3_1_0::span<char const* const, 18446744073709551615ul>) const /usr/include/c++/11/bits/std_function.h:590
#31 0x7f85c34e0abc in OpenImageIO_v3_1_0::ArgParse::Impl::parse_args(int, char const**) /openimageio/src/libutil/argparse.cpp:514
#32 0x7f85c34e42db in OpenImageIO_v3_1_0::ArgParse::parse_args(int, char const**) /openimageio/src/libutil/argparse.cpp:429
#33 0x56441137a01b in OpenImageIO_v3_1_0::OiioTool::Oiiotool::getargs(int, char**) /openimageio/src/oiiotool/oiiotool.cpp:6979
#34 0x5644110ff5a1 in main /openimageio/src/oiiotool/oiiotool.cpp:7338
#35 0x7f85c2f43d8f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
SUMMARY: AddressSanitizer: heap-buffer-overflow /openimageio/src/include/OpenImageIO/fmath.h:983 in float OpenImageIO_v3_1_0::convert_type<float, float>(float const&)
Shadow bytes around the buggy address:
0x0c0480002880: fa fa 00 fa fa fa 00 fa fa fa 00 fa fa fa 00 fa
0x0c0480002890: fa fa fd fd fa fa fd fa fa fa fd fd fa fa fd fd
0x0c04800028a0: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fa
0x0c04800028b0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
0x0c04800028c0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa fd fa
=>0x0c04800028d0: fa fa fd fa fa fa fd fa fa fa fd fa fa fa 00[01]
0x0c04800028e0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c04800028f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0480002900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0480002910: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0480002920: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==660139==ABORTING
Description
Dear developers,
We discovered a heap overflow bug in src/include/OpenImageIO/fmath.h:983 while fuzzing oiiotool.
The latest version also has this vulnerability.
Version
PoC
poc2oiio: https://github.com/Frank-Z7/z-vulnerabilitys/blob/main/poc2oiio
Reproduction
Address Sanitizer log
Environment
Thanks for your time!