Repository: python-pillow/Pillow

Issue:
Unpickle Image serialized with older version of Pillow
### What did you do?
Pickle TIff image with pillow==11.1.0 and then de-serialize it with pillow==11.2.1
### What did you expect to happen?
I expect the image to be successfully de-serialized
### What actually happened?
It's crashing with
### What are your OS, Python and Pillow versions?

* OS: 
Mac OS, Ubuntu
* Python: 
Python 3.12.7
* Pillow: 
11.2.1

To reproduce the issue 
Install pillow==11.1.0 and execute the following code (you can download the tiff from - https://people.math.sc.edu/Burkardt/data/tif/at3_1m4_01.tif)

```python
from PIL import Image
import pickle
image = Image.open('./at3_1m4_01.tif')
pickle.dump(image, open('./test.pickle', 'wb'))
```

Then install pillow==11.2.1 and de-serialize the file
```python
 pickle.load(open('./test.pickle', 'rb'))
```

It's crashing with 
```
File ~/.pyenv/versions/3.12.7/envs/forms/lib/python3.12/site-packages/PIL/ImageFile.py:260, in ImageFile.__setstate__(self, state)
    258 def __setstate__(self, state: list[Any]) -> None:
    259     self.tile = []
--> 260     self.filename = state[5]
    261     super().__setstate__(state)
```

I tested with regular PNG file and the issue is not reproducible.

Hints from issue comments:
@radarhere: The `self.filename` line was added in #8859 as part of 11.2.1

I suppose we could adjust the code to work with states from Pillow < 11.2.1, but that would be in the next release of Pillow, 11.3.0. If you're unable to upgrade from Pillow 11.1.0 in one environment, then I don't feel completely confident that you could upgrade from Pillow 11.2.1 to 11.3.0 in your other environment. How did you arrive at this scenario where you are using two versions simultaneously? Why can you not simply upgrade to use the same version in both environments?@manigoad: Thanks for the reply. I have training dataset that was generated with Pillow < 11.1.0. The application was working as expected with Pillow 11.1.0, but when upgraded to 11.22.1 it was no longer able to load it. 

Fixing it in 11.3.0 will be great. I already pin it to 11.1.0 to resolve the issue and once 11.3.0 is release I'll upgrade to it.@radarhere: I've created #8938 to resolve this. Would you be able to test it? I would like to be sure that your script will work and you won't create another issue after Pillow 11.3.0 is released.@manigoad: Thanks, yeah sure I'll test it. @manigoad: @radarhere tested the patch locally and it works as expected. @radarhere: Thanks.

Solution patch:
diff --git a/src/PIL/ImageFile.py b/src/PIL/ImageFile.py
index bcb7d462e..bf556a2c6 100644
--- a/src/PIL/ImageFile.py
+++ b/src/PIL/ImageFile.py
@@ -257,7 +257,8 @@ class ImageFile(Image.Image):
 
     def __setstate__(self, state: list[Any]) -> None:
         self.tile = []
-        self.filename = state[5]
+        if len(state) > 5:
+            self.filename = state[5]
         super().__setstate__(state)
 
     def verify(self) -> None:


Test patch:
diff --git a/Tests/test_pickle.py b/Tests/test_pickle.py
index 1c48cb743..54cef00ad 100644
--- a/Tests/test_pickle.py
+++ b/Tests/test_pickle.py
@@ -162,3 +162,13 @@ def test_pickle_font_file(tmp_path: Path, protocol: int) -> None:
 
     # Assert
     helper_assert_pickled_font_images(font, unpickled_font)
+
+
+def test_load_earlier_data() -> None:
+    im = pickle.loads(
+        b"\x80\x04\x95@\x00\x00\x00\x00\x00\x00\x00\x8c\x12PIL.PngImagePlugin"
+        b"\x94\x8c\x0cPngImageFile\x94\x93\x94)\x81\x94]\x94(}\x94\x8c\x01L\x94K\x01"
+        b"K\x01\x86\x94NC\x01\x00\x94eb."
+    )
+    assert im.mode == "L"
+    assert im.size == (1, 1)