Talos Vulnerability Report

TALOS-2022-1626

OpenImageIO PSD thumbnail resource code execution vulnerability

December 22, 2022
CVE Number

CVE-2022-41794

SUMMARY

A heap based buffer overflow vulnerability exists in the PSD thumbnail resource parsing code of OpenImageIO 2.3.19.0. A specially-crafted PSD file can lead to arbitrary code execution. An attacker can provide a malicious file to trigger this vulnerability.

CONFIRMED VULNERABLE VERSIONS

The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.

OpenImageIO Project OpenImageIO master-branch-9aeece7a
OpenImageIO Project OpenImageIO v2.3.19.0

PRODUCT URLS

OpenImageIO - https://github.com/OpenImageIO/oiio

CVSSv3 SCORE

9.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CWE

CWE-122 - Heap-based Buffer Overflow

DETAILS

OpenImageIO is an image processing library with easy-to-use interfaces and a sizable number of supported image formats. Useful for conversion and processing and even image comparison, this library is utilized by 3D-processing software from AliceVision (including Meshroom), as well as Blender for reading Photoshop .psd files.

When dealing with Photoshop .psd files, libOpenImageIO starts from the following function:

bool
PSDInput::open(const std::string& name, ImageSpec& newspec)
{
    m_filename = name;

    Filesystem::open(m_file, name, std::ios::binary);

    if (!m_file) {
        errorf("\"%s\": failed to open file", name);
        return false;
    }

    // File Header
    if (!load_header()) {      // [1]
        errorf("failed to open \"%s\": failed load_header", name);
        return false;
    }

    // Color Mode Data
    if (!load_color_data()) {  // [2]
        errorf("failed to open \"%s\": failed load_color_data", name);
        return false;
    }

    // Image Resources
    if (!load_resources()) {   // [3]
        errorf("failed to open \"%s\": failed load_resources", name);
        return false;
    }

The .psd file headers are read in at [1], populating the struct shown below:

[o.O]> ptype m_header
type = struct OpenImageIO_v2_3::psd_pvt::FileHeader {
    char signature[4];
    uint16_t version;
    uint16_t channel_count;
    uint32_t height;
    uint32_t width;
    uint16_t depth;
    uint16_t color_mode;
}

Even though the psd_pvt::FileHeader struct is only 0x14 bytes long, we end up skipping over six bytes between version and channel_count. Our file pointer ends up at offset 0x1a when we start reading the color data at [2] into a struct that looks like so:

type = struct OpenImageIO_v2_3::psd_pvt::ColorModeData {
    uint32_t length;
    std::string data;
}

The struct read is intuitive, with the 4 bytes for the length being read, then that many bytes being read for the ColorModeData.data. After this, we get to the more interesting resource data at [3] in load_resources():

bool
PSDInput::load_resources()
{
    uint32_t length;
    read_bige<uint32_t>(length);   // [4]

    if (!check_io())
        return false;

    ImageResourceBlock block;
    ImageResourceMap resources;                               // map of uint16_t to ImageResourceBlocks  
    std::streampos begin = m_file.tellg();   
    std::streampos end   = begin + (std::streampos)length;
    while (m_file && m_file.tellg() < end) {
        if (!read_resource(block) || !validate_resource(block)) //  [5] // validate ony checks for "8BIM" signature
            return false;

        resources.insert(std::make_pair(block.id, block));    // [6]
    }
    if (!check_io()) // if (!m_file)
        return false;

    if (!handle_resources(resources))  // [7]
        return false;

    m_file.seekg(end);
    return check_io();
}

Our read at [4] determines the total length of the resources in the file. The blocks are read in at [5] and subsequently added to the resources map at [6] before being processed in handle_resources [7]. For more context, the resource struct is given below:

type = struct OpenImageIO_v2_3::psd_pvt::ImageResourceBlock { 
    char signature[4];                               
    uint16_t id;                                     
    std::string name;                                // 1-256 bytes read in
    uint32_t length;                                 // [8]
    std::streampos pos;                              
}    

As one would expect, all of these struct members are simply read in order from the file, with the exception of std::string name, whose length is read in via read_pascal_string(). This boils down to a single byte read for the string length, then reading that many bytes, and finally padding out to an even length if needed. The length field at [8] designates the length of the resource data itself, and the offset of it in the file is saved to the std::streampos pos member before the file seeks forward length bytes to find the next ImageResourceBlock. Once all these objects have been read in, we go to the handle_resources function:

bool
PSDInput::handle_resources(ImageResourceMap& resources)
{
    // Loop through each of our resource loaders
    const ImageResourceMap::const_iterator end(resources.end());
    for (const ResourceLoader& loader : resource_loaders) {
        ImageResourceMap::const_iterator it(resources.find(loader.resource_id));
        // If a resource with that ID exists in the file, call the loader
        if (it != end) {
            m_file.seekg(it->second.pos);
            if (!check_io())
                return false;

            loader.load(this, it->second.length);
            if (!check_io())
                return false;
        }
    }
    return true;
}

The library contains a static list of PSDInput::ResourceLoader[] objects that determine which ImageResourceBlocks are actually parsed, which we see below:

const PSDInput::ResourceLoader PSDInput::resource_loaders[]
    = { ADD_LOADER(1005), ADD_LOADER(1006), ADD_LOADER(1010), ADD_LOADER(1033),
        ADD_LOADER(1036), ADD_LOADER(1039), ADD_LOADER(1047), ADD_LOADER(1058),
        ADD_LOADER(1059), ADD_LOADER(1060), ADD_LOADER(1064) };
#undef ADD_LOADER

As such, we only actually hit the handlers for ImageResourceBlocks, where the id field matches one of the above numbers. The handlers all have a definition looking like bool PSDInput::load_resource_XXXX(uint32_t length) whereby the X’s correspond to the ImageResourceBlock.id. For today’s vulnerability we only really care about PSDInput::load_resource_1033 or PSDInput::load_resource_1036:

bool
PSDInput::load_resource_1033(uint32_t length)
{
    return load_resource_thumbnail(length, true);
}

bool
PSDInput::load_resource_1036(uint32_t length)
{
    return load_resource_thumbnail(length, false);
}

Which both lead to the load_resource_thumbnail():

bool
PSDInput::load_resource_thumbnail(uint32_t length, bool isBGR)
{
    // [...]

    uint32_t jpeg_length = length - 28;

    read_bige<uint32_t>(format);          // [9]
    read_bige<uint32_t>(width);
    read_bige<uint32_t>(height);
    read_bige<uint32_t>(widthbytes);
    read_bige<uint32_t>(total_size);
    read_bige<uint32_t>(compressed_size);
    read_bige<uint16_t>(bpp);
    read_bige<uint16_t>(planes);
    if (!m_file)
        return false;

    //[...]

    std::string jpeg_data(jpeg_length, '\0');
    if (!m_file.read(&jpeg_data[0], jpeg_length)) // [10]
        return false;

    jpeg_create_decompress(&cinfo);
    jpeg_memory_src(&cinfo, (unsigned char*)&jpeg_data[0], jpeg_length);
    jpeg_read_header(&cinfo, TRUE);
    jpeg_start_decompress(&cinfo);

Thumbnails only seem to be able to be .jpg files, and so we now treat our loaded resource as if it were any other .jpg file. The file headers are read in order starting at [9], and then the rest of the jpeg data is read in at [10]. All the following jpeg_* calls get us setup for the actual decompression, and mostly either read parameters or change the decompressor’s state machine. It’s worth noting that the calls to jpeg_create_decompress and jpeg_start_decompress actually come from the libjpeg-turbo library, which is linked in. Continuing in load_resource_thumbnail():

    stride = cinfo.output_width * cinfo.output_components;                         // [11]
    ImageSpec thumbspec(cinfo.output_width, cinfo.output_height, 3, TypeUInt8);
    m_thumbnail.reset(thumbspec);
    // jpeg_destroy_decompress will deallocate this
    JSAMPLE** buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr)&cinfo,           // [12]
                                                  JPOOL_IMAGE, stride, 1);
    while (cinfo.output_scanline < cinfo.output_height) {                         // [13] 
        if (jpeg_read_scanlines(&cinfo, buffer, 1) != 1) {
            jpeg_finish_decompress(&cinfo);
            jpeg_destroy_decompress(&cinfo);
            errorf("[Image Resource] [JPEG Thumbnail] libjpeg error");
            return false;
        }
        m_thumbnail.get_pixels(ROI(0, width, cinfo.output_scanline,                 // [14]
                                   cinfo.output_scanline + 1, 0, 1, 0, 3),
                               TypeUInt8, buffer[0]);
    }
    // [...]
}

At [11], the stride of the thumbnail is determined by the cinfo.output_width and the cinfo.output_components, both of which are set inside the above menitoned call to jpeg_start_decompress in libjpeg-turbo (~jdapistd.c:49). At [12], a temporary array of the jpeg’s data is allocated via libjpeg-turbo’s memory manager (jmemmgr.c:138) with a call to alloc_sarray(j_common_ptr cinfo, int pool_id, JDIMENSION samplesperrow, JDIMENSION numrows). It’s important to note that the stride is our samplesperrow and we’re only allocating a single row. As such, this array’s size is strictly based on the stride variable (with some added bytes for object headers). Continuing on, we iterate over the output_height of our input jpeg [13], repeatedly reading lines and feeding them into the ImageSpec m_thumbnail object at [14] with a call to get_pixels. The code is as follows:

bool
ImageBuf::get_pixels(ROI roi, TypeDesc format, void* result, stride_t xstride,
                     stride_t ystride, stride_t zstride) const
{
    if (!roi.defined())
        roi = this->roi();
    roi.chend = std::min(roi.chend, nchannels());
    ImageSpec::auto_stride(xstride, ystride, zstride, format.size(),
                           roi.nchannels(), roi.width(), roi.height());
    if (localpixels() && this->roi().contains(roi)) {
             // [...]
    }

    // General case -- can handle IC-backed images.
    bool ok;
    OIIO_DISPATCH_COMMON_TYPES2_CONST(ok, "get_pixels", get_pixels_, format,
                                      spec().format, *this, *this, roi, roi,
                                      result, xstride, ystride, zstride,
                                      threads());
    return ok;
}

While the code looks a little opaque, we essentially just call out to the get_pixels_ function, which multithreads out a lambda function to write out the decompressed lines into our thumbnail:

template<typename D, typename S>
static bool
get_pixels_(const ImageBuf& buf, const ImageBuf& /*dummy*/, ROI whole_roi,
            ROI roi, void* r_, stride_t xstride, stride_t ystride,
            stride_t zstride, int nthreads = 0)
{
    ImageBufAlgo::parallel_image(
        roi, { "get_pixels", nthreads }, [=, &buf](ROI roi) {
            D* r       = (D*)r_;
            int nchans = roi.nchannels();
            for (ImageBuf::ConstIterator<S, D> p(buf, roi); !p.done(); ++p) {
                imagesize_t offset = (p.z() - whole_roi.zbegin) * zstride   // [15]
                                     + (p.y() - whole_roi.ybegin) * ystride
                                     + (p.x() - whole_roi.xbegin) * xstride;:
                D* rc = (D*)((char*)r + offset);
                for (int c = 0; c < nchans; ++c)
                    rc[c] = p[c + roi.chbegin];    // [16]
            }
        });
    return true;
}

The actual write occurs at [16], with the offset into our temporary buffer (allocated at [12]) being calculated at [15], and with the input iterator iterating over the jpeg_data array seen back at [10]. Now, if we’ll remember an important detail about our temporary output buffer, its length was essentially 1 * stride. If we re-examine the call to get_pixel at [14], we see the width variable being passed in as the xstride. If we take a look back at where width was populated, we can see an interesting fact:

bool
PSDInput::load_resource_thumbnail(uint32_t length, bool isBGR)
{
    // [...]

    uint32_t jpeg_length = length - 28;

    read_bige<uint32_t>(format);         
    read_bige<uint32_t>(width);    // [17]
    read_bige<uint32_t>(height);**

From [17], where we read the width directly from the file, all the way down to the call to get_pixels, there is neither any validation on the width variable nor any comparison between width and the size of the output JSAMPLE **buffer at [12]. As such, get_pixels is a classic attacker-controlled heap buffer overflow which can result in arbitrary code execution.

Crash Information

==71698==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6160000014b7 at pc 0x7fc62f28a279 bp 0x7fc61e9f0e70 sp 0x7fc61e9f0e68
WRITE of size 1 at 0x6160000014b7 thread T5
    #0 0x7fc62f28a278 in bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)::operator()(OpenImageIO_v2_3::ROI) const /oiio/oiio-2.3.19.0/src/libOpenImageIO/imagebuf.cpp:2220:27
    #1 0x7fc62f289126 in void std::__invoke_impl<void, bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)&, OpenImageIO_v2_3::ROI>(std::__invoke_other, bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)&, OpenImageIO_v2_3::ROI&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #2 0x7fc62f288c52 in std::enable_if<__and_<std::is_void<void>, std::__is_invocable<bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)&, OpenImageIO_v2_3::ROI> >::value, void>::type std::__invoke_r<void, bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)&, OpenImageIO_v2_3::ROI>(bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)&, OpenImageIO_v2_3::ROI&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:154:7
    #3 0x7fc62f2880ec in std::_Function_handler<void (OpenImageIO_v2_3::ROI), bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)>::_M_invoke(std::_Any_data const&, OpenImageIO_v2_3::ROI&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:290:9
    #4 0x7fc62a325319 in std::function<void (OpenImageIO_v2_3::ROI)>::operator()(OpenImageIO_v2_3::ROI) const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:590:9
    #5 0x7fc62a3296b4 in OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>)::'lambda'(int, long, long, long, long)::operator()(int, long, long, long, long) const /oiio/oiio-2.3.19.0/src/include/OpenImageIO/imagebufalgo_util.h:87:9
    #6 0x7fc62a328f37 in void std::__invoke_impl<void, OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>)::'lambda'(int, long, long, long, long)&, int, long, long, long, long>(std::__invoke_other, OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>)::'lambda'(int, long, long, long, long)&, int&&, long&&, long&&, long&&, long&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #7 0x7fc62a32839b in std::enable_if<__and_<std::is_void<void>, std::__is_invocable<OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>)::'lambda'(int, long, long, long, long)&, int, long, long, long, long> >::value, void>::type std::__invoke_r<void, OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>)::'lambda'(int, long, long, long, long)&, int, long, long, long, long>(OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>)::'lambda'(int, long, long, long, long)&, int&&, long&&, long&&, long&&, long&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:154:7
    #8 0x7fc62a327142 in std::_Function_handler<void (int, long, long, long, long), OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>)::'lambda'(int, long, long, long, long)>::_M_invoke(std::_Any_data const&, int&&, long&&, long&&, long&&, long&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:290:9
    #9 0x7fc62525992a in std::function<void (int, long, long, long, long)>::operator()(int, long, long, long, long) const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:590:9
    #10 0x7fc625309de7 in void std::__invoke_impl<void, std::function<void (int, long, long, long, long)>&, int, long&, long&, long&, long&>(std::__invoke_other, std::function<void (int, long, long, long, long)>&, int&&, long&, long&, long&, long&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #11 0x7fc625308dab in std::__invoke_result<std::function<void (int, long, long, long, long)>&, int, long&, long&, long&, long&>::type std::__invoke<std::function<void (int, long, long, long, long)>&, int, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, int&&, long&, long&, long&, long&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14
    #12 0x7fc6253085f6 in void std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>::__call<void, int&&, 0ul, 1ul, 2ul, 3ul, 4ul>(std::tuple<int&&>&&, std::_Index_tuple<0ul, 1ul, 2ul, 3ul, 4ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/functional:420:11
    #13 0x7fc625307852 in void std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>::operator()<int, void>(int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/functional:503:17
    #14 0x7fc6253074c2 in void std::__invoke_impl<void, std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>&, int>(std::__invoke_other, std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>&, int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #15 0x7fc625307262 in std::enable_if<__and_<std::is_void<void>, std::__is_invocable<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>&, int> >::value, void>::type std::__invoke_r<void, std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>&, int>(std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>&, int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:154:7
    #16 0x7fc625306ffb in std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'()::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:1468:13
    #17 0x7fc625306612 in std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'(), void>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:1409:6
    #18 0x7fc62530629a in std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter> std::__invoke_impl<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'(), void>&>(std::__invoke_other, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'(), void>&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #19 0x7fc625305ea7 in std::enable_if<__and_<std::__not_<std::is_void<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> > >, std::is_convertible<std::__invoke_result<std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'(), void>&>::type, std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> > >::value, std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> >::type std::__invoke_r<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'(), void>&>(std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'(), void>&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:142:14
    #20 0x7fc62530554a in std::_Function_handler<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> (), std::__future_base::_Task_setter<std::unique_ptr<std::__future_base::_Result<void>, std::__future_base::_Result_base::_Deleter>, std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&)::'lambda'(), void> >::_M_invoke(std::_Any_data const&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:290:9
    #21 0x7fc6252d7bf7 in std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:590:9
    #22 0x7fc6252d5a20 in std::__future_base::_State_baseV2::_M_do_set(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:571:27
    #23 0x7fc6252d78b9 in void std::__invoke_impl<void, void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::__invoke_memfun_deref, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:74:14
    #24 0x7fc6252d6eb5 in std::__invoke_result<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>::type std::__invoke<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14
    #25 0x7fc6252d69f3 in void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::'lambda'()::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:776:4
    #26 0x7fc6252d644e in std::once_flag::_Prepare_execution::_Prepare_execution<void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::'lambda'()>(void (std::__future_base::_State_baseV2::*&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*))::'lambda'()::operator()() const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:712:21
    #27 0x7fc6252d632c in std::once_flag::_Prepare_execution::_Prepare_execution<void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&)::'lambda'()>(void (std::__future_base::_State_baseV2::*&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*))::'lambda'()::__invoke() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:712:16
    #28 0x7fc625accf67 in __pthread_once_slow nptl/./nptl/pthread_once.c:116:7
    #29 0x7fc6252d60a7 in __gthread_once(int*, void (*)()) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/x86_64-linux-gnu/c++/11/bits/gthr-default.h:700:12
    #30 0x7fc6252d55ec in void std::call_once<void (std::__future_base::_State_baseV2::*)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*>(std::once_flag&, void (std::__future_base::_State_baseV2::*&&)(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*, bool*), std::__future_base::_State_baseV2*&&, std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>*&&, bool*&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/mutex:783:21
    #31 0x7fc6252d3eb1 in std::__future_base::_State_baseV2::_M_set_result(std::function<std::unique_ptr<std::__future_base::_Result_base, std::__future_base::_Result_base::_Deleter> ()>, bool) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:411:2
    #32 0x7fc625301c7c in std::__future_base::_Task_state<std::_Bind<std::function<void (int, long, long, long, long)> (std::_Placeholder<1>, long, long, long, long)>, std::allocator<int>, void (int)>::_M_run(int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:1471:8
    #33 0x7fc6252c1151 in std::packaged_task<void (int)>::operator()(int) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/future:1604:12
    #34 0x7fc625315338 in std::future<decltype(fp(0, fp0...))> OpenImageIO_v2_3::thread_pool::push<std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&)::'lambda'(int)::operator()(int) const /oiio/oiio-2.3.19.0/src/include/OpenImageIO/thread.h:700:17
    #35 0x7fc62531508c in std::function<void (int, long, long, long, long)>& std::__invoke_impl<void, std::future<decltype(fp(0, fp0...))> OpenImageIO_v2_3::thread_pool::push<std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&)::'lambda'(int)&, int>(std::__invoke_other, std::future<decltype(fp(0, fp0...))> OpenImageIO_v2_3::thread_pool::push<std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&)::'lambda'(int)&, int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #36 0x7fc625314c92 in std::enable_if<__and_<std::is_void<std::function<void (int, long, long, long, long)>&>, std::__is_invocable<std::future<decltype(fp(0, fp0...))> OpenImageIO_v2_3::thread_pool::push<std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&)::'lambda'(int)&, int> >::value, std::function<void (int, long, long, long, long)>&>::type std::__invoke_r<void, std::future<decltype(fp(0, fp0...))> OpenImageIO_v2_3::thread_pool::push<std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&)::'lambda'(int)&, int>(std::future<decltype(fp(0, fp0...))> OpenImageIO_v2_3::thread_pool::push<std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&)::'lambda'(int)&, int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:154:7
    #37 0x7fc625313eec in std::_Function_handler<void (int), std::future<decltype(fp(0, fp0...))> OpenImageIO_v2_3::thread_pool::push<std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&>(std::function<void (int, long, long, long, long)>&, long&, long&, long&, long&)::'lambda'(int)>::_M_invoke(std::_Any_data const&, int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:290:9
    #38 0x7fc62527ce13 in std::function<void (int)>::operator()(int) const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:590:9
    #39 0x7fc62527b5f8 in OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()::operator()() const /oiio/oiio-2.3.19.0/src/libutil/thread.cpp:309:21
    #40 0x7fc62527ae06 in void std::__invoke_impl<void, OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()>(std::__invoke_other, OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #41 0x7fc62527a9c6 in std::__invoke_result<OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()>::type std::__invoke<OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()>(OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14
    #42 0x7fc62527a867 in void std::thread::_Invoker<std::tuple<OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()> >::_M_invoke<0ul>(std::_Index_tuple<0ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:253:13
    #43 0x7fc62527a635 in std::thread::_Invoker<std::tuple<OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()> >::operator()() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:260:11
    #44 0x7fc625279c97 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<OpenImageIO_v2_3::thread_pool::Impl::set_thread(int)::'lambda'()> > >::_M_run() /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_thread.h:211:13
    #45 0x7fc634c862b2  (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc2b2) (BuildId: f57e02bfadacc0c923c82457d5e18e1830b5faea)
    #46 0x7fc625ac7b42 in start_thread nptl/./nptl/pthread_create.c:442:8
    #47 0x7fc625b599ff  misc/../sysdeps/unix/sysv/linux/x86_64/clone3.S:81

0x6160000014b7 is located 0 bytes to the right of 567-byte region [0x616000001280,0x6160000014b7)
allocated by thread T0 here:
    #0 0x55bf4a876b5e in malloc (/oiio/fuzzing/fuzz_oiio.bin+0xddb5e) (BuildId: e9d97e110da8ca7129ca0569fb37dfa703dccc25)
    #1 0x7fc62414fde4  (/lib/x86_64-linux-gnu/libjpeg.so.8+0x38de4) (BuildId: c54abff9294357e28532a76a049a4cb2542fc15b)
    #2 0x60f00000003f  (<unknown module>)
    #3 0x7fc624143d6f  (/lib/x86_64-linux-gnu/libjpeg.so.8+0x2cd6f) (BuildId: c54abff9294357e28532a76a049a4cb2542fc15b)

Thread T5 created by T0 here:
    #0 0x55bf4a85ffdc in __interceptor_pthread_create (/oiio/fuzzing/fuzz_oiio.bin+0xc6fdc) (BuildId: e9d97e110da8ca7129ca0569fb37dfa703dccc25)
    #1 0x7fc634c86388 in std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) (/lib/x86_64-linux-gnu/libstdc++.so.6+0xdc388) (BuildId: f57e02bfadacc0c923c82457d5e18e1830b5faea)
    #2 0x7fc6252677bd in OpenImageIO_v2_3::thread_pool::Impl::set_thread(int) /oiio/oiio-2.3.19.0/src/libutil/thread.cpp:331:17
    #3 0x7fc62524a59f in OpenImageIO_v2_3::thread_pool::Impl::resize(int) /oiio/oiio-2.3.19.0/src/libutil/thread.cpp:141:27
    #4 0x7fc625248fab in OpenImageIO_v2_3::thread_pool::Impl::Impl(int, int) /oiio/oiio-2.3.19.0/src/libutil/thread.cpp:108:15
    #5 0x7fc625248d24 in OpenImageIO_v2_3::thread_pool::thread_pool(int) /oiio/oiio-2.3.19.0/src/libutil/thread.cpp:358:18
    #6 0x7fc62524eccd in OpenImageIO_v2_3::default_thread_pool() /oiio/oiio-2.3.19.0/src/libutil/thread.cpp:467:57
    #7 0x7fc62a3247b9 in OpenImageIO_v2_3::parallel_options::resolve() /oiio/oiio-2.3.19.0/src/include/OpenImageIO/parallel.h:54:20
    #8 0x7fc62a322269 in OpenImageIO_v2_3::ImageBufAlgo::parallel_image(OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::parallel_options, std::function<void (OpenImageIO_v2_3::ROI)>) /oiio/oiio-2.3.19.0/src/include/OpenImageIO/imagebufalgo_util.h:55:9
    #9 0x7fc62cd022f3 in bool OpenImageIO_v2_3::fill_const_<unsigned char>(OpenImageIO_v2_3::ImageBuf&, float const*, OpenImageIO_v2_3::ROI, int) /oiio/oiio-2.3.19.0/src/libOpenImageIO/imagebufalgo_draw.cpp:41:5
    #10 0x7fc62cd17cf0 in OpenImageIO_v2_3::ImageBufAlgo::zero(OpenImageIO_v2_3::ImageBuf&, OpenImageIO_v2_3::ROI, int) /oiio/oiio-2.3.19.0/src/libOpenImageIO/imagebufalgo_draw.cpp:189:5
    #11 0x7fc62ede2d91 in OpenImageIO_v2_3::ImageBuf::reset(OpenImageIO_v2_3::ImageSpec const&, OpenImageIO_v2_3::InitializePixels) /oiio/oiio-2.3.19.0/src/libOpenImageIO/imagebuf.cpp:847:9
    #12 0x7fc63029cf28 in OpenImageIO_v2_3::PSDInput::load_resource_thumbnail(unsigned int, bool) /oiio/oiio-2.3.19.0/src/psd.imageio/psdinput.cpp:1321:17
    #13 0x7fc630245cd0 in OpenImageIO_v2_3::PSDInput::load_resource_1036(unsigned int) /oiio/oiio-2.3.19.0/src/psd.imageio/psdinput.cpp:1176:12
    #14 0x7fc6302cfa02 in bool std::__invoke_impl<bool, bool (OpenImageIO_v2_3::PSDInput::*&)(unsigned int), OpenImageIO_v2_3::PSDInput*, unsigned int>(std::__invoke_memfun_deref, bool (OpenImageIO_v2_3::PSDInput::*&)(unsigned int), OpenImageIO_v2_3::PSDInput*&&, unsigned int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:74:14
    #15 0x7fc6302cee35 in std::__invoke_result<bool (OpenImageIO_v2_3::PSDInput::*&)(unsigned int), OpenImageIO_v2_3::PSDInput*, unsigned int>::type std::__invoke<bool (OpenImageIO_v2_3::PSDInput::*&)(unsigned int), OpenImageIO_v2_3::PSDInput*, unsigned int>(bool (OpenImageIO_v2_3::PSDInput::*&)(unsigned int), OpenImageIO_v2_3::PSDInput*&&, unsigned int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:96:14
    #16 0x7fc6302ce731 in bool std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)>::__call<bool, OpenImageIO_v2_3::PSDInput*&&, unsigned int&&, 0ul, 1ul>(std::tuple<OpenImageIO_v2_3::PSDInput*&&, unsigned int&&>&&, std::_Index_tuple<0ul, 1ul>) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/functional:420:11
    #17 0x7fc6302ce171 in bool std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)>::operator()<OpenImageIO_v2_3::PSDInput*, unsigned int, bool>(OpenImageIO_v2_3::PSDInput*&&, unsigned int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/functional:503:17
    #18 0x7fc6302cdca5 in bool std::__invoke_impl<bool, std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)>&, OpenImageIO_v2_3::PSDInput*, unsigned int>(std::__invoke_other, std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)>&, OpenImageIO_v2_3::PSDInput*&&, unsigned int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:61:14
    #19 0x7fc6302cd615 in std::enable_if<__and_<std::__not_<std::is_void<bool> >, std::is_convertible<std::__invoke_result<std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)>&, OpenImageIO_v2_3::PSDInput*, unsigned int>::type, bool> >::value, bool>::type std::__invoke_r<bool, std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)>&, OpenImageIO_v2_3::PSDInput*, unsigned int>(std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)>&, OpenImageIO_v2_3::PSDInput*&&, unsigned int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/invoke.h:142:14
    #20 0x7fc6302cc25c in std::_Function_handler<bool (OpenImageIO_v2_3::PSDInput*, unsigned int), std::_Bind<bool (OpenImageIO_v2_3::PSDInput::* (std::_Placeholder<1>, std::_Placeholder<2>))(unsigned int)> >::_M_invoke(std::_Any_data const&, OpenImageIO_v2_3::PSDInput*&&, unsigned int&&) /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:290:9
    #21 0x7fc6302976d4 in std::function<bool (OpenImageIO_v2_3::PSDInput*, unsigned int)>::operator()(OpenImageIO_v2_3::PSDInput*, unsigned int) const /usr/bin/../lib/gcc/x86_64-linux-gnu/11/../../../../include/c++/11/bits/std_function.h:590:9
    #22 0x7fc630293ef6 in OpenImageIO_v2_3::PSDInput::handle_resources(std::map<unsigned short, OpenImageIO_v2_3::psd_pvt::ImageResourceBlock, std::less<unsigned short>, std::allocator<std::pair<unsigned short const, OpenImageIO_v2_3::psd_pvt::ImageResourceBlock> > >&) /oiio/oiio-2.3.19.0/src/psd.imageio/psdinput.cpp:1075:13
    #23 0x7fc630252e24 in OpenImageIO_v2_3::PSDInput::load_resources() /oiio/oiio-2.3.19.0/src/psd.imageio/psdinput.cpp:1020:10
    #24 0x7fc63024eace in OpenImageIO_v2_3::PSDInput::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, OpenImageIO_v2_3::ImageSpec&) /oiio/oiio-2.3.19.0/src/psd.imageio/psdinput.cpp:559:10
    #25 0x7fc63026848a in OpenImageIO_v2_3::PSDInput::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, OpenImageIO_v2_3::ImageSpec&, OpenImageIO_v2_3::ImageSpec const&) /oiio/oiio-2.3.19.0/src/psd.imageio/psdinput.cpp:615:12
    #26 0x7fc62f4496b9 in OpenImageIO_v2_3::ImageInput::create(OpenImageIO_v2_3::string_view, bool, OpenImageIO_v2_3::ImageSpec const*, OpenImageIO_v2_3::Filesystem::IOProxy*, OpenImageIO_v2_3::string_view) /oiio/oiio-2.3.19.0/src/libOpenImageIO/imageioplugin.cpp:758:27
    #27 0x7fc62f328579 in OpenImageIO_v2_3::ImageInput::open(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, OpenImageIO_v2_3::ImageSpec const*, OpenImageIO_v2_3::Filesystem::IOProxy*) /oiio/oiio-2.3.19.0/src/libOpenImageIO/imageinput.cpp:105:16
    #28 0x55bf4a8b440f in LLVMFuzzerTestOneInput /oiio/fuzzing/./oiio_harness.cpp:77:16
    #29 0x55bf4a7da4e3 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/oiio/fuzzing/fuzz_oiio.bin+0x414e3) (BuildId: e9d97e110da8ca7129ca0569fb37dfa703dccc25)
    #30 0x55bf4a7c425f in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) (/oiio/fuzzing/fuzz_oiio.bin+0x2b25f) (BuildId: e9d97e110da8ca7129ca0569fb37dfa703dccc25)
    #31 0x55bf4a7c9fb6 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/oiio/fuzzing/fuzz_oiio.bin+0x30fb6) (BuildId: e9d97e110da8ca7129ca0569fb37dfa703dccc25)
    #32 0x55bf4a7f3dd2 in main (/oiio/fuzzing/fuzz_oiio.bin+0x5add2) (BuildId: e9d97e110da8ca7129ca0569fb37dfa703dccc25)
    #33 0x7fc625a5cd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

SUMMARY: AddressSanitizer: heap-buffer-overflow /oiio/oiio-2.3.19.0/src/libOpenImageIO/imagebuf.cpp:2220:27 in bool OpenImageIO_v2_3::get_pixels_<unsigned char, unsigned char>(OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ImageBuf const&, OpenImageIO_v2_3::ROI, OpenImageIO_v2_3::ROI, void*, long, long, long, int)::'lambda'(OpenImageIO_v2_3::ROI)::operator()(OpenImageIO_v2_3::ROI) const
Shadow bytes around the buggy address:
  0x0c2c7fff8240: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c2c7fff8250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2c7fff8260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2c7fff8270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c2c7fff8280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c2c7fff8290: 00 00 00 00 00 00[07]fa fa fa fa fa fa fa fa fa
  0x0c2c7fff82a0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c2c7fff82b0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c2c7fff82c0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c2c7fff82d0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c2c7fff82e0: 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
==71698==ABORTING
TIMELINE

2022-10-20 - Vendor Disclosure
2022-11-01 - Vendor Patch Release
2022-12-22 - Public Release

Credit

Discovered by Lilith >_> of Cisco Talos.