Summary
A heap-buffer-overflow read vulnerability exists in cupsfilters/pdftoraster.c in the write_page_image() function. When a PDF page renders to an image smaller than the expected page size (a documented and expected scenario), an off-by-one error in the forward copy loop causes one extra row iteration, reading heap data past the allocated image buffer. The out-of-bounds data is passed through the color management pipeline and written to the CUPS raster output, leaking heap contents into the printer output stream.
Root Cause
In write_page_image(), lines 1970-1971 compute safe copy limits:
unsigned int copy_height = (height < doc->header.cupsHeight) ? height : doc->header.cupsHeight;
unsigned int copy_width = (width < doc->header.cupsWidth) ? width : doc->header.cupsWidth;
The forward loop at line 2011 then uses <= instead of <:
if (h <= copy_height) // ← BUG: should be h < copy_height
When the rendered image height is smaller than the page height, copy_height equals the image height. The loop iterates from h=0 to h=cupsHeight-1. After processing copy_height valid rows, bp has advanced by copy_height * image_rowsize bytes — exactly to the end of the heap allocation. The <= condition allows one additional iteration at h == copy_height, where bp points one row past the allocated buffer. The subsequent convertLine(bp, ...) call reads from this out-of-bounds pointer.
The same bug exists in the duplex/reverse loop at line 1981.
Affected Versions
- Introduced: commit
0ad5d2a08b40ff4e3f1406a9325cb309050f3800 (2026-01-24)
- Not in any release tag: The commit sits on master, 34 commits after tag
v2.1.1
- Any build from master between
0ad5d2a0 and a fix is affected
Trigger Conditions
The bug triggers when all of these conditions are met:
- A PDF page is rendered by
pdftoppm (or any configured PDF renderer) to an image smaller than the output page dimensions — a common scenario with font substitution, differing page size definitions, or rendering differences
- The forward (non-duplex, non-swap) loop path is taken
- Color space conversion requires reading from the source buffer (true for all non-trivial converters)
These conditions are realistic and occur during normal printer operation.
Impact
Information Disclosure
The out-of-bounds heap data flows through the color management subsystem (lcms2) and is written to the CUPS raster output via cupsRasterWritePixels(). This means heap data is leaked into the printer output stream — either to a captured raster file or to the physical printer.
Leak volume: One image_rowsize (page width × bytes per pixel) per triggering page. For a typical 300 DPI A4 CMYK job: ~9600 bytes of heap data per occurrence.
Denial of Service (related, secondary)
The same commit also added unconditional memset(lineBuf, ...) calls (lines 1983 and 2013) without checking doc->allocLineBuf. When the special-case color space path sets allocLineBuf = false (14 entries including CUPS_CSPACE_K, CUPS_CSPACE_W, CUPS_CSPACE_SW, etc.), lineBuf is NULL, causing a segmentation fault at the memset call.
Reproduction
Standalone (no external dependencies)
cd cupsfilters
gcc -std=c11 -O0 -g -fsanitize=address -fno-omit-frame-pointer \
test-pdftoraster-copy-height-asan.c -o /tmp/oob-harness
ASAN_OPTIONS=detect_leaks=0 /tmp/oob-harness
Expected output:
==PID==ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1
#0 identity_convert test-pdftoraster-copy-height-asan.c:79
#1 convert_line_chunked test-pdftoraster-copy-height-asan.c:100
#2 main test-pdftoraster-copy-height-asan.c:206
Real pipeline (requires ASan-instrumented lcms2)
cd cupsfilters
bash reproduce-oob-read-pipeline.sh
Expected output:
==PID==ERROR: AddressSanitizer: heap-buffer-overflow
READ of size 1
#0 Unroll3Bytes /tmp/lcms2-2.14/src/cmspack.c:308
#1 cmsDoTransform /tmp/lcms2-2.14/src/cmsxform.c:206
#2 convert_cspace_with_profiles cupsfilters/pdftoraster.c:855
#3 convert_line_chunked cupsfilters/pdftoraster.c:1142
#4 write_page_image cupsfilters/pdftoraster.c:2017
#5 out_page cupsfilters/pdftoraster.c:2301
#6 cfFilterPDFToRaster cupsfilters/pdftoraster.c:2674
Note: Without ASan-instrumented lcms2, the OOB read inside cmsDoTransform is silent — no runtime detection in production builds.
poc.zip
Attachments
test-pdftoraster-copy-height-asan.c — Minimal standalone reproduction (no external deps)
reproduce-oob-read.sh — Standalone repro script (build + run, cached)
reproduce-oob-read-pipeline.sh — Full pipeline repro script (requires ASan-lcms2)
test-pdftoraster-oob-read-harness.c — Real-pipeline harness source
All attachments are located in cupsfilters/ of the repository.
Summary
A heap-buffer-overflow read vulnerability exists in
cupsfilters/pdftoraster.cin thewrite_page_image()function. When a PDF page renders to an image smaller than the expected page size (a documented and expected scenario), an off-by-one error in the forward copy loop causes one extra row iteration, reading heap data past the allocated image buffer. The out-of-bounds data is passed through the color management pipeline and written to the CUPS raster output, leaking heap contents into the printer output stream.Root Cause
In
write_page_image(), lines 1970-1971 compute safe copy limits:The forward loop at line 2011 then uses
<=instead of<:When the rendered image height is smaller than the page height,
copy_heightequals the image height. The loop iterates fromh=0toh=cupsHeight-1. After processingcopy_heightvalid rows,bphas advanced bycopy_height * image_rowsizebytes — exactly to the end of the heap allocation. The<=condition allows one additional iteration ath == copy_height, wherebppoints one row past the allocated buffer. The subsequentconvertLine(bp, ...)call reads from this out-of-bounds pointer.The same bug exists in the duplex/reverse loop at line 1981.
Affected Versions
0ad5d2a08b40ff4e3f1406a9325cb309050f3800(2026-01-24)v2.1.10ad5d2a0and a fix is affectedTrigger Conditions
The bug triggers when all of these conditions are met:
pdftoppm(or any configured PDF renderer) to an image smaller than the output page dimensions — a common scenario with font substitution, differing page size definitions, or rendering differencesThese conditions are realistic and occur during normal printer operation.
Impact
Information Disclosure
The out-of-bounds heap data flows through the color management subsystem (lcms2) and is written to the CUPS raster output via
cupsRasterWritePixels(). This means heap data is leaked into the printer output stream — either to a captured raster file or to the physical printer.Leak volume: One
image_rowsize(page width × bytes per pixel) per triggering page. For a typical 300 DPI A4 CMYK job: ~9600 bytes of heap data per occurrence.Denial of Service (related, secondary)
The same commit also added unconditional
memset(lineBuf, ...)calls (lines 1983 and 2013) without checkingdoc->allocLineBuf. When the special-case color space path setsallocLineBuf = false(14 entries including CUPS_CSPACE_K, CUPS_CSPACE_W, CUPS_CSPACE_SW, etc.),lineBufis NULL, causing a segmentation fault at thememsetcall.Reproduction
Standalone (no external dependencies)
cd cupsfilters gcc -std=c11 -O0 -g -fsanitize=address -fno-omit-frame-pointer \ test-pdftoraster-copy-height-asan.c -o /tmp/oob-harness ASAN_OPTIONS=detect_leaks=0 /tmp/oob-harnessExpected output:
Real pipeline (requires ASan-instrumented lcms2)
cd cupsfilters bash reproduce-oob-read-pipeline.shExpected output:
Note: Without ASan-instrumented lcms2, the OOB read inside
cmsDoTransformis silent — no runtime detection in production builds.poc.zip
Attachments
test-pdftoraster-copy-height-asan.c— Minimal standalone reproduction (no external deps)reproduce-oob-read.sh— Standalone repro script (build + run, cached)reproduce-oob-read-pipeline.sh— Full pipeline repro script (requires ASan-lcms2)test-pdftoraster-oob-read-harness.c— Real-pipeline harness sourceAll attachments are located in
cupsfilters/of the repository.