summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/attrsets.nix4
-rw-r--r--lib/strings.nix32
-rw-r--r--lib/tests/misc.nix42
3 files changed, 76 insertions, 2 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 72430522f7d8..7d84c25de77a 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -4,7 +4,7 @@
let
inherit (builtins) head tail length;
inherit (lib.trivial) and;
- inherit (lib.strings) concatStringsSep;
+ inherit (lib.strings) concatStringsSep sanitizeDerivationName;
inherit (lib.lists) fold concatMap concatLists;
in
@@ -310,7 +310,7 @@ rec {
path' = builtins.storePath path;
res =
{ type = "derivation";
- name = builtins.unsafeDiscardStringContext (builtins.substring 33 (-1) (baseNameOf path'));
+ name = sanitizeDerivationName (builtins.substring 33 (-1) (baseNameOf path'));
outPath = path';
outputs = [ "out" ];
out = res;
diff --git a/lib/strings.nix b/lib/strings.nix
index 4f9509ffe7c0..7ecd6b143ee8 100644
--- a/lib/strings.nix
+++ b/lib/strings.nix
@@ -678,4 +678,36 @@ rec {
=> "1.0"
*/
fileContents = file: removeSuffix "\n" (builtins.readFile file);
+
+
+ /* Creates a valid derivation name from a potentially invalid one.
+
+ Type: sanitizeDerivationName :: String -> String
+
+ Example:
+ sanitizeDerivationName "../hello.bar # foo"
+ => "-hello.bar-foo"
+ sanitizeDerivationName ""
+ => "unknown"
+ sanitizeDerivationName pkgs.hello
+ => "-nix-store-2g75chlbpxlrqn15zlby2dfh8hr9qwbk-hello-2.10"
+ */
+ sanitizeDerivationName = string: lib.pipe string [
+ # Get rid of string context. This is safe under the assumption that the
+ # resulting string is only used as a derivation name
+ builtins.unsafeDiscardStringContext
+ # Strip all leading "."
+ (x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0)
+ # Split out all invalid characters
+ # https://github.com/NixOS/nix/blob/2.3.2/src/libstore/store-api.cc#L85-L112
+ # https://github.com/NixOS/nix/blob/2242be83c61788b9c0736a92bb0b5c7bbfc40803/nix-rust/src/store/path.rs#L100-L125
+ (builtins.split "[^[:alnum:]+._?=-]+")
+ # Replace invalid character ranges with a "-"
+ (concatMapStrings (s: if lib.isList s then "-" else s))
+ # Limit to 211 characters (minus 4 chars for ".drv")
+ (x: substring (lib.max (stringLength x - 207) 0) (-1) x)
+ # If the result is empty, replace it with "unknown"
+ (x: if stringLength x == 0 then "unknown" else x)
+ ];
+
}
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index 739c5d5fe15d..36ddd186d7b7 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -3,6 +3,23 @@
# if the resulting list is empty, all tests passed
with import ../default.nix;
+let
+
+ testSanitizeDerivationName = { name, expected }:
+ let
+ drv = derivation {
+ name = strings.sanitizeDerivationName name;
+ builder = "x";
+ system = "x";
+ };
+ in {
+ # Evaluate the derivation so an invalid name would be caught
+ expr = builtins.seq drv.drvPath drv.name;
+ inherit expected;
+ };
+
+in
+
runTests {
@@ -490,4 +507,29 @@ runTests {
expected = "'-X' 'PUT' '--data' '{\"id\":0}' '--retry' '3' '--url' 'https://example.com/foo' '--url' 'https://example.com/bar' '--verbose'";
};
+
+ testSanitizeDerivationNameLeadingDots = testSanitizeDerivationName {
+ name = "..foo";
+ expected = "foo";
+ };
+
+ testSanitizeDerivationNameAscii = testSanitizeDerivationName {
+ name = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
+ expected = "-+--.-0123456789-=-?-ABCDEFGHIJKLMNOPQRSTUVWXYZ-_-abcdefghijklmnopqrstuvwxyz-";
+ };
+
+ testSanitizeDerivationNameTooLong = testSanitizeDerivationName {
+ name = "This string is loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong";
+ expected = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong";
+ };
+
+ testSanitizeDerivationNameTooLongWithInvalid = testSanitizeDerivationName {
+ name = "Hello there aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa &&&&&&&&";
+ expected = "there-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-";
+ };
+
+ testSanitizeDerivationNameEmpty = testSanitizeDerivationName {
+ name = "";
+ expected = "unknown";
+ };
}