diff --git a/doc/manual/rl-next/toml-number-overflow.md b/doc/manual/rl-next/toml-number-overflow.md new file mode 100644 index 000000000..1522213cb --- /dev/null +++ b/doc/manual/rl-next/toml-number-overflow.md @@ -0,0 +1,14 @@ +--- +synopsis: Reject overflowing TOML integer literals +issues: [] +cls: [3916] +category: "Breaking Changes" +credits: [emilazy] +--- + +The toml11 library used by Lix was updated. The new +version aligns with the [TOML v1.0.0 specification’s +requirement](https://toml.io/en/v1.0.0#integer) to reject integer +literals that cannot be losslessly parsed. This means that code like +`builtins.fromTOML "v=0x8000000000000000"` will now produce an error +rather than silently saturating the integer result. diff --git a/lix/libexpr/primops/fromTOML.cc b/lix/libexpr/primops/fromTOML.cc index 32edbb3ac..a66ccfb4e 100644 --- a/lix/libexpr/primops/fromTOML.cc +++ b/lix/libexpr/primops/fromTOML.cc @@ -6,8 +6,6 @@ namespace nix { -#if HAVE_TOML11_4 - /** * This is what toml11 < 4.0 did when choosing the subsecond precision. * TOML 1.0.0 spec doesn't define how sub-millisecond ranges should be handled and calls it @@ -82,8 +80,6 @@ static void normalizeDatetimeFormat(toml::value & t) } } -#endif - void prim_fromTOML(EvalState & state, Value ** args, Value & val) { auto toml = state.forceStringNoCtx( @@ -130,9 +126,7 @@ void prim_fromTOML(EvalState & state, Value ** args, Value & val) case toml::value_t::local_date: case toml::value_t::local_time: { if (experimentalFeatureSettings.isEnabled(Xp::ParseTomlTimestamps)) { -#if HAVE_TOML11_4 normalizeDatetimeFormat(t); -#endif auto attrs = state.ctx.buildBindings(2); attrs.alloc("_type").mkString("timestamp"); std::ostringstream s; @@ -155,13 +149,10 @@ void prim_fromTOML(EvalState & state, Value ** args, Value & val) val, toml::parse( tomlStream, - "fromTOML" /* the "filename" */ -#if HAVE_TOML11_4 - , + "fromTOML", /* the "filename" */ toml::spec::v( 1, 0, 0 ) // Be explicit that we are parsing TOML 1.0.0 without extensions -#endif ) ); } catch (std::exception & e) { // NOLINT(lix-foreign-exceptions) // TODO: toml::syntax_error diff --git a/meson.build b/meson.build index 666743e26..242d8f762 100644 --- a/meson.build +++ b/meson.build @@ -365,10 +365,7 @@ gtest = [ dependency('gmock_main', required : enable_tests, include_type : 'system'), ] -toml11 = dependency('toml11', version : '>=3.7.0', required : true, method : 'cmake', include_type : 'system') -configdata += { - 'HAVE_TOML11_4': toml11.version().version_compare('>= 4.0.0').to_int(), -} +toml11 = dependency('toml11', version : '>=4.0.0', required : true, method : 'cmake', include_type : 'system') pegtl = dependency( 'pegtl', diff --git a/misc/toml11.nix b/misc/toml11.nix new file mode 100644 index 000000000..c53be3da1 --- /dev/null +++ b/misc/toml11.nix @@ -0,0 +1,47 @@ +{ + lib, + stdenv, + fetchFromGitHub, + cmake, +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "toml11"; + version = "4.4.0"; + + src = fetchFromGitHub { + owner = "ToruNiina"; + repo = "toml11"; + rev = "v${finalAttrs.version}"; + hash = "sha256-sgWKYxNT22nw376ttGsTdg0AMzOwp8QH3E8mx0BZJTQ="; + }; + + nativeBuildInputs = [ + cmake + ]; + + meta = with lib; { + homepage = "https://github.com/ToruNiina/toml11"; + description = "TOML for Modern C++"; + longDescription = '' + toml11 is a C++11 (or later) header-only toml parser/encoder depending + only on C++ standard library. + + - It is compatible to the latest version of TOML v1.0.0. + - It is one of the most TOML standard compliant libraries, tested with + the language agnostic test suite for TOML parsers by BurntSushi. + - It shows highly informative error messages. + - It has configurable container. You can use any random-access containers + and key-value maps as backend containers. + - It optionally preserves comments without any overhead. + - It has configurable serializer that supports comments, inline tables, + literal strings and multiline strings. + - It supports user-defined type conversion from/into toml values. + - It correctly handles UTF-8 sequences, with or without BOM, both on posix + and Windows. + ''; + license = licenses.mit; + maintainers = with maintainers; [ ]; + platforms = platforms.unix ++ platforms.windows; + }; +}) diff --git a/package.nix b/package.nix index 4d0a35060..cb393c114 100644 --- a/package.nix +++ b/package.nix @@ -56,6 +56,8 @@ rustc, sqlite, systemtap-lix ? __forDefaults.systemtap-lix, + # FIXME: remove default after dropping NixOS 25.05 + toml11-lix ? __forDefaults.toml11-lix, toml11, util-linuxMinimal ? utillinuxMinimal, utillinuxMinimal ? null, @@ -116,6 +118,9 @@ build-release-notes = callPackage ./maintainers/build-release-notes.nix { }; passt-lix = callPackage ./misc/passt.nix { }; + + toml11-lix = + if lib.versionOlder toml11.version "4.4.0" then callPackage ./misc/toml11.nix { } else toml11; }, }: @@ -336,7 +341,7 @@ stdenv.mkDerivation (finalAttrs: { boost lowdown libsodium - toml11 + toml11-lix pegtl capnproto dtrace-headers diff --git a/tests/functional2/lang/fromTOML-overflowing/eval-fail-overflow.err.exp b/tests/functional2/lang/fromTOML-overflowing/eval-fail-overflow.err.exp new file mode 100644 index 000000000..0c90e85ed --- /dev/null +++ b/tests/functional2/lang/fromTOML-overflowing/eval-fail-overflow.err.exp @@ -0,0 +1,13 @@ +error: + … while calling the 'fromTOML' builtin + at /pwd/in.nix:1:1: + 1| builtins.fromTOML ''attr = 9223372036854775808'' + | ^ + 2| + + error: while parsing TOML: [error] toml::parse_dec_integer: too large integer: current max digits = 2^63 + --> fromTOML + | + 1 | attr = 9223372036854775808 + | ^-- must be < 2^63 + diff --git a/tests/functional2/lang/fromTOML-overflowing/eval-fail-underflow.err.exp b/tests/functional2/lang/fromTOML-overflowing/eval-fail-underflow.err.exp new file mode 100644 index 000000000..a287e1865 --- /dev/null +++ b/tests/functional2/lang/fromTOML-overflowing/eval-fail-underflow.err.exp @@ -0,0 +1,13 @@ +error: + … while calling the 'fromTOML' builtin + at /pwd/in.nix:1:1: + 1| builtins.fromTOML ''attr = -9223372036854775809'' + | ^ + 2| + + error: while parsing TOML: [error] toml::parse_dec_integer: too large integer: current max digits = 2^63 + --> fromTOML + | + 1 | attr = -9223372036854775809 + | ^-- must be < 2^63 + diff --git a/tests/functional2/lang/fromTOML-overflowing/eval-okay-overflow.out.exp b/tests/functional2/lang/fromTOML-overflowing/eval-okay-overflow.out.exp deleted file mode 100644 index e241ca9ba..000000000 --- a/tests/functional2/lang/fromTOML-overflowing/eval-okay-overflow.out.exp +++ /dev/null @@ -1 +0,0 @@ -{ attr = 9223372036854775807; } diff --git a/tests/functional2/lang/fromTOML-overflowing/eval-okay-underflow.out.exp b/tests/functional2/lang/fromTOML-overflowing/eval-okay-underflow.out.exp deleted file mode 100644 index 83b822591..000000000 --- a/tests/functional2/lang/fromTOML-overflowing/eval-okay-underflow.out.exp +++ /dev/null @@ -1 +0,0 @@ -{ attr = -9223372036854775808; }