Hello,
exiv2 in bookworm/bullseye dies on a crafted JPEG-2000 file. The 0.28 line is not affected,
but the 0.27 line is, and that is what the stable releases ship.
`Jp2Image::readMetadata()` subtracts the box header size from the attacker-controlled box
length without checking that the length can hold a header (src/jp2image.cpp:212):
boxFileTypeFound = true;
std::vector<byte> boxData(box.length - boxSize); /* 1..7 -> 0xfffffffffffffff9..fffe */
`boxSize` is `sizeof(Jp2BoxHeader)` (8), `box.length` comes straight from the file, and the
earlier bound check plus the `== 0` / `== 1` special cases let 2..7 through. The subtraction
wraps, `std::vector<byte>` asks for ~2^64 bytes, and because the allocation is not caught the
process dies instead of reporting corrupted metadata. The same expression exists in
`printStructure()` (line 479).
Reproduction, 80 bytes: a valid 12-byte JP2 signature box followed by a `ftyp` box whose
length field is 0x00000001.
exiv2 -p a poc-ftyp-len1.jp2
terminate called after throwing an instance of 'std::bad_alloc'
Aborted
With ASan the abort is explicit (`requested allocation size 0xfffffffffffffff9`,
`Jp2Image::readMetadata`). A length of 4 gives the same result.
Suggested fix, attached as a two-line patch (same guard upstream added for the 0.28 line):
enforce(box.length >= sizeof(box), Exiv2::kerCorruptedMetadata);
With it the sample returns through the normal corrupted-metadata path and 40 corpus files
still parse unchanged.
Status: fixed on 0.28 (0.28.7+ carry the guard) and in sid, absent in 0.27.7 and in the whole
`0.27-maintenance` branch, which is frozen at the v0.27.7 merge. Upstream report with the
reproducer and patch: https://github.com/Exiv2/exiv2/issues/9563
Please consider a stable update and a CVE for the 0.27 line.
Thanks,
netwind
zwfnetwind@hotmail.com