CVE-2025-64181: OpenEXR Makes Use of Uninitialized Memory

Published Nov 10, 2025
·
Updated

Summary While fuzzing openexrexrcheckfuzzer, Valgrind reports a conditional branch depending on uninitialized data inside genericunpack. This indicates a use of uninitialized memory (CWE-457). The issue is reproducible with the current OSS-Fuzz harness and a single-file PoC.

Details

Environment: - Tooling: valgrind --tool=memcheck --track-origins=yes - Target: openexrexrcheckfuzzer - OS: Ubuntu 20.04.6 LTS focal x8664 - openexr version and Git-commit hash: openexr 3.4.2 | commit fd657e8a41e157e5841c7cc2e2a5efe094b069a1 (grafted, HEAD -> main, origin/main, origin/HEAD)

Function: genericunpack

Possible root cause (based on observed symptoms): The unpacker is branching on bytes in a scratch buffer that were never written because the decode step didn’t fully populate it. - The first use flagged is in genericunpack(). That function reads from the decompressed/expanded pixel buffer to scatter data into the framebuffer. A “conditional jump depends on uninitialised value(s)” means it’s consulting bytes in that buffer before they were written. - Valgrind says the uninitialised value “was created by a heap allocation (malloc)”, not the stack: this matches a per-tile/per-scanline decode scratch buffer allocated in exrdecodingrun().

Valgrind Trace (top frames): bash ==454== Conditional jump or move depends on uninitialised value(s) ==454== at 0x4539BE: genericunpack (in /out/openexrexrcheckfuzzer) ==454== by 0x44B85F: exrdecodingrun (in /out/openexrexrcheckfuzzer) ==454== by 0x38BC5F: Imf40::(anonymous namespace)::TileProcess::rundecode(privexrcontextt const, int, Imf40::FrameBuffer const, std::1::vector<Imf40::Slice, std::1::allocator<Imf40::Slice> > const&) (in /out/openexrexrcheckfuzzer) ==454== by 0x388BE1: Imf40::TiledInputFile::Data::readTiles(int, int, int, int, int, int) (in /out/openexrexrcheckfuzzer) ==454== by 0x388619: Imf40::TiledInputFile::readTiles(int, int, int, int, int, int) (in /out/openexrexrcheckfuzzer) ==454== by 0x353755: Imf40::InputFile::Data::bufferedReadPixels(int, int) (in /out/openexrexrcheckfuzzer) ==454== by 0x352286: Imf40::InputFile::readPixels(int) (in /out/openexrexrcheckfuzzer) ==454== by 0x3190FA: Imf40::(anonymous namespace)::readMultiPart(Imf40::MultiPartInputFile&, bool, bool) (in /out/openexrexrcheckfuzzer) ==454== by 0x314C4D: Imf40::checkOpenEXRFile(char const, unsigned long, bool, bool, bool) (in /out/openexrexrcheckfuzzer) ==454== Uninitialised value was created by a heap allocation at 0x483B7F3: malloc (in /usr/lib/x8664-linux-gnu/valgrind/vgpreloadmemcheck-amd64-linux.so)

PoC In the attached archive, you will find: - The executable used for our tests. - The testcase used to trigger the bug.

To observe the bug, simply run the OSS-Fuzz helper script: bash git clone https://github.com/google/oss-fuzz.git cd oss-fuzz

python3 infra/helper.py buildimage openexr python3 infra/helper.py buildfuzzers --sanitizer=none openexr python3 infra/helper.py shell openexr

apt update && apt install -y valgrind ulimit -n 65535 valgrind --tool=memcheck --track-origins=yes /out/openexrexrcheckfuzzer /path/to/poc

Impact - Undefined Behavior - Potential crash - Denial of Service

Credit: Aldo Ristori archive0.zip

Update Note: Other saved testcases from the fuzzing campaign trigger the same underlying bug, but with a different manifestation. So there is one root cause (missing post-decode validation / zero-init before any unpack), with different call-sites. Below there are several archives, formatted like the previous one, that reproduce the other test cases.

Other observed sinks (distinct manifestations of the same bug):

Deep pointers path: genericunpackdeeppointers (deep scanline/tiled) archive1.zip

Deep sample table path: unpacksampletable (deep scanline) archive2.zip

Half conversion path: halftofloatbufferf16c via unpackhalftofloat3chanplanar archive3.zip

Deep compositing: CompositeDeepScanLine::readPixels → ThreadPool::addTask → LineCompositeTask::execute archive4.zip

Other sources

OpenEXR provides the specification and reference implementation of the EXR file format, an image storage format for the motion picture industry. In versions 3.3.0 through 3.3.5 and 3.4.0 through 3.4.2, while fuzzing openexrexrcheckfuzzer, Valgrind reports a conditional branch depending on uninitialized data inside genericunpack. This indicates a use of uninitialized memory. The issue can result in undefined behavior and/or a potential crash/denial of service. Versions 3.3.6 and 3.4.3 fix the issue.

MITRE

Affected Software

5 affected componentsFixes available
OpenEXR OpenEXR>=3.3.0<=3.3.5, >=3.4.0<=3.4.2
OpenEXR OpenEXR>=3.3.0<3.3.6
OpenEXR OpenEXR>=3.4.0<3.4.3
pip/OpenEXR>=3.4.0<3.4.3
3.4.3
pip/OpenEXR>=3.3.0<3.3.6
3.3.6

Event History

Nov 10, 2025
CVE Published
via MITRE·09:23 PM
Data Sourced
via MITRE·09:23 PM
DescriptionWeakness
Data Sourced
via NVD·10:15 PM
DescriptionSeverityWeaknessAffected Software
Apr 6, 2026
Advisory Published
via GitHub·05:51 PM
Data Sourced
via GitHub·05:51 PM
DescriptionSeverityWeaknessAffected Software
Apr 21, 58233
Event
via NVD·10:20 AM

Frequently Asked Questions

1

What is the severity of CVE-2025-64181?

CVE-2025-64181 has a moderate severity rating due to potential denial of service effects when processing certain EXR files.

2

How do I fix CVE-2025-64181?

To fix CVE-2025-64181, upgrade OpenEXR to version 3.3.6 or 3.4.3 or later.

3

What versions of OpenEXR are affected by CVE-2025-64181?

CVE-2025-64181 affects OpenEXR versions 3.3.0 through 3.3.5 and 3.4.0 through 3.4.2.

4

Is CVE-2025-64181 exploitable remotely?

CVE-2025-64181 can potentially be exploited remotely by processing malicious EXR files.

5

Are there any workarounds for CVE-2025-64181?

The only effective workaround for CVE-2025-64181 is to update to the fixed versions of OpenEXR.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203