Description
Page.remove_rotation() raises ValueError: bad rect when a page contains widgets with empty or infinite rects (e.g., invisible signature fields with Rect(0, 0, 0, 0)).
The widget loop in remove_rotation() calls widget.update() without error handling, but widget._validate() raises ValueError("bad rect") if the rect is empty or infinite.
Steps to Reproduce
import fitz
doc = fitz.open()
page = doc.new_page()
page.set_rotation(90)
# Add a widget with a zero-dimension rect (simulating an invisible signature field)
widget = fitz.Widget()
widget.field_type = fitz.PDF_WIDGET_TYPE_SIGNATURE
widget.rect = fitz.Rect(0, 0, 0, 0)
page.add_widget(widget)
page.remove_rotation() # raises ValueError: bad rect
Expected Behavior
remove_rotation() should skip widgets with invalid rects gracefully, similar to how the link loop in the same method already handles errors:
for link in self.get_links():
...
try:
self.insert_link(link)
except Exception:
pass
Actual Behavior
Traceback (most recent call last):
File "...", line X, in remove_rotation
widget.update()
File "...", line X, in update
self._validate()
File "...", line X, in _validate
raise ValueError("bad rect")
ValueError: bad rect
Root Cause
The rotation inverse matrix transforms degenerate rects into rects that are still degenerate:
Rect(0, 0, 0, 0) * rot → e.g., Rect(612.0, 0.0, 612.0, 0.0) — still empty (x0 == x1)
FZ_INFINITE_RECT * rot → still infinite (overflow back to sentinel values)
The link loop and annotation loop in remove_rotation() both have guards for this case, but the widget loop does not.
Context
We hit this in production processing medical record PDFs. Scanned documents that have been through OCR or signing workflows often contain invisible signature fields or hidden form fields with zero-dimension rects. When these pages also have /Rotate != 0, remove_rotation() crashes.
Suggested Fix
Wrap widget.update() in a try/except, matching the pattern used for links:
for widget in self.widgets():
r = widget.rect * rot
widget.rect = r
try:
widget.update()
except Exception:
pass
Environment
- PyMuPDF 1.26.6
- Python 3.12
- macOS / Linux (AWS Lambda)
Description
Page.remove_rotation()raisesValueError: bad rectwhen a page contains widgets with empty or infinite rects (e.g., invisible signature fields withRect(0, 0, 0, 0)).The widget loop in
remove_rotation()callswidget.update()without error handling, butwidget._validate()raisesValueError("bad rect")if the rect is empty or infinite.Steps to Reproduce
Expected Behavior
remove_rotation()should skip widgets with invalid rects gracefully, similar to how the link loop in the same method already handles errors:Actual Behavior
Root Cause
The rotation inverse matrix transforms degenerate rects into rects that are still degenerate:
Rect(0, 0, 0, 0) * rot→ e.g.,Rect(612.0, 0.0, 612.0, 0.0)— still empty (x0 == x1)FZ_INFINITE_RECT * rot→ still infinite (overflow back to sentinel values)The link loop and annotation loop in
remove_rotation()both have guards for this case, but the widget loop does not.Context
We hit this in production processing medical record PDFs. Scanned documents that have been through OCR or signing workflows often contain invisible signature fields or hidden form fields with zero-dimension rects. When these pages also have
/Rotate != 0,remove_rotation()crashes.Suggested Fix
Wrap
widget.update()in a try/except, matching the pattern used for links:Environment