Repository navigation
Read from tall PSD tiles safely - #10151
Merged
radarhere merged 4 commits intoOct 9, 2026
Merged
Conversation
Member
|
I suspect this problem was only introduced in #10089 |
Contributor
Author
|
Ah interesting - I went back and tried the file on |
radarhere
force-pushed
the
fix/psd-rle-bytecounts-dos
branch
2 times, most recently
from
October 9, 2026 11:40
ab45e52 to
5511602
Compare
radarhere
force-pushed
the
fix/psd-rle-bytecounts-dos
branch
from
October 9, 2026 12:14
5511602 to
e4340eb
Compare
radarhere
approved these changes
Oct 9, 2026
radarhere
enabled auto-merge (squash)
October 9, 2026 12:17
radarhere
disabled auto-merge
October 9, 2026 12:17
radarhere
enabled auto-merge (squash)
October 9, 2026 12:18
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.
Issue
When opening a PackBits-compressed PSD,
PsdImagePlugin._maketilereads the per-row bytecounts table using a size taken straight from the file header:ysizeis the declared image height, an unsigned 32-bit field that is never validated. A 40-byte PSD declaring a height of0xFFFFFFFFmakes Pillow askread()for ~26 GB while parsing the header. Where the allocation is refused,Image.open()dies with a rawMemoryError; where it succeeds, the process still pins tens of gigabytes of address space for a file containing no image data. Any service that opens untrusted PSDs can be taken down by a single tiny upload.Both the merged image (read during
Image.open()) and individual layers (read through.layers) go through_maketile, so both paths are affected.Reproduction
Fix
Read the table with
ImageFile._safe_read(), which exists for exactly this case ("Unlike fp.read(n), this function doesn't trust the user"). It reads block by block instead of pre-allocating the declared size, and raisesOSError("Truncated File Read")when the file cannot supply the table:One subtlety:
_safe_readreturnsb""for a non-positive size, butread()raisesValueErrorthere, andtest_bounds_crash_overflowrelies on a crafted layer with a negative height being rejected withValueError. The fix rejects a negative height explicitly first, preserving that behavior.The regression test opens a 40-byte PSD declaring a
0xFFFFFFFF-tall image and asserts it is rejected withOSError. Without the fix, the test dies withMemoryError.