diff --git a/pypdf/generic/_data_structures.py b/pypdf/generic/_data_structures.py index bb2e028d2..9af470028 100644 --- a/pypdf/generic/_data_structures.py +++ b/pypdf/generic/_data_structures.py @@ -194,11 +194,27 @@ def _clone( """ # First check if this is a chain list, we need to loop to prevent recur if ( - ("/Next" not in ignore_fields and "/Next" in src) - or ("/Prev" not in ignore_fields and "/Prev" in src) + ( + "/Next" not in ignore_fields + and "/Next" in src + and isinstance(src.raw_get("/Next"), IndirectObject) + ) + or ( + "/Prev" not in ignore_fields + and "/Prev" in src + and isinstance(src.raw_get("/Prev"), IndirectObject) + ) ) or ( - ("/N" not in ignore_fields and "/N" in src) - or ("/V" not in ignore_fields and "/V" in src) + ( + "/N" not in ignore_fields + and "/N" in src + and isinstance(src.raw_get("/N"), IndirectObject) + ) + or ( + "/V" not in ignore_fields + and "/V" in src + and isinstance(src.raw_get("/V"), IndirectObject) + ) ): ignore_fields = list(ignore_fields) for lst in (("/Next", "/Prev"), ("/N", "/V")): @@ -230,7 +246,7 @@ def _clone( except Exception: cur_obj = None for (s, c) in objs: - c._clone(s, pdf_dest, force_duplicate, ignore_fields + [k]) + c._clone(s, pdf_dest, force_duplicate, ignore_fields) for k, v in src.items(): if k not in ignore_fields: diff --git a/tests/test_generic.py b/tests/test_generic.py index 044608b30..d0b4d59b6 100644 --- a/tests/test_generic.py +++ b/tests/test_generic.py @@ -1044,3 +1044,21 @@ def test_cloning(caplog): obj21 = obj20.clone(writer, ignore_fields=None) assert "/Test" in obj21 assert isinstance(obj21.get("/Test2"), IndirectObject) + + +@pytest.mark.external +def test_iss1615(): + """ + test cases where /N is not indicating chains of objects + """ + url = "https://github.com/py-pdf/pypdf/files/10671366/graph_letter.pdf" + name = "graph_letter.pdf" + reader = PdfReader(BytesIO(get_pdf_from_url(url, name=name))) + writer = PdfWriter() + writer.append(reader) + assert ( + "/N" + in writer.pages[0]["/Annots"][0] + .get_object()["/AP"]["/N"]["/Resources"]["/ColorSpace"]["/Cs1"][1] + .get_object() + )