Repository navigation
Conversation
## Extended Description
`ImagingAllocateArray()` computes the block count in 32-bit signed
arithmetic:
blocks_count = (im->ysize + lines_per_block - 1) / lines_per_block;
With a large arena block size (~2 GiB) and a specific image height, the
addition overflows and wraps negative, so `calloc()` allocates (near)
zero elements while the allocation loop still writes 16-byte
`ImagingMemoryBlock` entries into it — a heap out-of-bounds write
(confirmed by UBSan/ASan).
Independently, `ImagingDestroyArray()` terminates its cleanup loop on a
NULL pointer instead of `blocks_count`, so whenever the count is wrong
for any reason, it reads past the array and passes whatever it finds to
`free()` (confirmed with valgrind against the official wheel).
This PR fixes both, independently:
1. Compute the block count in 64 bits with an `INT_MAX` range check,
failing cleanly with a memory error on overflow. No behavior change
for any valid input.
2. Bound the destroy loop by `im->blocks_count`, keeping the NULL
early-exit, so a miscalculated count can never turn into an
out-of-bounds read followed by `free()`.
Both are defensive robustness fixes; triggering requires the host to
raise the block size via `set_block_size()` or `PILLOW_BLOCK_SIZE`,
which is not attacker-controllable.
radarhere
reviewed
Nov 3, 2026
| #include "Imaging.h" | ||
| #include <string.h> | ||
| #include <limits.h> | ||
| #include <stdint.h> |
Contributor
Author
There was a problem hiding this comment.
INT_MAX (used in the new range check) comes from <limits.h>, and int64_t from <stdint.h>. I added both explicitly rather than relying on them being pulled in indirectly — but happy to drop either one if they're already guaranteed elsewhere.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Extended Description
ImagingAllocateArray()computes the block count in 32-bit signed arithmetic:With a large arena block size (~2 GiB) and a specific image height, the addition overflows and wraps negative, so
calloc()allocates (near) zero elements while the allocation loop still writes 16-byteImagingMemoryBlockentries into it — a heap out-of-bounds write (confirmed by UBSan/ASan).Independently,
ImagingDestroyArray()terminates its cleanup loop on a NULL pointer instead ofblocks_count, so whenever the count is wrong for any reason, it reads past the array and passes whatever it finds tofree()(confirmed with valgrind against the official wheel).This PR fixes both, independently:
INT_MAXrange check, failing cleanly with a memory error on overflow. No behavior change for any valid input.im->blocks_count, keeping the NULL early-exit, so a miscalculated count can never turn into an out-of-bounds read followed byfree().Both are defensive robustness fixes.Both defects were found while fuzzing and are described in the
security advisory (GHSA-xq7j-jqgf-54xq):
https://github.com/python-pillow/Pillow/security/advisories/GHSA-xq7j-jqgf-54xq