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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions