Skip to content

Panic in format64_to_fixed when rounding carries past all integer digits #55

@Ansh-699

Description

@Ansh-699

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 read

When 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
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    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