Repository: python-pillow/Pillow

Issue:
Uncaught Exception(s) in Pillow Library
### What did you do?

We (@DogukanK, @esraercann) discovered a 3 crashes in Python Pillow library because of 'Uncaught Exception' via specially crafted input. 

### What did you expect to happen?

Exceptions should be handled properly in Pillow.

### What actually happened?

Crash. 

* Here is the first crash log:

 ```bash
=== Uncaught Python exception: ===

error: argument out of range

Traceback (most recent call last):

  File "/home/ubuntu/targets/pillow/main.py", line 20, in TestOneInput

    pilfuzz(data)

  File "/home/ubuntu/targets/pillow/main.py", line 11, in pilfuzz

    out = im.transpose(Image.Transpose.FLIP_LEFT_RIGHT)

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 2807, in transpose

    def transpose(self, method):

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/ImageFile.py", line 266, in load

    err_code = decoder.decode(b"")[1]

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/PpmImagePlugin.py", line 273, in decode

    data = self._decode_blocks(maxval)

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/PpmImagePlugin.py", line 261, in _decode_blocks

    data += o32(value) if self.mode == "I" else o8(value)

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/_binary.py", line 93, in o32le

    def o32le(i: int) -> bytes:

error: argument out of range
```
Poc:

```python3
>>> from PIL import Image                                                                                                                                     

>>> im = Image.open("./crash-4148ce4324e2e54cc3c2c6aa369420ddbd9dee5e")

>>> im.transpose(Image.Transpose.FLIP_LEFT_RIGHT)                                                                                                             

Traceback (most recent call last):                                               

  File "<stdin>", line 1, in <module>                                                                                                                              

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 2818, in transpose                                                                    

    self.load()                                                                                                                                                    

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/ImageFile.py", line 266, in load                                                                      

    err_code = decoder.decode(b"")[1]                                            

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/PpmImagePlugin.py", line 273, in decode                                                               

    data = self._decode_blocks(maxval)                                           

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/PpmImagePlugin.py", line 261, in _decode_blocks

    data += o32(value) if self.mode == "I" else o8(value)                                                                                                          

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/_binary.py", line 94, in o32le                                                                        

    return pack("<I", i)                                                         

struct.error: argument out of range 
```

* Here is the second crash:

```python3
>>> from PIL import Image, ImageFilter

>>> im = Image.open("./crash-73c3d4dca546775e83ea511a0fc882f3c5b6f60a")

>>> im.filter(ImageFilter.DETAIL)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 1281, in filter

    self.load()

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/GbrImagePlugin.py", line 94, in load

    self.frombytes(self.fp.read(self._data_size))

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 810, in frombytes

    d.setimage([self.im](http://self.im/))

MemoryError
```

* Here is the third crash:

```bash
=== Uncaught Python exception: ===

OverflowError: Python int too large to convert to C ssize_t

Traceback (most recent call last):

  File "/home/ubuntu/targets/pillow/main.py", line 16, in TestOneInput

    pilfuzz(data)

  File "/home/ubuntu/targets/pillow/main.py", line 10, in pilfuzz

    with Image.open(io.BytesIO(data)) as im:

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 3258, in open

    preinit()

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 3273, in _open_core

    fp.seek(0)

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/TiffImagePlugin.py", line 1082, in __init__

    super().__init__(fp, filename)

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/ImageFile.py", line 137, in __init__

    self._open()

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/TiffImagePlugin.py", line 1109, in _open

    self._seek(0)

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/TiffImagePlugin.py", line 1150, in _seek

    self.fp.seek(self.__next)

OverflowError: Python int too large to convert to C ssize_t
```

PoC:

```python3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux                                                                                  

Type "help", "copyright", "credits" or "license" for more information.                                                                                          

>>> from PIL import Image                                                                                                                              

>>> im = Image.open("./crash-ecd6f7d1583338a2a2c4aaee944b0b3371f4f926")                                                                                

Traceback (most recent call last):                                              

  File "<stdin>", line 1, in <module>                                           

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 3293, in open                                                             

    im = _open_core(                    

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/Image.py", line 3274, in _open_core                                                       

    im = factory(fp, filename)          

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/TiffImagePlugin.py", line 1082, in __init__                                               

    super().__init__(fp, filename)                                              

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/ImageFile.py", line 137, in __init__                                                      

    self._open()                        

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/TiffImagePlugin.py", line 1109, in _open                                                  

    self._seek(0)                       

  File "/home/ubuntu/.local/lib/python3.10/site-packages/PIL/TiffImagePlugin.py", line 1150, in _seek                                                  

    self.fp.seek(self.__next)           

ValueError: cannot fit 'int' into an offset-sized integer

```

### What are your OS, Python and Pillow versions?

* Python3 Version: Python 3.10.12
* PIL Version: 10.2.0
* OS: Ubuntu 22.04.3 LTS 5.15.0-84-generic x86/64


### Crash Files

[Archive.zip](https://github.com/python-pillow/Pillow/files/14588492/Archive.zip)



Discussion:
Looking at your second situation, I see it is hitting
https://github.com/python-pillow/Pillow/blob/9e3d1a7b05b5c961eb1daaae4e5ed62feb6d5507/src/decode.c#L194-L198

You are trying to create an image that is 134,217,792px wide, greater than the limit in that logic of 67,108,856px wide.

So that's not an unexpected exception, that's something we're deliberately raising.
The first one was sent to security@. The error for that one is raised by python core, and isn't an issue unless valgrind finds memory corruption, and since that's directly in python core, it would be a bug for them. 

Resolving patch:
diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py
--- a/src/PIL/TiffImagePlugin.py
+++ b/src/PIL/TiffImagePlugin.py
@@ -1166,6 +1166,9 @@ def _seek(self, frame):
                 self.__next,
                 self.fp.tell(),
             )
+            if self.__next >= 2**63:
+                msg = "Unable to seek to frame"
+                raise ValueError(msg)
             self.fp.seek(self.__next)
             self._frame_pos.append(self.__next)
             logger.debug("Loading tags, location: %s", self.fp.tell())


Test patch:
diff --git a/Tests/images/seek_too_large.tif b/Tests/images/seek_too_large.tif
new file mode 100644
Binary files /dev/null and b/Tests/images/seek_too_large.tif differ
diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py
--- a/Tests/test_file_tiff.py
+++ b/Tests/test_file_tiff.py
@@ -113,6 +113,10 @@ def test_bigtiff(self, tmp_path: Path) -> None:
             outfile = str(tmp_path / "temp.tif")
             im.save(outfile, save_all=True, append_images=[im], tiffinfo=im.tag_v2)
 
+    def test_seek_too_large(self):
+        with pytest.raises(ValueError, match="Unable to seek to frame"):
+            Image.open("Tests/images/seek_too_large.tif")
+
     def test_set_legacy_api(self) -> None:
         ifd = TiffImagePlugin.ImageFileDirectory_v2()
         with pytest.raises(Exception) as e: