From 80c302015455c271cf89176592248561f6b3f219 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 8 May 2021 00:13:58 +1000 Subject: [PATCH] Fix an infinite loop when checking number of TIFF frames --- Tests/images/multipage_multiple_frame_loop.tiff | Bin 0 -> 816 bytes Tests/images/multipage_out_of_order.tiff | Bin 0 -> 816 bytes Tests/images/multipage_single_frame_loop.tiff | Bin 0 -> 816 bytes Tests/test_file_tiff.py | 13 +++++++++++++ src/PIL/TiffImagePlugin.py | 7 ++++++- 5 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 Tests/images/multipage_multiple_frame_loop.tiff create mode 100644 Tests/images/multipage_out_of_order.tiff create mode 100644 Tests/images/multipage_single_frame_loop.tiff diff --git a/Tests/images/multipage_multiple_frame_loop.tiff b/Tests/images/multipage_multiple_frame_loop.tiff new file mode 100644 index 0000000000000000000000000000000000000000..b6759b08023f766caa9c66355849d9dd2ebfd610 GIT binary patch literal 816 zcmb_ayAHxI40IAes1sB?q|%WEHg*Qq{s21zNGuF2to>EHsS{tF54+R$xW7oIuEixkf8vkBzvhqL zz#llp-#~@HA2oqL*DEhTG4?J0rqS?^uGNX(&d&+skLCoA`A(-R2GP&S8vFY>$uMwU aryMw?lO-2)Dp2Efn)9%#rFHUI*6Rg47$3&~ literal 0 HcmV?d00001 diff --git a/Tests/images/multipage_out_of_order.tiff b/Tests/images/multipage_out_of_order.tiff new file mode 100644 index 0000000000000000000000000000000000000000..1576a549b58ae83da286c7481c1b8f7f797ad4fd GIT binary patch literal 816 zcmb`FEf2yl5QgtsSjZGCd?aHM0}hWsVD<;_2uLsp40gYVpM^xCNygi**Httjd^G9q zY45J<_qOb9>+{h#3Vuc1-xy#KjL0pL5sd z-oR7GcW@Ep&cO3**iY4T4O(fePV8!0DBge)|ThP?zBDbFJ^5~=Cmp)0+ daH3NNj_IUGd!2H`h)y#b-zX5*sqqmRyy?5o=-`rdS+cWwD&;04Ek}*QM}`FGAIf?N3nvwqX*3L`q7tnhv3 ilN5$?I%U8yofK)WQ;r&^(@e~2L-djO)Tzl4iC!;pIUn!< literal 0 HcmV?d00001 diff --git a/Tests/test_file_tiff.py b/Tests/test_file_tiff.py index c24438c4851..dd312d6df6a 100644 --- a/Tests/test_file_tiff.py +++ b/Tests/test_file_tiff.py @@ -301,6 +301,19 @@ def test_multipage_last_frame(self): assert im.size == (20, 20) assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255) + def test_frame_order(self): + # A frame can't progress to itself after reading + with Image.open("Tests/images/multipage_single_frame_loop.tiff") as im: + assert im.n_frames == 1 + + # A frame can't progress to a frame that has already been read + with Image.open("Tests/images/multipage_multiple_frame_loop.tiff") as im: + assert im.n_frames == 2 + + # Frames don't have to be in sequence + with Image.open("Tests/images/multipage_out_of_order.tiff") as im: + assert im.n_frames == 3 + def test___str__(self): filename = "Tests/images/pil136.tiff" with Image.open(filename) as im: diff --git a/src/PIL/TiffImagePlugin.py b/src/PIL/TiffImagePlugin.py index 5d046761a6a..ed14ec4c7b0 100644 --- a/src/PIL/TiffImagePlugin.py +++ b/src/PIL/TiffImagePlugin.py @@ -1067,7 +1067,12 @@ def _seek(self, frame): self._frame_pos.append(self.__next) logger.debug("Loading tags, location: %s" % self.fp.tell()) self.tag_v2.load(self.fp) - self.__next = self.tag_v2.next + if self.tag_v2.next in self._frame_pos: + # This IFD has already been processed + # Declare this to be the end of the image to prevent an infinite loop + self.__next = 0 + else: + self.__next = self.tag_v2.next if self.__next == 0: self._n_frames = frame + 1 if len(self._frame_pos) == 1: