Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/targa.imageio/targainput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,34 @@ TGAInput::open(const std::string& name, ImageSpec& newspec)
if (m_tga.type >= TYPE_PALETTED_RLE)
m_spec.attribute("compression", "rle");

// The width/height/bpp fields are not cross-checked against how much
// pixel data the file actually contains, so a corrupt header can claim
// an arbitrarily large image (e.g. thousands of pixels square) backed
// by only a few bytes of real data. Reject implausible claims before
// committing to a potentially huge allocation in readimg(). Compare
// against the *on-disk* pixel size (palette/16-bit storage is smaller
// per pixel than the decoded, unpacked ImageSpec) -- and RLE can expand
// at most 128x (a 1-byte run-length count can encode up to 128 output
// pixels from very little input) -- so give a generous bound based on
// how much data remains in the file.
{
int bytespp = (m_tga.bpp == 15) ? 2 : (m_tga.bpp / 8);
uint64_t raw_pixel_bytes = uint64_t(m_tga.width) * uint64_t(m_tga.height)
* uint64_t(bytespp);
uint64_t filesize = uint64_t(ioproxy()->size());
uint64_t pos = uint64_t(iotell());
uint64_t avail = filesize > pos ? filesize - pos : 0;
uint64_t max_plausible_bytes = (m_tga.type >= TYPE_PALETTED_RLE)
? avail * 128
: avail;
if (raw_pixel_bytes > max_plausible_bytes) {
errorfmt(
"TGA header claims image size {} bytes, implausible for {} bytes of remaining file data",
raw_pixel_bytes, avail);
return false;
}
}

/*std::cerr << "[tga] " << m_tga.width << "x" << m_tga.height << "@"
<< (int)m_tga.bpp << " (" << m_spec.nchannels
<< ") type " << (int)m_tga.type << "\n";*/
Expand Down
7 changes: 2 additions & 5 deletions testsuite/targa/ref/out.txt
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,7 @@ Reading ../oiio-images/targa/round_grill.tga
Comparing "../oiio-images/targa/round_grill.tga" and "round_grill.tga"
PASS
Converting src/crash1.tga to crash1.exr
iconvert ERROR copying "src/crash1.tga" to "crash1.exr" :
Read error: hit end of file in targa reader
iconvert ERROR: TGA header claims image size 1506428560 bytes, implausible for 1886 bytes of remaining file data
oiiotool ERROR: read : "src/crash2.tga": Palette image with no palette
Full command line was:
> oiiotool --oiioattrib try_all_readers 0 src/crash2.tga -o crash2.exr
Expand All @@ -204,9 +203,7 @@ Full command line was:
oiiotool ERROR: read : "src/crash1708.tga": Too big a color palette (382) for 8 bpp, assume corruption
Full command line was:
> oiiotool --oiioattrib try_all_readers 0 src/crash1708.tga -o crash1708.exr
oiiotool ERROR: read : "src/crash3952.tga": Uncompressed image size 15231.5 MB exceeds the 1024 MB limit.
Image claimed to be 60927x65535, 4-channel uint8. Possible corrupt input?
If this is a valid file, raise the OIIO attribute "limits:imagesize_MB".
oiiotool ERROR: read : "src/crash3952.tga": TGA header claims image size 15971403780 bytes, implausible for 3 bytes of remaining file data
Full command line was:
> oiiotool --oiioattrib limits:imagesize_MB 1024 --oiioattrib try_all_readers 0 src/crash3952.tga -o crash3952.exr
oiiotool ERROR: read : "src/crash-20250423.tga": Corrupt palette index
Expand Down
Loading