diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 50f9828..0e06a44 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -2,6 +2,15 @@ === [Unreleased] +==== Fixed — JCS numbers on decimal ties + +* `+ijson-jcs+` is bumped from 3a9a4ee to 03df9ed, which formats numbers with +`+ryu-js+` (ECMAScript `+Number::toString+`). The old pin printed RFC 8785 +Appendix B vector 0x43143ff3c1cb0959 as `+1424953923781206.3+`; JCS requires +`+1424953923781206.2+` (ties to even). Any report or attestation holding such a +float now hashes to the value other JCS implementations compute. A test in +`+crate::json+` pins the vector. + ==== Fixed — KYAML keys holding a line separator * KYAML output now escapes U+2028 (LS) and U+2029 (PS) as `+\uXXXX+`, as it diff --git a/Cargo.lock b/Cargo.lock index d10e538..e223d5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2212,8 +2212,9 @@ dependencies = [ [[package]] name = "ijson-jcs" version = "0.1.0" -source = "git+https://github.com/hyperpolymath/ijson-jcs?rev=3a9a4ee326a968a32b2f152b4faec243a2d00765#3a9a4ee326a968a32b2f152b4faec243a2d00765" +source = "git+https://github.com/hyperpolymath/ijson-jcs?rev=03df9ed20c1a2e1d6d913b8b20cf0874651bb61a#03df9ed20c1a2e1d6d913b8b20cf0874651bb61a" dependencies = [ + "ryu-js", "serde", "serde_json", "thiserror 2.0.18", @@ -3708,6 +3709,12 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "ryu-js" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04d056b875a9d2e6cb9a61d127afee9ac5999b9f87bcb32079d1318e505be714" + [[package]] name = "same-file" version = "1.0.6" diff --git a/Cargo.toml b/Cargo.toml index a412e58..f6c0545 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" # JCS (RFC 8785) for JSON artefacts: the estate tool behind JSON-POLICY rule # J-1. Not on crates.io, so pinned to a full commit SHA. -ijson-jcs = { git = "https://github.com/hyperpolymath/ijson-jcs", rev = "3a9a4ee326a968a32b2f152b4faec243a2d00765" } +ijson-jcs = { git = "https://github.com/hyperpolymath/ijson-jcs", rev = "03df9ed20c1a2e1d6d913b8b20cf0874651bb61a" } # Pure safe-Rust YAML (replaces serde_yaml + unsafe-libyaml, RUSTSEC-2024-0449). serde-saphyr = "2.0" regex = "1.10" diff --git a/src/json.rs b/src/json.rs index b6a7c2d..65eb5a4 100644 --- a/src/json.rs +++ b/src/json.rs @@ -61,6 +61,14 @@ mod tests { ); } + #[test] + fn numbers_follow_rfc_8785_on_decimal_ties() { + // RFC 8785 Appendix B: binary64 0x43143ff3c1cb0959 must print as + // ECMAScript does, choosing the even digit on a decimal tie. + let tie = f64::from_bits(0x4314_3ff3_c1cb_0959); + assert_eq!(to_canonical_string(&tie).unwrap(), "1424953923781206.2\n"); + } + #[test] fn rejects_integers_outside_i_json_range() { // I-JSON safe integers: [-(2^53 - 1), 2^53 - 1].