Skip to content

tech-debt: bound depythonize recursion depth in native bindings (stack-overflow hardening) #134

Description

@dean0x

Deferred from PR #131 (Python bindings code review, 2026-07-02).

Problem

The native binding walks the incoming Python object graph via depythonize with no recursion-depth bound:

  • crates/mds-python/src/lib.rsextract_vars (vars), parse_modules (modules), and CompileResult.__new__ (unpickle).

A pathologically deep structure (buildable iteratively, then handed to compile(..., vars=…) / compile_virtual(modules=…) / pickle.loads) could overflow the Rust stack → an uncatchable process abort. This also sidesteps the crate's "never panic across the FFI boundary" guarantee, because extract_vars/parse_modules run before run_catching.

Severity is low in practice: input is in-process, same-trust caller (not network-facing) — this is defense-in-depth. Reviewer confidence ~70%, filed as a Suggestion (not a blocker) in the #131 review.

Why deferred (not fixed in #131)

pyo3/pythonize 0.29 expose no depth/recursion-limit knob. A correct fix needs either a custom recursion-limited Deserializer wrapping pythonize::Depythonizer, or a hand-rolled pre-walk replicating its full type dispatch — genuine surgery with a real risk of silent incompleteness (miss one container type → false confidence).

Scope — cross-binding

The same latent gap exists in mds-napi (its depythonize equivalent). The correct fix is a coordinated bound applied at both native-binding boundaries so parity is preserved — not a unilateral change in one crate.

Acceptance criteria

  • A shared, tested depth bound at the native-binding boundary (mds-python + mds-napi) that surfaces a clean mds::invalid_options (or mds::resource_limit) error instead of aborting on deeply-nested input.
  • Regression test with a deeply-nested vars/modules payload asserting the clean error.

Target: v0.4.0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions