Skip to content

math.c jets: _math_rnd global leaves u3qi_* composites dependent on call history #74

Description

@sigilante

Found during a durability review of the transcendental jets (pkg/noun/jets/i/math.c) headed upstream in urbit/vere#1044 and urbit/vere#1045.

Problem. _math_rnd is a single file-scope static int whose only writers are the u3wi_* door-dispatch wrappers (they read the door's rounding mode at axis 60 of the core). The composite u3qi_* entry points — atan2, pow, pow-n for all four doors, plus u3qi_rh_tan/u3qi_rq_tan whose kernels divide under _math_rnd — never set it themselves. Any caller that reaches a u3qi_* entry point without a preceding u3wi_* call in the same process gets rounding behavior determined by whatever unrelated door invocation last ran (or the compiled-in default if none did): two calls with identical arguments can produce different results depending on prior history.

Why the test suite can't see it. The MATH_JET_HARNESS bit-exact test build compiles only the _rd_*/_rs_*/_rh_*/_rq_* cores; the entire u3qi_*/u3wi_* wrapper layer is behind #ifndef MATH_JET_HARNESS, so the harness structurally cannot exercise the stale-mode path.

Secondary (low severity). The axis-60 rounding-mode fetch (_rnd_of(u3r_at(60, cor))) is not checked with u3_none/u3ud before the switch, unlike the sample fetch two lines up; a hand-crafted ill-typed core silently falls to the minMag default instead of matching what the Nock would do.

Suggested fix (either):

  • give every composite u3qi_* entry point an explicit rounding-mode parameter (or have it set _math_rnd on entry) so its output is a pure function of its arguments; or
  • document + assert the contract "never call u3qi_* outside a u3wi_* wrapper", and add a harness target that compiles the wrapper layer so the contract is testable.

Also guard the axis-60 fetch like the sample fetch.

For scope contrast: everything else in the review came up clean — no leaks, no GMP road-lifetime hazards (no GMP in this file), sample validation solid, u3m_bail discipline consistent. Registration is 135-tree-only by design (shipped kelvin trees are frozen).

Fix should land on the branches behind urbit/vere#1044 / urbit/vere#1045 before they merge.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions