Skip to content

lib: fix overflowing fromHexString tests and example#433710

Merged
emilazy merged 2 commits intoNixOS:masterfrom
emilazy:push-vzytywkmlnwv
Aug 16, 2025
Merged

lib: fix overflowing fromHexString tests and example#433710
emilazy merged 2 commits intoNixOS:masterfrom
emilazy:push-vzytywkmlnwv

Conversation

@emilazy
Copy link
Member

@emilazy emilazy commented Aug 14, 2025

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 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.

Things done

  • Built on platform:
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • Tested, as applicable:
  • Ran nixpkgs-review on this PR. See nixpkgs-review usage.
  • Tested basic functionality of all binary files, usually in ./result/bin/.
  • Nixpkgs Release Notes
    • Package update: when the change is major or breaking.
  • NixOS Release Notes
    • Module addition: when adding a new NixOS module.
    • Module update: when the change is significant.
  • Fits CONTRIBUTING.md, pkgs/README.md, maintainers/README.md and other READMEs.

Add a 👍 reaction to pull requests you find important.

@emilazy emilazy changed the title lib: fix fromHexString tests and example lib: fix overflowing fromHexString tests and example Aug 14, 2025
@nix-owners nix-owners bot requested review from hsjobeki and infinisil August 14, 2025 15:27
@nixpkgs-ci nixpkgs-ci bot added 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. labels Aug 14, 2025
xokdvium added a commit to xokdvium/nixpkgs that referenced this pull request Aug 14, 2025
This would have allowed us to catch to fromTOML regression in
[1] without waiting for the dogfooding on master, since previously
these tests [2] were not run for the Nix/Lix under test - only the host
nix.

[1]: NixOS/nix#13741
[2]: NixOS#433710
Copy link
Member

@lf- lf- left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh yeah that is ..... a nasty thing to throw into a test in nixpkgs tbh. thanks for fixing it. lossful encoding is not ideal.

@nixpkgs-ci nixpkgs-ci bot added the 12.approvals: 1 This PR was reviewed and approved by one person. label Aug 14, 2025
@flokli
Copy link
Member

flokli commented Aug 14, 2025

CI disagrees:

Error:        error: while parsing TOML: [error] toml::parse_hexadecimal_integer
        --> fromTOML
          |
        1 | v=0x-8000000000000000
          |   ^--- the next token is not an integer
Error: Process completed with exit code 1.

@emilazy
Copy link
Member Author

emilazy commented Aug 14, 2025

Yeah it turns out that this doesn’t handle negative literals at all. Will fix soon.

This was cherry‐picked from
<NixOS#266705> and merged as part of
<NixOS#318712>, 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.
`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]: <https://toml.io/en/v1.0.0#integer>

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:

* <https://nix.dev/manual/nix/stable/release-notes/rl-2.25>
* <https://docs.lix.systems/manual/lix/stable/release-notes/rl-2.91.html#fixes>

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.
@emilazy emilazy force-pushed the push-vzytywkmlnwv branch from 6474066 to 449ad44 Compare August 14, 2025 20:02
@emilazy
Copy link
Member Author

emilazy commented Aug 14, 2025

I’ve fixed that and added some more tests for some really bad behaviour of this function.

@woojiq @Janik-Haag I think it is unfortunate that this was merged as part of #318712, despite the PR it was cherry‐picked from having a blocking review from @infinisil from half a year prior pointing out serious problems with this function. If those had been addressed this wouldn’t be blocking correctness fixes in Nix implementations and an update of our toml11 package, and we wouldn’t have shipped behaviour like lib.fromHexString "1\nwhoops = {}" == 1 as public API in two Nixpkgs releases. Not sure what to do now. I lean towards deprecating the function for eventual removal; its name is inconsistent with other functions like lib.toIntBase10, we would have to make breaking changes anyway to give it reasonable behaviour, and its only in‐tree user restricts the format much more heavily and could have this implementation inlined at no real cost.

@emilazy emilazy mentioned this pull request Aug 14, 2025
13 tasks
@nixpkgs-ci nixpkgs-ci bot added the 6.topic: lib The Nixpkgs function library label Aug 14, 2025
@samos667
Copy link
Contributor

samos667 commented Aug 15, 2025

Maybe I'm off the mark, but why does fromHexString use builtins.fromTOML?
And what is this new lib.network? It doesn't seem to be used anywhere in Nixpkgs, and it's the only thing that depends on fromHexString.
I would like to see network support in Nixpkgs, but it seems to me to be more of a POC than anything else.
A more complete implementation that I personally use is: https://github.com/oddlama/nixos-extra-modules/blob/main/lib/net.nix
based on https://github.com/oddlama/nixos-extra-modules/blob/main/lib/netu.nix for IP parsing.

@woojiq
Copy link
Contributor

woojiq commented Aug 15, 2025

And what is this new lib.network?

Network library that was planned to be implemented as part of the "google summer of code" project. But after implementation I didn't see much activity in pull-requests (no reviews, suggestions, etc), and probably no one really needed it, so it wasn't fully merged and finished.

This happened because of some "political" nixpkgs stuff (that I haven't tried to understand), after which my mentor left the nixpkgs community.

P.S. My bad for not fixing blocking threads in cherry-picked commit. I'll take this as a lesson.

@emilazy
Copy link
Member Author

emilazy commented Aug 16, 2025

And what is this new lib.network? It doesn't seem to be used anywhere in Nixpkgs, and it's the only thing that depends on fromHexString.

It seems like it’s used in the Akkoma module and in a few out‐of‐tree repos, and I don’t see any immediate issues with its interface or implementation. So I think there’s no reason to drop it – it’s providing value to people and not causing any harm.

fromHexString itself is surprisingly popular already. So deprecation/removal is probably not the way. It seems like the callers stick to a sensible (0x)?[0-9A-Fa-f]+ format, so I think that we can follow up after this PR to add a warning for such inputs, and turn them into a throw after a release cycle or so. I won’t put that in this PR, since it wouldn’t be suitable for backport.

Network library that was planned to be implemented as part of the "google summer of code" project. But after implementation I didn't see much activity in pull-requests (no reviews, suggestions, etc), and probably no one really needed it, so it wasn't fully merged and finished.

This happened because of some "political" nixpkgs stuff (that I haven't tried to understand), after which my mentor left the nixpkgs community.

P.S. My bad for not fixing blocking threads in cherry-picked commit. I'll take this as a lesson.

Sorry if you didn’t have a great GSoC experience, and sorry if I came off as a little cranky here! It’s a failure of review processes on our side more than anything; just a matter of figuring out how we can ensure fromHexString behaves sensibly now that people are relying on it. Thankfully I think we can restrict it to a sensible input format and it shouldn’t be too bad a compatibility break. Thanks for your contributions, and it does seem like there are people benefiting from the IPv6 interface you added, including in NixOS itself.

@emilazy
Copy link
Member Author

emilazy commented Aug 16, 2025

BTW, it seems like Snix and Tvix already reject this test due to using a more compliant TOML parser:

note: while evaluating this Nix code
 --> /snixbolt:1:1
  |
1 | (builtins.fromTOML "v=0x${builtins.hashString "sha256" "test"}").v
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
 --> /snixbolt:1:2
  |
1 | (builtins.fromTOML "v=0x${builtins.hashString "sha256" "test"}").v
  |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E035]: Error converting TOML to a Nix value: error in TOML serialization: TOML parse error at line 1, column 3
  |
1 | v=0x9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
  |   ^
number too large to fit in target type

 --> /snixbolt:1:2
  |
1 | (builtins.fromTOML "v=0x${builtins.hashString "sha256" "test"}").v
  |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

and funnily enough, so did 2.3:

nix-repl> (builtins.fromTOML "v=0x${builtins.hashString "sha256" "test"}").v
error: while parsing a TOML string at (string):1:2: Malformed number (out of range: stoll: out of range) at line 1

@emilazy
Copy link
Member Author

emilazy commented Aug 16, 2025

Forgot to reply to this:

Maybe I'm off the mark, but why does fromHexString use builtins.fromTOML?

Because Nix has no native integer parsing functions so we just use TOML and JSON 🫠

Copy link
Contributor

@hsjobeki hsjobeki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems lgtm to me.

Negative numbers such as 0x-8 would need support in nix ideally.

A possible workaround until then could be to detect and strip the negative sign, then apply it afterwards to the result.

We could handle this, now and remove it once it is fixed in nix. I'll leave this up to you, since this is not really related to the fix done in this PR.
Otherwise i'd merge as is.

@nixpkgs-ci nixpkgs-ci bot added 12.approvals: 2 This PR was reviewed and approved by two persons. and removed 12.approvals: 1 This PR was reviewed and approved by one person. labels Aug 16, 2025
@emilazy
Copy link
Member Author

emilazy commented Aug 16, 2025

We could easily support them in this function, but considering its input format is so unintentionally permissive to begin with, I’d rather focus on locking it down for now than expanding it. Not sure what Nix‐side fix you’re referring to?

@emilazy emilazy merged commit 677ccc5 into NixOS:master Aug 16, 2025
28 of 30 checks passed
@emilazy emilazy deleted the push-vzytywkmlnwv branch August 16, 2025 12:25
@nixpkgs-ci
Copy link
Contributor

nixpkgs-ci bot commented Aug 16, 2025

Successfully created backport PR for release-25.05:

@github-actions github-actions bot added the 8.has: port to stable This PR already has a backport to the stable release. label Aug 16, 2025
@emilazy
Copy link
Member Author

emilazy commented Aug 16, 2025

Opened #434218 to follow up on restricting the format here.

emilazy added a commit to emilazy/nixpkgs that referenced this pull request Aug 16, 2025
lf- pushed a commit to lix-project/lix that referenced this pull request Aug 16, 2025
This version changes the handling of TOML timestamps, and throws an
error on out‐of‐range integer literals rather than the previous
saturating behaviour, as required by [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]: <https://toml.io/en/v1.0.0#integer>

The only known use of this is a questionable Nixpkgs test that I have
proposed [a fix] for.

[a fix]: <NixOS/nixpkgs#433710>

Bumping this ahead of Nixpkgs ensures we can test these cases on
HEAD in advance. I presume that the next Lix major version will be
released after 25.05 goes out of support, so it should be fine to
drop support for the old version of toml11.

The co‐authors of this commit are the contributors to the vendored
package definition from Nixpkgs.

Co-authored-by: Anderson Torres <torres.anderson.85@protonmail.com>
Co-authored-by: Artturin <Artturin@artturin.com>
Co-authored-by: Silvan Mosberger <silvan.mosberger@moduscreate.com>
Change-Id: I6a6a69644a188b6e09eee5c9cf91ddd3c81d24ee
nixpkgs-ci bot pushed a commit that referenced this pull request Aug 18, 2025
This would have allowed us to catch to fromTOML regression in
[1] without waiting for the dogfooding on master, since previously
these tests [2] were not run for the Nix/Lix under test - only the host
nix.

[1]: NixOS/nix#13741
[2]: #433710

(cherry picked from commit 67ef265)
arcnmx pushed a commit to arcnmx/nixpkgs-lib that referenced this pull request Aug 29, 2025
This would have allowed us to catch to fromTOML regression in
[1] without waiting for the dogfooding on master, since previously
these tests [2] were not run for the Nix/Lix under test - only the host
nix.

[1]: NixOS/nix#13741
[2]: NixOS/nixpkgs#433710

(cherry picked from commit 67ef2657ff6e3e8ece62a7a08b4231573a052a15)
@emilazy emilazy mentioned this pull request Sep 5, 2025
14 tasks
github-actions bot pushed a commit to yunfachi/nixpkgs.lib that referenced this pull request Oct 28, 2025
This would have allowed us to catch to fromTOML regression in
[1] without waiting for the dogfooding on master, since previously
these tests [2] were not run for the Nix/Lix under test - only the host
nix.

[1]: NixOS/nix#13741
[2]: NixOS/nixpkgs#433710
github-actions bot pushed a commit to yunfachi/nixpkgs.lib that referenced this pull request Oct 28, 2025
sternenseemann pushed a commit to sternenseemann/nix-lang-tests that referenced this pull request Feb 25, 2026
This version changes the handling of TOML timestamps, and throws an
error on out‐of‐range integer literals rather than the previous
saturating behaviour, as required by [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]: <https://toml.io/en/v1.0.0#integer>

The only known use of this is a questionable Nixpkgs test that I have
proposed [a fix] for.

[a fix]: <NixOS/nixpkgs#433710>

Bumping this ahead of Nixpkgs ensures we can test these cases on
HEAD in advance. I presume that the next Lix major version will be
released after 25.05 goes out of support, so it should be fine to
drop support for the old version of toml11.

The co‐authors of this commit are the contributors to the vendored
package definition from Nixpkgs.

Co-authored-by: Anderson Torres <torres.anderson.85@protonmail.com>
Co-authored-by: Artturin <Artturin@artturin.com>
Co-authored-by: Silvan Mosberger <silvan.mosberger@moduscreate.com>
Change-Id: I6a6a69644a188b6e09eee5c9cf91ddd3c81d24ee
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

6.topic: lib The Nixpkgs function library 8.has: port to stable This PR already has a backport to the stable release. 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 12.approvals: 2 This PR was reviewed and approved by two persons.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants