Skip to content

Stack-based buffer overflow in JM_set_annot_callout_line #5112

Description

@k3rn3lbr3ach3r

Description of the bug

In src/extra.i (JM_set_annot_callout_line), a fixed stack buffer of 3 points (fz_point points[3]) is indexed up to
caller-controlled count. In src/__init__.py:9816–9817, Page.add_freetext_annot(..., callout=...) passes point_count = len(callout) without length bounds validation.MuPDF's pdf_set_annot_callout_line, a callout line (/CL) has either 2 or 3 points.
Passing >= 4 points writes past the stack buffer onto the stack frame, causing a SIGBUS crash.

How to reproduce the bug

import pymupdf

doc = pymupdf.open()
page = doc.new_page()
rect = pymupdf.Rect(50, 50, 200, 150)
callout = [(10, 10), (20, 20), (30, 30), (40, 40), (50, 50), (60, 60)]
page.add_freetext_annot(rect, "test", callout=callout)

Security Impact

Because each point coordinate corresponds to two IEEE-754 32-bit floats, this out-of-bounds stack write overwrites callee-saved registers (RBX, RBP, R12–R14) and the saved return address (RIP). I have attached a video below demonstrating an end-to-end RCE proof-of-concept.

PoC Demonstration

compressed_poc_video.mp4

PyMuPDF version

1.28.2

Operating system

Linux

Python version

3.13

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions