Skip to content

fix(vm): range-check magnitude before the long long cast in value_to_string (#695)#698

Merged
InauguralPhysicist merged 1 commit into
InauguralSystems:mainfrom
Nitjsefnie-OSC:fix/value-to-string-ub
Jul 24, 2026
Merged

fix(vm): range-check magnitude before the long long cast in value_to_string (#695)#698
InauguralPhysicist merged 1 commit into
InauguralSystems:mainfrom
Nitjsefnie-OSC:fix/value-to-string-ub

Conversation

@Nitjsefnie

Copy link
Copy Markdown
Contributor

Fixes #695.

value_to_string's VAL_NUM case had n == (long long)n && fabs(n) < 9007199254740992.0, so the (long long)n cast (left conjunct) was evaluated before the magnitude guard. For any |n| >= 2^63 reaching this path that is undefined behavior (float-cast-overflow — flagged by UBSan/CodeQL). Swapping the conjuncts makes the range check short-circuit and guard the cast:

if (fabs(n) < 9007199254740992.0 && n == (long long)n)

In-range formatting is unchanged (an out-of-range value falls to the %.*g branch either way, so local output is identical — the UB only manifests under UBSan/CodeQL, which is CIs regression guard here). ./build.sh clean; run_all_tests.sh 3183/3183.


Generated by Claude Fable 5 (brief, review), Claude Opus 4.8 (implementation)

…string (InauguralSystems#695)

value_to_string's VAL_NUM case tested `n == (long long)n && fabs(n) < 2^53`,
evaluating the `(long long)n` cast (the left conjunct) before the magnitude
guard. For |n| >= 2^63 that float-to-long-long conversion is undefined
behavior (float-cast-overflow, flagged by UBSan/CodeQL). Swap the conjuncts
so the range check short-circuits and guards the cast; behavior for in-range
values is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@InauguralPhysicist
InauguralPhysicist merged commit 9e41730 into InauguralSystems:main Jul 24, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

value_to_string: double->long long cast evaluated before the range check (UB for |n| >= 2^63)

2 participants