Bug 2492871 (CVE-2026-12912)
| Summary: | CVE-2026-12912 libtiff: libtiff: Heap-based buffer overflow via crafted PixarLog-compressed TIFF image | ||
|---|---|---|---|
| Product: | [Other] Security Response | Reporter: | OSIDB Bzimport <bzimport> |
| Component: | vulnerability | Assignee: | Product Security <prodsec-ir-bot> |
| Status: | NEW --- | QA Contact: | |
| Severity: | high | Docs Contact: | |
| Priority: | high | ||
| Version: | unspecified | CC: | rhel-process-autobot, watson-tool-maintainers |
| Target Milestone: | --- | Keywords: | Security |
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: |
A flaw was found in libtiff. A remote attacker could exploit this vulnerability by providing a specially crafted PixarLog-compressed TIFF image. This issue occurs when decoding Pixarlog codec images with the PIXARLOGDATAFMT_8BITABGR output format and a specific stride value, leading to a heap-based buffer overflow. This could potentially result in arbitrary code execution or a denial of service (DoS).
|
Story Points: | --- |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | --- | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
The issue happens when decoding Pixarlog codec images with PIXARLOGDATAFMT_8BITABGR output format and stride = 3 . The decoder writes 4 output bytes per 3 decoded samples (synthetic alpha byte) but advances the output cursor by 3 bytes. This mismatch causes a linear heap based buffer-overflow of approx. width bytes per scan line. For every 4-bytes in the overflow, the first is always 0x00 while the others are controlled. The overflow happens on a user allocated buffer, but according to the docs (TIFFReadScnaline.rst) the user is supposed to allocate a buffer of this TIFFScanlineSize(t) , which will return the incorrect size. The bug can be pinpointed to two locations in libtiff/tif_pixarlog.c - the horizontalAccumulate8abgr function (3->4 byte expansion), and PixarLogDecode which updates the output pointer. RCA PixarLogDecode dispatches on sp->user_datafmt: case PIXARLOGDATAFMT_8BITABGR: horizontalAccumulate8abgr(up, llen, sp->stride, (unsigned char *)op, sp->ToLinear8); op += llen * sizeof(unsigned char); // <-- WRONG for stride=3 break; horizontalAccumulate8abgr with stride == 3 emits 4 bytes per input triplet: if (stride == 3) { op[0] = 0; op[1] = t1; op[2] = t2; op[3] = t3; /* 4 bytes written */ n -= 3; while (n > 0) { n -= 3; wp += 3; op += 4; /* advance 4 per triplet */ op[0] = 0; op[1] = …; op[2] = …; op[3] = …; } } So for llen = stride * width = 3 * W input samples the function writes (llen / 3) * 4 = 4 * W bytes. PixarLogDecode then advances op by only llen = 3 * W. The next iteration starts W bytes before the position where the previous write ended, and on the final iteration the writes extend W bytes past the end of the buffer the caller allocated from TIFFScanlineSize (which is W * stride * 1 = 3 * W bytes for this configuration). Reachability Any application that selects PIXARLOGDATAFMT_8BITABGR via TIFFSetField(tif, TIFFTAG_PIXARLOGDATAFMT, PIXARLOGDATAFMT_8BITABGR) and then reads a PixarLog-compressed TIFF with SamplesPerPixel == 3 is affected. The standard format picker in TIFFRGBAImageBegin does not select 8BITABGR (it picks 8BIT, 16BIT or FLOAT), so TIFFReadRGBAImage is not directly affected. PoC I attached a c program, that when executed produces a file that will overflow a heap buffer by 64 bytes. To verify I compiled it along with ASan-enabled libtiff, and got: $ gcc -fsanitize=address -g -O1 pixarlog_heap_overflow_poc.c \ -I$LIBTIFF/libtiff -I$BUILD/libtiff \ -L$BUILD/libtiff -ltiff -Wl,-rpath,$BUILD/libtiff -o poc $ ./poc ================================================================= ==...==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x… at pc 0x… WRITE of size 1 at 0x… thread T0 #0 horizontalAccumulate8abgr libtiff/tif_pixarlog.c:470 #1 PixarLogDecode libtiff/tif_pixarlog.c:980 #2 TIFFReadScanline libtiff/tif_read.c:465 #3 main poc_pixarlog_8bitabgr.c:31 0 bytes to the right of 192-byte region The 192-byte region is the caller's TIFFScanlineSize-sized buffer (W * 3 = 192). The decoder writes 256 bytes ((W * 3 / 3) * 4 = 256) per row, producing a 64-byte overflow per row. pixarlog_heap_overflow_poc.c Fix I didn't open a PR for this fix, since I'm not sure how to make it confidential and I wanted the maintainer to review this issue first. If you want me to open the PR, lmk and I'll do it as instructed. I think that in order to fix, we need to correct the output pointer advancement in PixarLogDecode: case PIXARLOGDATAFMT_8BITABGR: horizontalAccumulate8abgr(up, llen, sp->stride, (unsigned char *)op, sp->ToLinear8); if (sp->stride == 3) op += (size_t)(llen / 3) * 4; /* 4 output bytes per triplet */ else op += (size_t)llen * sizeof(unsigned char); break; And also to somehow make TIFFScanlineSize return the correct size. We can maybe do this with introducing a codec ScanLinesize override that is checked in the function: /* tif_strip.c — TIFFScanlineSize64 */ if (tif->tif_scanlinesize_override) return tif->tif_scanlinesize_override(tif); // ...