diff --git a/Tests/images/trailer_loop.pdf b/Tests/images/trailer_loop.pdf new file mode 100644 index 00000000000..7bf27ca370e Binary files /dev/null and b/Tests/images/trailer_loop.pdf differ diff --git a/Tests/test_pdfparser.py b/Tests/test_pdfparser.py index d85fb1212e3..cba6cd05390 100644 --- a/Tests/test_pdfparser.py +++ b/Tests/test_pdfparser.py @@ -125,3 +125,8 @@ def test_duplicate_xref_entry() -> None: pdf = PdfParser("Tests/images/duplicate_xref_entry.pdf") assert pdf.xref_table.existing_entries[6][0] == 1197 pdf.close() + + +def test_trailer_loop() -> None: + with pytest.raises(PdfFormatError, match="trailer loop found"): + PdfParser("Tests/images/trailer_loop.pdf") diff --git a/src/PIL/PdfParser.py b/src/PIL/PdfParser.py index 2c9031469ad..f7f3a46431d 100644 --- a/src/PIL/PdfParser.py +++ b/src/PIL/PdfParser.py @@ -685,7 +685,9 @@ def read_trailer(self) -> None: if b"Prev" in self.trailer_dict: self.read_prev_trailer(self.trailer_dict[b"Prev"]) - def read_prev_trailer(self, xref_section_offset: int) -> None: + def read_prev_trailer( + self, xref_section_offset: int, processed_offsets: list[int] = [] + ) -> None: assert self.buf is not None trailer_offset = self.read_xref_table(xref_section_offset=xref_section_offset) m = self.re_trailer_prev.search( @@ -700,7 +702,11 @@ def read_prev_trailer(self, xref_section_offset: int) -> None: ) trailer_dict = self.interpret_trailer(trailer_data) if b"Prev" in trailer_dict: - self.read_prev_trailer(trailer_dict[b"Prev"]) + processed_offsets.append(xref_section_offset) + check_format_condition( + trailer_dict[b"Prev"] not in processed_offsets, "trailer loop found" + ) + self.read_prev_trailer(trailer_dict[b"Prev"], processed_offsets) re_whitespace_optional = re.compile(whitespace_optional) re_name = re.compile(