Skip to content

Commit 0571b61

Browse files
BUG: Fix set_page_label TypeError when start=None (#4286)
* ROB: Tolerate extra operands before Tm/cm in layout mode A matrix operator consumes the 6 operands nearest to it; values left on the operand stack before those (malformed content streams) overflowed TextStateManager.new_transform() and raised TypeError in layout mode text extraction. Complete the matrix with only the last 6 operands in _complete_matrix and add_cm, mirroring the tolerance already in place for missing/non-numeric TD and Tz operands (#4232, #4233). Fixes #4283 Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com> * Fix set_page_label TypeError when start=None The start parameter is annotated Optional[int] and its validation accepts None as "not set", but _set_page_label used , which treats None as a value to write and crashes in NumberObject. Only write /St when a concrete non-zero start was provided. Fixes #4285 Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com> * Add tests for set_page_label with start=None Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com> * Update tests/test_writer.py * Update tests/test_writer.py --------- Co-authored-by: rahul05ranjan <11793455+rahul05ranjan@users.noreply.github.com> Co-authored-by: Stefan <96178532+stefan6419846@users.noreply.github.com>
1 parent 694aa59 commit 0571b61

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

‎pypdf/_writer.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3460,7 +3460,7 @@ def _set_page_label(
34603460
new_page_label[NameObject("/S")] = NameObject(style)
34613461
if prefix is not None:
34623462
new_page_label[NameObject("/P")] = TextStringObject(prefix)
3463-
if start != 0:
3463+
if start is not None and start != 0:
34643464
new_page_label[NameObject("/St")] = NumberObject(start)
34653465

34663466
if NameObject(CatalogAttributes.PAGE_LABELS) not in self._root_object:

‎tests/test_writer.py‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,38 @@ def test_set_page_label(pdf_file_path):
17691769
writer.write(pdf_file_path)
17701770

17711771

1772+
def test_set_page_label__start_none():
1773+
"""`start=None` is a legitimate "not set" value and must not crash at write time (#4285).
1774+
1775+
It behaves exactly like the default `0`: no `/St` entry is written, so numbering
1776+
restarts at 1 per the PDF spec.
1777+
"""
1778+
writer = PdfWriter()
1779+
for _ in range(4):
1780+
writer.add_blank_page(width=100, height=100)
1781+
writer.set_page_label(0, 3, "/D", None, None)
1782+
1783+
buffer = BytesIO()
1784+
writer.write(buffer)
1785+
buffer.seek(0)
1786+
1787+
assert PdfReader(buffer).page_labels == ["1", "2", "3", "4"]
1788+
1789+
1790+
def test_set_page_label__prefix_only_without_start():
1791+
"""A prefix-only label with `style=None` and `start=None` works (#4285)."""
1792+
writer = PdfWriter()
1793+
for _ in range(4):
1794+
writer.add_blank_page(width=100, height=100)
1795+
writer.set_page_label(0, 3, None, "P", None)
1796+
1797+
buffer = BytesIO()
1798+
writer.write(buffer)
1799+
buffer.seek(0)
1800+
1801+
assert PdfReader(buffer).page_labels == ["P", "P", "P", "P"]
1802+
1803+
17721804
@pytest.mark.enable_socket
17731805
def test_iss1601():
17741806
url = "https://github.com/py-pdf/pypdf/files/10579503/badges-38.pdf"

0 commit comments

Comments
 (0)