Skip to content

Correct integer overflow in 16-bit resampling#9480

Merged
radarhere merged 13 commits into
python-pillow:mainfrom
hayatoikoma:fixresample
May 2, 2026
Merged

Correct integer overflow in 16-bit resampling#9480
radarhere merged 13 commits into
python-pillow:mainfrom
hayatoikoma:fixresample

Conversation

@hayatoikoma
Copy link
Copy Markdown
Contributor

📝 Description
This PR fixes a bug in Resample.c where downsampling 16-bit images (I;16) using filters with negative lobes (such as Image.Resampling.LANCZOS) could result in byte corruption.

Because Lanczos weighting can create overshoots (ringing artifacts) near sharp edges, the accumulated floating-point sum can sometimes exceed the 16-bit maximum (65535) or fall below zero. Previously, these out-of-bounds values were not correctly clamped before being cast or packed into the 16-bit output buffer, leading to integer overflow/underflow and corrupted pixels.

This update correctly clamps the accumulated float values to the [0, 65535] range for I;16 images during resampling.

🛠️ Changes Made

  • src/libImaging/Resample.c: Added bounding/clamping logic to ensure the accumulated float sum is strictly clamped to 0 and 65535 before writing to the I;16 output buffer.
  • Unit Tests: Added test_resampling_clamp to verify this behavior. The test constructs an image with a hard step edge (0 to 65535) and applies a 5x Lanczos downsampling, comparing the clamped I;16 output against a float (F) reference image to ensure no byte corruption occurs.

@hayatoikoma hayatoikoma changed the title Fix integer overflow/byte corruption in 16-bit (I;16) resampling by clamping float sums Fix integer overflow in 16-bit resampling Mar 20, 2026
This commit fixes a bug in Resample.c where downsampling 16-bit
images (I;16) using filters with negative lobes (such as
Image.Resampling.LANCZOS) could result in byte corruption.

Because Lanczos weighting can create overshoots (ringing artifacts)
near sharp edges, the accumulated floating-point sum can sometimes
exceed the 16-bit maximum (65535) or fall below zero. Previously,
these out-of-bounds values were not correctly clamped before being
cast or packed into the 16-bit output buffer, leading to integer
overflow/underflow and corrupted pixels.

This update correctly clamps the accumulated float values to the
[0, 65535] range for I;16 images during resampling.
@hayatoikoma hayatoikoma marked this pull request as ready for review March 20, 2026 22:50
@hayatoikoma
Copy link
Copy Markdown
Contributor Author

@radarhere Codecov was failing and I added another test. But I couldn't figure out how I can run Codecov to check the result so it might be going to fail again.

Please let me know if there is anything else I should do to merge this PR. 👍🏼

Comment thread src/libImaging/Resample.c Outdated
@hayatoikoma
Copy link
Copy Markdown
Contributor Author

@wiredfool @radarhere Any additional action items for me? Do I need to squash the commits?

@radarhere
Copy link
Copy Markdown
Member

You don't need to squash the commits, no.

Did you use AI to develop this?

@hayatoikoma
Copy link
Copy Markdown
Contributor Author

Yes, I used AI.

@radarhere radarhere added the 🤖-assisted AI-assisted label Apr 6, 2026
CLIP16 is already defined in ImagingUtils.h
@radarhere radarhere changed the title Fix integer overflow in 16-bit resampling Correct integer overflow in 16-bit resampling May 2, 2026
@radarhere radarhere merged commit 7e4ca8b into python-pillow:main May 2, 2026
55 of 56 checks passed
@hayatoikoma
Copy link
Copy Markdown
Contributor Author

Awesome! Thank you for merging it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🤖-assisted AI-assisted

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants