Fix PIL image cache key collisions across dimensions#9359
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the _save_pil_image method to include image metadata (mode, width, and height) in the SHA256 hash calculation, ensuring unique cache keys for images with identical raw bytes but different dimensions. A unit test has been added to verify that different image dimensions result in distinct paths. Review feedback recommends using incremental hash updates to improve memory efficiency when handling large images.
| img_meta = f'{image.mode}:{image.width}:{image.height}:'.encode() | ||
| img_hash = hashlib.sha256(img_meta + image.tobytes()).hexdigest() |
There was a problem hiding this comment.
For better memory efficiency, especially with large images, you can update the hash object incrementally instead of creating a new concatenated bytes object. This avoids allocating extra memory for the combined metadata and image bytes.
| img_meta = f'{image.mode}:{image.width}:{image.height}:'.encode() | |
| img_hash = hashlib.sha256(img_meta + image.tobytes()).hexdigest() | |
| hasher = hashlib.sha256() | |
| hasher.update(f'{image.mode}:{image.width}:{image.height}:'.encode()) | |
| hasher.update(image.tobytes()) | |
| img_hash = hasher.hexdigest() |
PR type
PR information
Fixes #9360.
Template._save_pil_image()used onlyimage.tobytes()to build the image cache hash. Pillow's flattened byte stream does not include mode, width, or height, so images with identical raw bytes but different dimensions could reuse the same cached PNG path.This PR includes the image mode and dimensions in the hash input before the raw pixel bytes. It also adds a regression test that creates two images from the same bytes with dimensions
120x80and80x120, verifies they get different cache paths, and checks that both cached files keep their correct dimensions.Experiment results