From b591001250842aa1ae470523d45274243926a853 Mon Sep 17 00:00:00 2001 From: Emily Date: Thu, 14 Aug 2025 20:57:04 +0100 Subject: [PATCH 1/2] lib: add `fromHexString` tests for distressing behaviour MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was cherry‐picked from and merged as part of , despite there being a blocking review on the former pointing out these kinds of issues. This documents some of the dodgy behaviour. It also can’t handle negative literals. It might be worth considering deprecating and dropping this, by inlining it into `lib.network.ipv6.fromString`, its only in‐tree user. (cherry picked from commit 6673e05ad065b0f2388c94cc3b3445f9f7da780e) --- lib/tests/misc.nix | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 99b335cdb295f..8fd02e49cded3 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -390,6 +390,30 @@ runTests { expected = 15; }; + # FIXME: This might be bad and should potentially be deprecated. + testFromHexStringQuestionableMixedCase = { + expr = fromHexString "eEeEe"; + expected = 978670; + }; + + # FIXME: This is probably bad and should potentially be deprecated. + testFromHexStringQuestionableUnderscore = { + expr = fromHexString "F_f"; + expected = 255; + }; + + # FIXME: This is definitely bad and should be deprecated. + testFromHexStringBadComment = { + expr = fromHexString "0 # oops"; + expected = 0; + }; + + # FIXME: Oh my god. + testFromHexStringAwfulInjection = { + expr = fromHexString "1\nwhoops = {}"; + expected = 1; + }; + testToBaseDigits = { expr = toBaseDigits 2 6; expected = [ From fce01f7d71457982563557b4dac3d24e91ba40eb Mon Sep 17 00:00:00 2001 From: Emily Date: Thu, 14 Aug 2025 15:41:55 +0100 Subject: [PATCH 2/2] lib: fix overflowing `fromHexString` tests and example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `fromHexString` is backed by `builtins.fromTOML`. Per [the TOML v1.0.0 specification]: > Arbitrary 64-bit signed integers (from −2^63 to 2^63−1) should be > accepted and handled losslessly. If an integer cannot be represented > losslessly, an error must be thrown. [the TOML v1.0.0 specification]: The saturating behaviour of the toml11 version currently used by Nix is not lossless, and is therefore a violation of the TOML specification. We should not be relying on it. This blocks the update of toml11, as it became stricter about reporting this condition. This, yes, is arguably an evaluation compatibility break. However, integer overflow was recently explicitly defined as an error by both Nix and Lix, as opposed to the C++ undefined behaviour it was previously implemented as: * * This included changing `builtins.fromJSON` to explicitly reject overflowing integer literals. I believe that the case for `builtins.fromTOML` is comparable, and that we are effectively testing undefined behaviour in TOML and the Nix language here, in the same way that we would have been if we had tests relying on overflowing integer arithmetic. I am not aware of any use of this behaviour outside of these tests; the reverted toml11 bump in Nix did not break the 23.11 evaluation regression test, for example. C++ undefined behaviour is not involved here, as toml11 used the C++ formatted input functions that are specified to saturate on invalid values. But it’s still a violation of the TOML specification caused by insufficient error checking in the old version of the library, and inconsistent with the handling of overflowing literals in the rest of Nix. Let’s fix this so that Nix implementations can correctly flag up this error and we can unblock the toml11 update. (cherry picked from commit 449ad44f163198718caaf8bc89080e6187418dc9) --- lib/tests/misc.nix | 5 +++-- lib/trivial.nix | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 8fd02e49cded3..a44561fb1e691 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -380,8 +380,9 @@ runTests { expected = 255; }; - testFromHexStringSecondExample = { - expr = fromHexString (builtins.hashString "sha256" "test"); + # Highest supported integer value in Nix. + testFromHexStringMaximum = { + expr = fromHexString "7fffffffffffffff"; expected = 9223372036854775807; }; diff --git a/lib/trivial.nix b/lib/trivial.nix index eba6dd69b12e3..ada83b8fb4bef 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -1114,7 +1114,7 @@ in fromHexString "FF" => 255 - fromHexString (builtins.hashString "sha256" "test") + fromHexString "0x7fffffffffffffff" => 9223372036854775807 ``` */