Skip to content

JsonStreamWriter emits an f64 >= 1e100 that its own reader rejects #183

Description

@hey-jj

JsonStreamWriter::fp_number_value writes a large-magnitude f64 as a plain-decimal number with more than 100 characters. JsonStreamReader with default settings rejects any number whose text is longer than 100 characters or whose exponent exceeds 99, so a value the writer produced cannot be read back by a reader from the same crate with default settings.

Reproduced on struson 0.7.2 from crates.io, default features.

struson = "0.7.2"

Reproducer

use struson::reader::{JsonReader, JsonStreamReader};
use struson::writer::{JsonStreamWriter, JsonWriter};

fn main() {
    let mut buf: Vec<u8> = Vec::new();
    let mut w = JsonStreamWriter::new(&mut buf);
    w.fp_number_value(1e100_f64).unwrap();
    w.finish_document().unwrap();

    let s = String::from_utf8(buf).unwrap();
    println!("written length = {}", s.len());

    let mut r = JsonStreamReader::new(s.as_bytes());
    let read: Result<Result<f64, _>, _> = r.next_number::<f64>();
    println!("read back = {:?}", read);
}

Observed

written length = 101
read back = Err(unsupported number value '100000...000' at path '$')

fp_number_value calls to_string on the f64, and 1e100_f64.to_string() is a 101-character plain-decimal string. The default reader returns ReaderError::UnsupportedNumberValue for it. Larger magnitudes such as 5e120 behave the same way.

Expected

A finite f64 written by the crate's own writer with default settings can be read back by the crate's own reader with default settings. Either the writer emits scientific notation for large magnitudes so the text stays short, or the writer and the default reader agree on the same size bound.

Scope

A pipeline that serializes with JsonStreamWriter and later reads with JsonStreamReader, both at defaults, fails on ordinary large f64 values such as physics or finance magnitudes at or above 1e100. The failure surfaces only at read time and only for large inputs, so it is easy to miss in testing.

Root cause

fp_number_value for a finite float uses self.to_string() (src/writer/mod.rs around line 779), which never uses scientific notation and grows without bound for large magnitudes. The default reader sets restrict_number_values: true (src/reader/stream_reader.rs around line 366), which rejects text longer than 100 characters or an exponent above 99. The two defaults disagree on the same value.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions