-
Notifications
You must be signed in to change notification settings - Fork 7
Open
Description
Description
format64_to_fixed panics in debug builds (and has UB in release builds) when rounding causes a carry that propagates through all integer digits (e.g., 9.5 with toFixed(0) should produce "10").
Reproducer
Using Boa (which calls ryu_js::Buffer::format_to_fixed):
(9.5).toFixed(0) // panics (expected: "10")
(99.5).toFixed(0) // panics (expected: "100")Panic
assertion failed: (0..self.len).contains(&i)
Location: ryu-js-1.0.2/src/pretty/to_fixed/mod.rs:225
Root Cause
In the rounding loop at the end of format64_to_fixed (line ~621), result.get(round_index) is called before checking round_index == -1:
round_index -= 1;
let c = result.get(round_index); // reads buffer[-1] when round_index is -1
if round_index == -1 || c == b'-' { // check happens AFTER the readWhen all integer digits are 9, the carry turns each to 0 and round_index reaches -1. The next result.get(-1) is an out-of-bounds read.
Negative numbers are unaffected because '-' at index 0 stops the loop before round_index can underflow.
Fix
Move the boundary check before the read:
loop {
round_index -= 1;
if round_index == -1 {
result.set(0, b'1');
if dot_index > 0 {
result.set(dot_index, b'0');
result.set(dot_index + 1, b'.');
}
result.append_byte(b'0');
break;
}
let c = result.get(round_index);
if c == b'-' {
result.set(round_index + 1, b'1');
if dot_index > 0 {
result.set(dot_index, b'0');
result.set(dot_index + 1, b'.');
}
result.append_byte(b'0');
break;
}
// ... rest unchanged
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels