Unverified Commit 70dab284 authored by Robert Hensing's avatar Robert Hensing Committed by GitHub
Browse files

Merge pull request #208168 from hercules-ci/lib-types-string-coercions

`types.path`: Do not allow lists of strings
parents 1ca08d4c cb98e26a
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ let

    inherit (builtins) add addErrorContext attrNames concatLists
      deepSeq elem elemAt filter genericClosure genList getAttr
      hasAttr head isAttrs isBool isInt isList isString length
      hasAttr head isAttrs isBool isInt isList isPath isString length
      lessThan listToAttrs pathExists readFile replaceStrings seq
      stringLength sub substring tail trace;
    inherit (self.trivial) id const pipe concat or and bitAnd bitOr bitXor
@@ -96,14 +96,16 @@ let
      concatImapStringsSep makeSearchPath makeSearchPathOutput
      makeLibraryPath makeBinPath optionalString
      hasInfix hasPrefix hasSuffix stringToCharacters stringAsChars escape
      escapeShellArg escapeShellArgs isValidPosixName toShellVar toShellVars
      escapeShellArg escapeShellArgs
      isStorePath isStringLike
      isValidPosixName toShellVar toShellVars
      escapeRegex escapeXML replaceChars lowerChars
      upperChars toLower toUpper addContextFrom splitString
      removePrefix removeSuffix versionOlder versionAtLeast
      getName getVersion
      mesonOption mesonBool mesonEnable
      nameFromURL enableFeature enableFeatureAs withFeature
      withFeatureAs fixedWidthString fixedWidthNumber isStorePath
      withFeatureAs fixedWidthString fixedWidthNumber
      toInt toIntBase10 readPathsFromFile fileContents;
    inherit (self.stringsWithDeps) textClosureList textClosureMap
      noDepEntry fullDepEntry packEntry stringAfter;
+28 −6
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ rec {
    isInt
    isList
    isAttrs
    isPath
    isString
    match
    parseDrvName
@@ -395,7 +396,7 @@ rec {
  */
  toShellVar = name: value:
    lib.throwIfNot (isValidPosixName name) "toShellVar: ${name} is not a valid shell variable name" (
    if isAttrs value && ! isCoercibleToString value then
    if isAttrs value && ! isStringLike value then
      "declare -A ${name}=(${
        concatStringsSep " " (lib.mapAttrsToList (n: v:
          "[${escapeShellArg n}]=${escapeShellArg v}"
@@ -798,10 +799,31 @@ rec {
  in lib.warnIf (!precise) "Imprecise conversion from float to string ${result}"
    result;

  /* Check whether a value can be coerced to a string */
  isCoercibleToString = x:
    elem (typeOf x) [ "path" "string" "null" "int" "float" "bool" ] ||
    (isList x && lib.all isCoercibleToString x) ||
  /* Soft-deprecated function. While the original implementation is available as
     isConvertibleWithToString, consider using isStringLike instead, if suitable. */
  isCoercibleToString = lib.warnIf (lib.isInOldestRelease 2305)
    "lib.strings.isCoercibleToString is deprecated in favor of either isStringLike or isConvertibleWithToString. Only use the latter if it needs to return true for null, numbers, booleans and list of similarly coercibles."
    isConvertibleWithToString;

  /* Check whether a list or other value can be passed to toString.

     Many types of value are coercible to string this way, including int, float,
     null, bool, list of similarly coercible values.
  */
  isConvertibleWithToString = x:
    isStringLike x ||
    elem (typeOf x) [ "null" "int" "float" "bool" ] ||
    (isList x && lib.all isConvertibleWithToString x);

  /* Check whether a value can be coerced to a string.
     The value must be a string, path, or attribute set.

     String-like values can be used without explicit conversion in
     string interpolations and in most functions that expect a string.
   */
  isStringLike = x:
    isString x ||
    isPath x ||
    x ? outPath ||
    x ? __toString;

@@ -818,7 +840,7 @@ rec {
       => false
  */
  isStorePath = x:
    if !(isList x) && isCoercibleToString x then
    if isStringLike x then
      let str = toString x; in
      substring 0 1 str == "/"
      && dirOf str == storeDir
+3 −3
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ let
    concatStringsSep
    escapeNixString
    hasInfix
    isCoercibleToString
    isStringLike
    ;
  inherit (lib.trivial)
    boolToString
@@ -227,7 +227,7 @@ rec {
      merge = loc: defs:
        let
          getType = value:
            if isAttrs value && isCoercibleToString value
            if isAttrs value && isStringLike value
            then "stringCoercibleSet"
            else builtins.typeOf value;

@@ -479,7 +479,7 @@ rec {
    path = mkOptionType {
      name = "path";
      descriptionClass = "noun";
      check = x: isCoercibleToString x && builtins.substring 0 1 (toString x) == "/";
      check = x: isStringLike x && builtins.substring 0 1 (toString x) == "/";
      merge = mergeEqualOption;
    };

+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ let
        else if isDerivation v then toString v
        else if builtins.isPath v then toString v
        else if isString v then v
        else if strings.isCoercibleToString v then toString v
        else if strings.isConvertibleWithToString v then toString v
        else abort "The nix conf value: ${toPretty {} v} can not be encoded";

      mkKeyValue = k: v: "${escape [ "=" ] k} = ${mkValueString v}";
+1 −1
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ let
    in
    lib.concatStrings (lib.mapAttrsToList toArg args);

  isPathType = x: lib.strings.isCoercibleToString x && builtins.substring 0 1 (toString x) == "/";
  isPathType = x: lib.types.path.check x;

in
{