Exclude formats with ! when opening#9564
Conversation
hugovk
left a comment
There was a problem hiding this comment.
Right, so:
Image.open(path) # tries all, default formats=None
Image.open(path, formats=None) # tries all
Image.open(path, formats=["JPEG"]) # only tries JPEG
Image.open(path, formats=["!EPS"]) # tries all but EPS
Image.open(path, formats=["EPS", "!EPS"]) # tries all but EPS
Image.open(path, formats=["JPEG", "!EPS"]) # only tries JPEG, !EPS has no effectThat last one could be surprising, but it's probably okay.
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
I originally thought this should try none, but it's an edge case that could be debated. I've pushed your suggestions, and gone with trying all except EPS. |
|
If someone is currently denying all formats with: from PIL import Image
im = Image.open("Tests/images/hopper.png", formats=[])
print(im)On Traceback (most recent call last):
File "/Users/hugo/github/Pillow/1.py", line 2, in <module>
im = Image.open("Tests/images/hopper.png", formats=[])
File "/Users/hugo/github/Pillow/src/PIL/Image.py", line 3715, in open
raise UnidentifiedImageError(msg)
PIL.UnidentifiedImageError: cannot identify image file 'Tests/images/hopper.png'With the PR: This PR updates the security recommendation in |
hugovk
left a comment
There was a problem hiding this comment.
Also, given a PNG file with .jpg extension, and only allowing formats=["JPEG"], and counting the preinit and init calls:
from PIL import Image
calls = []
preinit, init = Image.preinit, Image.init
Image.preinit = lambda: (calls.append("preinit"), preinit())[1]
Image.init = lambda: (calls.append("init"), init())[1]
try:
# cp Tests/images/hopper.png /tmp/hopper_png.jpg
Image.open("/tmp/hopper_png.jpg", formats=["JPEG"]).load()
except Image.UnidentifiedImageError:
print("UnidentifiedImageError")
print(calls)
print("plugins loaded:", len(Image.ID), sorted(Image.ID))On main, the lazy loading means the JPEG plugin is loaded, the file is rejected, the allowlist is exhausted, and it quickly gives up:
UnidentifiedImageError
[]
plugins loaded: 1 ['JPEG']
With this PR, the fallback runs anyway, both preinit and init are called and all the plugins are loaded for nothing:
UnidentifiedImageError
['preinit', 'init']
plugins loaded: 43 ['AVIF', 'BLP', 'BMP', 'BUFR', 'CUR', 'DCX', 'DDS', 'DIB', 'EPS', 'FITS', 'FLI', 'FTEX', 'GBR', 'GIF', 'GRIB', 'HDF5', 'ICNS', 'ICO', 'IM', 'IMT', 'IPTC', 'JPEG', 'JPEG2000', 'MCIDAS', 'MPEG', 'MSP', 'PCD', 'PCX', 'PIXAR', 'PNG', 'PPM', 'PSD', 'QOI', 'SGI', 'SPIDER', 'SUN', 'TGA', 'TIFF', 'WEBP', 'WMF', 'XBM', 'XPM', 'XVTHUMB']
| assert im.size == (128, 128) | ||
|
|
||
| @pytest.mark.parametrize("formats", (("!PNG",), ("PNG", "!PNG"), ("JPEG", "!PNG"))) | ||
| def test_open_formats_exclude(self, formats: tuple[str]) -> None: |
There was a problem hiding this comment.
| def test_open_formats_exclude(self, formats: tuple[str]) -> None: | |
| def test_open_formats_exclude(self, formats: tuple[str, ...]) -> None: |
Currently, to prevent opening a file in a certain format, without limiting your access to any other format, you can
or
It would be nice if there was a simpler way. This PR suggests
And yes, I suggest that
Image.open(path, formats=["EPS", "!EPS"])still does not allow an EPS image to be opened.