Skip to content

fix(tiff): handle CMYK and odd bit depths in the tiled reader - #5475

Open
lgritz wants to merge 2 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-tiffcmyk
Open

lgritz wants to merge 2 commits into
AcademySoftwareFoundation:mainfrom
lgritz:lg-tiffcmyk

Conversation

@lgritz

@lgritz lgritz commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Fixes #5315

This is essentially the same fix as PR #5296, but for the tile path (we had only fixed scanline).

For CMYK (photometric=separated) files, readspec_photometric() drops m_spec.nchannels to 3 for the CMYK->RGB conversion while m_inputchannels stays 4, and the tiled path was unaware of the difference:

  • sub-8-bit and 9-15 bit samples were unpacked straight into the caller's 3-channel buffer, writing tile_pixels*4 values into room for tile_pixels*3 (heap buffer overflow write)
  • planarconfig=separate overflowed the same way in separate_to_contig
  • at 8 and 16 bits the tile was read into scratch and never copied out, so the caller got back uninitialized heap
  • 17-31 bit samples were never unpacked at all, likewise leaving the caller's buffer uninitialized

Assisted-by: Claude Code / Claude Opus 5

Fixes 5315

This is essentially the same fix as PR 5296, but for the tile path
(we had only fixed scanline).

For CMYK (photometric=separated) files, readspec_photometric() drops
m_spec.nchannels to 3 for the CMYK->RGB conversion while
m_inputchannels stays 4, and the tiled path was unaware of the
difference:

- sub-8-bit and 9-15 bit samples were unpacked straight into the
  caller's 3-channel buffer, writing tile_pixels*4 values into room
  for tile_pixels*3 (heap buffer overflow write)
- planarconfig=separate overflowed the same way in separate_to_contig
- at 8 and 16 bits the tile was read into scratch and never copied
  out, so the caller got back uninitialized heap
- 17-31 bit samples were never unpacked at all, likewise leaving the
  caller's buffer uninitialized

Assisted-by: Claude Code / Claude Opus 5

Signed-off-by: Larry Gritz <lg@larrygritz.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Tiled row-padding handling and regression coverage for CMYK 8/16-bit and 9–15-bit paths remain unresolved.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 Medium severity

Open (1)
What changed in this PR

Fixes tiled TIFF decoding for CMYK images and non-native bit depths, with regression coverage against strip decoding.

Changes:

  • Adds scratch-buffer handling for CMYK and planar tile reads.
  • Adds unpacking for supported non-native sample depths.
  • Updates tiled/strip regression comparisons and expected outputs.
File Summary
testsuite/​tiff-misc/​run.py Adds tiled-versus-strip regression comparisons. Moderate finding (2 votes): coverage is missing CMYK 8/16-bit and 9–15-bit paths.
testsuite/​tiff-misc/​ref/​out.txt Updates expected test output.
testsuite/​tiff-misc/​ref/​out-libtiff470.txt Updates libtiff 4.7 expected output.
testsuite/​tiff-misc/​ref/​out-libtiff470-c.txt Updates libtiff 4.7 variant output.
testsuite/​tiff-misc/​ref/​out-libtiff470-b.txt Updates libtiff 4.7 variant output.
testsuite/​tiff-misc/​ref/​out-libtiff430.txt Updates libtiff 4.3 expected output.
testsuite/​tiff-misc/​ref/​out-libtiff410.txt Updates libtiff 4.1 expected output.
testsuite/​tiff-misc/​ref/​out-libtiff409.txt Updates libtiff 4.0.9 expected output.
testsuite/​tiff-misc/​ref/​out-libtiff403.txt Updates libtiff 4.0.3 expected output.
testsuite/​tiff-misc/​ref/​out-libtiff403-c.txt Updates libtiff 4.0.3 variant output.
testsuite/​tiff-misc/​ref/​out-libtiff403-b.txt Updates libtiff 4.0.3 variant output.
src/​tiff.imageio/​tiffinput.cpp Updates tiled decoding and CMYK conversion. Moderate finding (1 vote): packed tile rows require independent row-padding handling.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread testsuite/tiff-misc/run.py Outdated
Comment on lines +56 to +57
for base in [ "cmyk-1bit", "cmyk-4bit-planar", "rgb-24bit" ] :
command += oiiotool ("src/{0}-tiled.tif src/{0}-strip.tif --diff".format(base))
The tiled/strip regression matrix was missing two of the four bugs the
previous commit fixed: CMYK at native 8 and 16 bits (read into scratch
and never copied out) and 9-15 bit samples. Adds cmyk-8bit, cmyk-12bit
and cmyk-16bit pairs. All three fail against the pre-fix reader.

Assisted-by: Claude Code / Claude Opus 5
Signed-off-by: Larry Gritz <lg@larrygritz.com>
@lgritz lgritz added bug Crash or wrong behavior of an existing feature. file formats Image file formats, ImageInput, ImageOutput labels Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Crash or wrong behavior of an existing feature. file formats Image file formats, ImageInput, ImageOutput

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: heap-buffer-overflow (out-of-bounds write) in TIFFInput::bit_convert (src/tiff.imageio/tiffinput.cpp)

2 participants