diff --git a/doc/manual/rl-next/json-number-overflow.md b/doc/manual/rl-next/json-number-overflow.md new file mode 100644 index 000000000..27850364a --- /dev/null +++ b/doc/manual/rl-next/json-number-overflow.md @@ -0,0 +1,16 @@ +--- +synopsis: Parse overflowing JSON number literals as floating‐point +issues: [] +cls: [3919] +category: "Fixes" +credits: [emilazy] +--- + +Previously, `builtins.fromJSON "-9223372036854775809"` would +return a floating‐point number, while `builtins.fromJSON +"9223372036854775808"` would cause an evaluation error. This was +introduced with the banning of integer overflow in Lix 2.91; previously +the latter would result in C++ undefined behaviour. These cases are +now treated consistently with JSON’s model of a single numeric type, +and JSON number literals that do not fit in a Nix‐language integer +will be parsed as floating‐point numbers. diff --git a/lix/libexpr/json-to-value.cc b/lix/libexpr/json-to-value.cc index caddd0366..58c91a0bd 100644 --- a/lix/libexpr/json-to-value.cc +++ b/lix/libexpr/json-to-value.cc @@ -108,7 +108,9 @@ public: bool number_unsigned(number_unsigned_t val_) override { if (val_ > std::numeric_limits::max()) { - throw Error("unsigned json number %1% outside of Nix integer range", val_); + // Parse as a float for consistency with signed integers + // and interoperability with JSON’s single numeric type. + return number_float(static_cast(val_), ""); } NixInt::Inner val = val_; rs->value(state).mkInt(val); diff --git a/tests/functional2/lang/fromJSON-overflowing/eval-fail-overflow.err.exp b/tests/functional2/lang/fromJSON-overflowing/eval-fail-overflow.err.exp deleted file mode 100644 index 49b8bf8b7..000000000 --- a/tests/functional2/lang/fromJSON-overflowing/eval-fail-overflow.err.exp +++ /dev/null @@ -1,8 +0,0 @@ -error: - … while calling the 'fromJSON' builtin - at /pwd/in.nix:1:1: - 1| builtins.fromJSON ''{"attr": 18446744073709551615}'' - | ^ - 2| - - error: unsigned json number 18446744073709551615 outside of Nix integer range diff --git a/tests/functional2/lang/fromJSON-overflowing/eval-okay-overflow.out.exp b/tests/functional2/lang/fromJSON-overflowing/eval-okay-overflow.out.exp new file mode 100644 index 000000000..deb1ba3b1 --- /dev/null +++ b/tests/functional2/lang/fromJSON-overflowing/eval-okay-overflow.out.exp @@ -0,0 +1 @@ +{ attr = 1.84467e+19; }