Exiv2 Segmentation Faults in Exiv2::EpsImage::writeMetadata() via crafted EPS file
Description
Exiv2 is a C++ library and a command-line utility to read, write, delete and modify Exif, IPTC, XMP and ICC image metadata. An out-of-bounds read was found in Exiv2 versions 0.28.5 and earlier. The out-of-bounds read is triggered when Exiv2 is used to write metadata into a crafted image file. An attacker could potentially exploit the vulnerability to cause a denial of service by crashing Exiv2, if they can trick the victim into running Exiv2 on a crafted image file. Note that this bug is only triggered when writing the metadata, which is a less frequently used Exiv2 operation than reading the metadata. The bug is fixed in version 0.28.6.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
Exiv2PyPI | <= 0.17.3 | — |
Affected products
1Patches
14 files changed · +32 −29
src/epsimage.cpp+11 −29 modified@@ -241,19 +241,17 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList uint32_t posTiff = 0; uint32_t sizeTiff = 0; + ErrorCode errcode = write ? ErrorCode::kerImageWriteFailed : ErrorCode::kerFailedToReadImageData; + // check for DOS EPS const bool dosEps = (size >= dosEpsSignature.size() && memcmp(data, dosEpsSignature.data(), dosEpsSignature.size()) == 0); if (dosEps) { #ifdef DEBUG EXV_DEBUG << "readWriteEpsMetadata: Found DOS EPS signature\n"; #endif - if (size < 30) { -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << "Premature end of file after DOS EPS signature.\n"; -#endif - throw Error(write ? ErrorCode::kerImageWriteFailed : ErrorCode::kerFailedToReadImageData); - } + + enforce(size >= 30, errcode); posEps = getULong(data + 4, littleEndian); posEndEps = getULong(data + 8, littleEndian) + posEps; posWmf = getULong(data + 12, littleEndian); @@ -285,29 +283,13 @@ void readWriteEpsMetadata(BasicIo& io, std::string& xmpPacket, NativePreviewList if (write) throw Error(ErrorCode::kerImageWriteFailed); } - if (posEps < 30 || posEndEps > size) { -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << "DOS EPS file has invalid position (" << posEps << ") or size (" << (posEndEps - posEps) - << ") for EPS section.\n"; -#endif - throw Error(write ? ErrorCode::kerImageWriteFailed : ErrorCode::kerFailedToReadImageData); - } - if (sizeWmf != 0 && (posWmf < 30 || posWmf + sizeWmf > size)) { -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << "DOS EPS file has invalid position (" << posWmf << ") or size (" << sizeWmf - << ") for WMF section.\n"; -#endif - if (write) - throw Error(ErrorCode::kerImageWriteFailed); - } - if (sizeTiff != 0 && (posTiff < 30 || posTiff + sizeTiff > size)) { -#ifndef SUPPRESS_WARNINGS - EXV_WARNING << "DOS EPS file has invalid position (" << posTiff << ") or size (" << sizeTiff - << ") for TIFF section.\n"; -#endif - if (write) - throw Error(ErrorCode::kerImageWriteFailed); - } + enforce(30 <= posEps, errcode); + enforce(sizeWmf == 0 || 30 <= posWmf, errcode); + enforce(sizeTiff == 0 || 30 <= posTiff, errcode); + + enforce(posEps <= posEndEps && posEndEps <= size, errcode); + enforce(posWmf <= size && sizeWmf <= size - posWmf, errcode); + enforce(posTiff <= size && sizeTiff <= size - posTiff, errcode); } // check first line
test/data/issue_ghsa_496f_x7cq_cq39_poc.jpg+0 −0 addedtests/bugfixes/github/test_issue_ghsa_496f_x7cq_cq39.py+20 −0 added@@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- + +from system_tests import CaseMeta, CopyTmpFiles, path, check_no_ASAN_UBSAN_errors +@CopyTmpFiles("$data_path/issue_ghsa_496f_x7cq_cq39_poc.jpg") + +class EpsImageDeleteSegV(metaclass=CaseMeta): + """ + Regression test for the bug described in: + https://github.com/Exiv2/exiv2/security/advisories/GHSA-496f-x7cq-cq39 + """ + url = "https://github.com/Exiv2/exiv2/security/advisories/GHSA-496f-x7cq-cq39" + + filename = path("$tmp_path/issue_ghsa_496f_x7cq_cq39_poc.jpg") + commands = ["$exiv2 rm $filename"] + stdout = [""] + stderr = [ + """$exception_in_erase """ + filename + """: +$kerCorruptedMetadata +"""] + retval = [1]
tests/regression_tests/test_regression_allfiles.py+1 −0 modified@@ -121,6 +121,7 @@ def get_valid_files(data_dir): "issue_ghsa_hrw9_ggg3_3r4r_poc.jpg", "issue_ghsa_g9xm_7538_mq8w_poc.mov", "issue_ghsa_38h4_fx85_qcx7_poc.tiff", + "issue_ghsa_496f_x7cq_cq39_poc.jpg", "pocIssue283.jpg", "poc_1522.jp2", "xmpsdk.xmp",
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-496f-x7cq-cq39ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-54080ghsaADVISORY
- github.com/Exiv2/exiv2/commit/e737332427711f15bcdc4e903203d6b7493eaec0ghsax_refsource_MISCWEB
- github.com/Exiv2/exiv2/security/advisories/GHSA-496f-x7cq-cq39ghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.