July 16, 2026
How a ~3 KB TIFF Can Make libtiff Ask for 16 GB of Memory
A tiny malformed image, one oversized SamplesPerPixel tag, and a denial-of-service bug in one of the most widely used TIFF parsing…

By Aleens-labs
2 min read
A tiny malformed image, one oversized SamplesPerPixel tag, and a denial-of-service bug in one of the most widely used TIFF parsing libraries. Most people see a small image file and think: harmless. That assumption is exactly why image parsers are such interesting targets for vulnerability research.
A file can be tiny on disk but still describe something enormous to the software parsing it. In this case, a malformed TIFF file only needed one unrealistic metadata value to make libtiff prepare for an allocation of approximately 16.4 GB.
This write-up covers CVE-2026–36849, a denial-of-service vulnerability I found in libtiff. The issue was caused by an oversized SamplesPerPixel value flowing into buffer-size calculations before enough sanity checking happened.
This is not a remote code execution claim. The confirmed impact is resource exhaustion / denial of service. But it is still a useful example of how small parser mistakes can become large operational problems.
TL;DR
CVE : CVE-2026-36849
Project : libtiff
Affected version tested : 4.7.1 / upstream master at test time
Vulnerability type : Uncontrolled resource consumption
CWE : CWE-400, CWE-789
Trigger : Crafted TIFF with oversized SamplesPerPixel
Malicious value : 0xFFF9 / 65529
Allocation attempted : Approximately 16.4 GB
Confirmed impact : Denial of serviceCVE : CVE-2026-36849
Project : libtiff
Affected version tested : 4.7.1 / upstream master at test time
Vulnerability type : Uncontrolled resource consumption
CWE : CWE-400, CWE-789
Trigger : Crafted TIFF with oversized SamplesPerPixel
Malicious value : 0xFFF9 / 65529
Allocation attempted : Approximately 16.4 GB
Confirmed impact : Denial of serviceThe bug can be summarized like this:
tiny TIFF file
-> oversized SamplesPerPixel tag
-> inflated decoded-buffer calculation
-> ~16.4 GB allocation attempt
-> out-of-memory denial of servicetiny TIFF file
-> oversized SamplesPerPixel tag
-> inflated decoded-buffer calculation
-> ~16.4 GB allocation attempt
-> out-of-memory denial of serviceThis issue was coordinated with the libtiff maintainers through the project's public vulnerability tracker and was later assigned CVE-2026–36849.
Why this caught my attention :
Image formats are full of metadata. Some metadata describes colors. Some describes compression. Some describes dimensions. Some tells the decoder how many values exist for each pixel. That last part matters here.
In TIFF, the SamplesPerPixel tag tells the parser how many samples are stored for each pixel. Normal values are small:
Image type Typical SamplesPerPixel
Grayscale 1
RGB 3
RGBA 4Image type Typical SamplesPerPixel
Grayscale 1
RGB 3
RGBA 4The malformed file used a value that does not make sense for a normal image:
SamplesPerPixel = 0xFFF9 = 65529SamplesPerPixel = 0xFFF9 = 65529That value should immediately look suspicious. The problem was not just that the value was strange. The problem was that it could influence how much memory libtiff tried to allocate.
The root cause :
The vulnerable behavior comes from a metadata-to-allocation path. The crafted TIFF used values like:
Width = 500
Height = 500
SamplesPerPixel = 65529
BitsPerSample = 8
Bytes per sample = 1Width = 500
Height = 500
SamplesPerPixel = 65529
BitsPerSample = 8
Bytes per sample = 1When those values are multiplied together, the decoded buffer requirement becomes:
500 x 500 x 65529 x 1 = 16,382,250,000 bytes (~16.4 GB)500 x 500 x 65529 x 1 = 16,382,250,000 bytes (~16.4 GB)The file itself does not need to be large. The danger comes from the parser trusting metadata enough to turn a small input file into a huge memory request. That is the core bug:
small input
large declared layout
unrealistic allocation
process runs out of memorysmall input
large declared layout
unrealistic allocation
process runs out of memoryAffected code path
The issue was reached through libtiff's RGBA decoding path. The simplified call chain:
TIFFReadRGBAImageOriented()
-> gtStripContig()
-> _TIFFReadEncodedStripAndAllocBuffer()
-> malloc(0x3d0754c10)TIFFReadRGBAImageOriented()
-> gtStripContig()
-> _TIFFReadEncodedStripAndAllocBuffer()
-> malloc(0x3d0754c10)Representative source locations from the tested build:
TIFFReadRGBAImageOriented() tif_getimage.c:643
-> gtStripContig() tif_getimage.c:1227
-> _TIFFReadEncodedStripAndAllocBuffer() tif_read.c:615
-> malloc(...) out-of-memoryTIFFReadRGBAImageOriented() tif_getimage.c:643
-> gtStripContig() tif_getimage.c:1227
-> _TIFFReadEncodedStripAndAllocBuffer() tif_read.c:615
-> malloc(...) out-of-memoryThe allocation size observed during testing was 0x3d0754c10 bytes, which corresponds to roughly 16.4 GB.