OpenPrinting / OpenPrinting/libcupsfilters
Heap-buffer-overflow READ in pdftoraster.c write_page_image()
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 17
- Forks
- 71
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 13
Description
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
0ad5d2a0and 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.
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in cupsfilters/pdftoraster.c at write_page_image(), especially the forward and duplex/reverse copy loops and the lineBuf handling described in the issue. Run test-pdftoraster-copy-height-asan.c with the standalone reproduction, then use reproduce-oob-read-pipeline.sh if the ASan-instrumented lcms2 setup is available. Done means the reported OOB read and NULL line-buffer crash are no longer reproduced in the affected paths.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 63/100