about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorJacob Abel <jacobabel@nullpo.dev>2022-05-23 03:39:48 -0400
committerJacob Abel <jacobabel@nullpo.dev>2022-10-23 17:50:23 -0400
commit3d196a5f2a72595b14c439a9b4aba7737c0f1ebe (patch)
tree48c839f091c9f1c56ad2bc041150201b87a3c64c /lib
parentfebff1dccd2c173472fe4a6bed2e620429c5b1ba (diff)
downloadnixlib-3d196a5f2a72595b14c439a9b4aba7737c0f1ebe.tar
nixlib-3d196a5f2a72595b14c439a9b4aba7737c0f1ebe.tar.gz
nixlib-3d196a5f2a72595b14c439a9b4aba7737c0f1ebe.tar.bz2
nixlib-3d196a5f2a72595b14c439a9b4aba7737c0f1ebe.tar.lz
nixlib-3d196a5f2a72595b14c439a9b4aba7737c0f1ebe.tar.xz
nixlib-3d196a5f2a72595b14c439a9b4aba7737c0f1ebe.tar.zst
nixlib-3d196a5f2a72595b14c439a9b4aba7737c0f1ebe.zip
lib/strings: Update toInt to handle intermixed ws and zeros. Added tests
Diffstat (limited to 'lib')
-rw-r--r--lib/strings.nix20
-rw-r--r--lib/tests/misc.nix11
-rwxr-xr-xlib/tests/modules.sh2
3 files changed, 25 insertions, 8 deletions
diff --git a/lib/strings.nix b/lib/strings.nix
index 8f3568fc1fc5..c6269e755e2a 100644
--- a/lib/strings.nix
+++ b/lib/strings.nix
@@ -802,16 +802,22 @@ rec {
   # Obviously, it is a bit hacky to use fromJSON this way.
   toInt = str:
     let
-      strippedInput = match "[[:space:]]*(0*)(.*)" str;
-      isNonZeroEmpty = match "[[:space:]]*" (lib.last strippedInput) == [];
-      isZeroNonEmpty = head strippedInput != "";
-      mayBeInt = fromJSON (lib.last strippedInput);
+      # RegEx: Match any leading whitespace, then any zero padding, and capture any remaining
+      # digits after that, and finally match any trailing whitespace.
+      strippedInput = match "[[:space:]]*0*([[:digit:]]+)[[:space:]]*" str;
+
+      # RegEx: Match any leading whitespace, at least one '0', and any trailing whitespace.
+      isZero = match "[[:space:]]*0+[[:space:]]*" str == [];
+
+      # Attempt to parse input
+      parsedInput = fromJSON (elemAt strippedInput 0);
     in
-      if isNonZeroEmpty && isZeroNonEmpty
+      # Value is zero
+      if isZero
       then 0
       else
-      if isInt mayBeInt
-      then mayBeInt
+      if strippedInput != null && isInt parsedInput
+      then parsedInput
       else throw "Could not convert ${str} to int.";
 
   /* Read a list of paths from `file`, relative to the `rootPath`.
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index ef4483219f7e..97d53026c644 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -355,6 +355,17 @@ runTests {
     (0 == toInt " 000000 ")
   ];
 
+  testToIntFails = testAllTrue [
+    ( builtins.tryEval (toInt "") == { success = false; value = false; } )
+    ( builtins.tryEval (toInt "123 123") == { success = false; value = false; } )
+    ( builtins.tryEval (toInt "0 123") == { success = false; value = false; } )
+    ( builtins.tryEval (toInt " 0d ") == { success = false; value = false; } )
+    ( builtins.tryEval (toInt " foo ") == { success = false; value = false; } )
+    ( builtins.tryEval (toInt " foo 123 ") == { success = false; value = false; } )
+    ( builtins.tryEval (toInt " foo 00123 ") == { success = false; value = false; } )
+    ( builtins.tryEval (toInt " foo00123 ") == { success = false; value = false; } )
+  ];
+
 # LISTS
 
   testFilter = {
diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh
index 2be9b5835090..f6298297d136 100755
--- a/lib/tests/modules.sh
+++ b/lib/tests/modules.sh
@@ -162,7 +162,7 @@ checkConfigError 'A definition for option .* is not.*string or signed integer co
 # Check coerced value with unsound coercion
 checkConfigOutput '^12$' config.value ./declare-coerced-value-unsound.nix
 checkConfigError 'A definition for option .* is not of type .*. Definition values:\n\s*- In .*: "1000"' config.value ./declare-coerced-value-unsound.nix ./define-value-string-bigint.nix
-checkConfigError 'json.exception.parse_error' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
+checkConfigError 'Could not convert .* to int.' config.value ./declare-coerced-value-unsound.nix ./define-value-string-arbitrary.nix
 
 # Check mkAliasOptionModule.
 checkConfigOutput '^true$' config.enable ./alias-with-priority.nix