aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/src/language/advanced-attributes.md6
-rw-r--r--package.nix16
-rw-r--r--src/libexpr/eval.cc14
-rw-r--r--src/libexpr/eval.hh13
-rw-r--r--src/libexpr/parser/parser.cc6
-rw-r--r--src/libexpr/parser/state.hh1
-rw-r--r--src/libexpr/primops.cc14
-rw-r--r--src/libstore/build/local-derivation-goal.cc18
-rw-r--r--tests/functional/lang/eval-okay-derivation-legacy.err.exp6
-rw-r--r--tests/functional/lang/eval-okay-derivation-legacy.exp1
-rw-r--r--tests/functional/lang/eval-okay-derivation-legacy.nix12
-rw-r--r--tests/unit/libexpr-support/tests/libexpr.hh4
-rw-r--r--tests/unit/libexpr/trivial.cc17
13 files changed, 107 insertions, 21 deletions
diff --git a/doc/manual/src/language/advanced-attributes.md b/doc/manual/src/language/advanced-attributes.md
index e9006a3ae..ee93f5672 100644
--- a/doc/manual/src/language/advanced-attributes.md
+++ b/doc/manual/src/language/advanced-attributes.md
@@ -292,6 +292,12 @@ Derivations can declare some infrequently used optional attributes.
(associative) arrays. For example, the attribute `hardening.format = true`
ends up as the Bash associative array element `${hardening[format]}`.
+ > **Warning**
+ >
+ > If set to `true`, other advanced attributes such as [`allowedReferences`](#adv-attr-allowedReferences), [`allowedReferences`](#adv-attr-allowedReferences), [`allowedRequisites`](#adv-attr-allowedRequisites),
+ [`disallowedReferences`](#adv-attr-disallowedReferences) and [`disallowedRequisites`](#adv-attr-disallowedRequisites), maxSize, and maxClosureSize.
+ will have no effect.
+
- [`outputChecks`]{#adv-attr-outputChecks}\
When using [structured attributes](#adv-attr-structuredAttrs), the `outputChecks`
attribute allows defining checks per-output.
diff --git a/package.nix b/package.nix
index 0f006fef4..be2f0010d 100644
--- a/package.nix
+++ b/package.nix
@@ -58,8 +58,11 @@
buildUnreleasedNotes ? true,
internalApiDocs ? false,
+ # Support garbage collection in the evaluator.
+ enableGC ? sanitize == null || !builtins.elem "address" sanitize,
# List of Meson sanitize options. Accepts values of b_sanitize, e.g.
# "address", "undefined", "thread".
+ # Enabling the "address" sanitizer will disable garbage collection in the evaluator.
sanitize ? null,
# Turn compiler warnings into errors.
werror ? false,
@@ -118,10 +121,7 @@ let
# The internal API docs need these for the build, but if we're not building
# Nix itself, then these don't need to be propagated.
- maybePropagatedInputs = [
- boehmgc-nix
- nlohmann_json
- ];
+ maybePropagatedInputs = lib.optional enableGC boehmgc-nix ++ [ nlohmann_json ];
# .gitignore has already been processed, so any changes in it are irrelevant
# at this point. It is not represented verbatim for test purposes because
@@ -179,10 +179,9 @@ stdenv.mkDerivation (finalAttrs: {
mesonFlags =
let
- sanitizeOpts = lib.optionals (sanitize != null) (
- [ "-Db_sanitize=${builtins.concatStringsSep "," sanitize}" ]
- ++ lib.optional (builtins.elem "address" sanitize) "-Dgc=disabled"
- );
+ sanitizeOpts = lib.optional (
+ sanitize != null
+ ) "-Db_sanitize=${builtins.concatStringsSep "," sanitize}";
in
lib.optionals hostPlatform.isLinux [
# You'd think meson could just find this in PATH, but busybox is in buildInputs,
@@ -196,6 +195,7 @@ stdenv.mkDerivation (finalAttrs: {
# mesonConfigurePhase automatically passes -Dauto_features=enabled,
# so we must explicitly enable or disable features that we are not passing
# dependencies for.
+ (lib.mesonEnable "gc" enableGC)
(lib.mesonEnable "internal-api-docs" internalApiDocs)
(lib.mesonBool "enable-tests" finalAttrs.finalPackage.doCheck)
(lib.mesonBool "enable-docs" canRunInstalled)
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index a925ce2d8..741a24e3c 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -249,6 +249,12 @@ EvalState::EvalState(
, sRight(symbols.create("right"))
, sWrong(symbols.create("wrong"))
, sStructuredAttrs(symbols.create("__structuredAttrs"))
+ , sAllowedReferences(symbols.create("allowedReferences"))
+ , sAllowedRequisites(symbols.create("allowedRequisites"))
+ , sDisallowedReferences(symbols.create("disallowedReferences"))
+ , sDisallowedRequisites(symbols.create("disallowedRequisites"))
+ , sMaxSize(symbols.create("maxSize"))
+ , sMaxClosureSize(symbols.create("maxClosureSize"))
, sBuilder(symbols.create("builder"))
, sArgs(symbols.create("args"))
, sContentAddressed(symbols.create("__contentAddressed"))
@@ -2802,20 +2808,20 @@ Expr & EvalState::parseExprFromFile(const SourcePath & path, std::shared_ptr<Sta
}
-Expr & EvalState::parseExprFromString(std::string s_, const SourcePath & basePath, std::shared_ptr<StaticEnv> & staticEnv)
+Expr & EvalState::parseExprFromString(std::string s_, const SourcePath & basePath, std::shared_ptr<StaticEnv> & staticEnv, const ExperimentalFeatureSettings & xpSettings)
{
// NOTE this method (and parseStdin) must take care to *fully copy* their input
// into their respective Pos::Origin until the parser stops overwriting its input
// data.
auto s = make_ref<std::string>(s_);
s_.append("\0\0", 2);
- return *parse(s_.data(), s_.size(), Pos::String{.source = s}, basePath, staticEnv);
+ return *parse(s_.data(), s_.size(), Pos::String{.source = s}, basePath, staticEnv, xpSettings);
}
-Expr & EvalState::parseExprFromString(std::string s, const SourcePath & basePath)
+Expr & EvalState::parseExprFromString(std::string s, const SourcePath & basePath, const ExperimentalFeatureSettings & xpSettings)
{
- return parseExprFromString(std::move(s), basePath, staticBaseEnv);
+ return parseExprFromString(std::move(s), basePath, staticBaseEnv, xpSettings);
}
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index e54eede40..ff45efc08 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -13,7 +13,6 @@
#include "search-path.hh"
#include "repl-exit-status.hh"
-#include <gc/gc_allocator.h>
#include <map>
#include <optional>
#include <unordered_map>
@@ -162,7 +161,10 @@ public:
const Symbol sWith, sOutPath, sDrvPath, sType, sMeta, sName, sValue,
sSystem, sOverrides, sOutputs, sOutputName, sIgnoreNulls,
sFile, sLine, sColumn, sFunctor, sToString,
- sRight, sWrong, sStructuredAttrs, sBuilder, sArgs,
+ sRight, sWrong, sStructuredAttrs,
+ sAllowedReferences, sAllowedRequisites, sDisallowedReferences, sDisallowedRequisites,
+ sMaxSize, sMaxClosureSize,
+ sBuilder, sArgs,
sContentAddressed, sImpure,
sOutputHash, sOutputHashAlgo, sOutputHashMode,
sRecurseForDerivations,
@@ -342,8 +344,8 @@ public:
/**
* Parse a Nix expression from the specified string.
*/
- Expr & parseExprFromString(std::string s, const SourcePath & basePath, std::shared_ptr<StaticEnv> & staticEnv);
- Expr & parseExprFromString(std::string s, const SourcePath & basePath);
+ Expr & parseExprFromString(std::string s, const SourcePath & basePath, std::shared_ptr<StaticEnv> & staticEnv, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
+ Expr & parseExprFromString(std::string s, const SourcePath & basePath, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
Expr & parseStdin();
@@ -566,7 +568,8 @@ private:
size_t length,
Pos::Origin origin,
const SourcePath & basePath,
- std::shared_ptr<StaticEnv> & staticEnv);
+ std::shared_ptr<StaticEnv> & staticEnv,
+ const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
/**
* Current Nix call stack depth, used with `max-call-depth` setting to throw stack overflow hopefully before we run out of system stack.
diff --git a/src/libexpr/parser/parser.cc b/src/libexpr/parser/parser.cc
index b7a105fe7..68aa3ddc5 100644
--- a/src/libexpr/parser/parser.cc
+++ b/src/libexpr/parser/parser.cc
@@ -631,7 +631,7 @@ template<> struct BuildAST<grammar::expr::path> : p::maybe_nothing {};
template<> struct BuildAST<grammar::expr::uri> {
static void apply(const auto & in, ExprState & s, State & ps) {
- static bool noURLLiterals = experimentalFeatureSettings.isEnabled(Xp::NoUrlLiterals);
+ bool noURLLiterals = ps.xpSettings.isEnabled(Xp::NoUrlLiterals);
if (noURLLiterals)
throw ParseError({
.msg = HintFmt("URL literals are disabled"),
@@ -832,7 +832,8 @@ Expr * EvalState::parse(
size_t length,
Pos::Origin origin,
const SourcePath & basePath,
- std::shared_ptr<StaticEnv> & staticEnv)
+ std::shared_ptr<StaticEnv> & staticEnv,
+ const ExperimentalFeatureSettings & xpSettings)
{
parser::State s = {
symbols,
@@ -840,6 +841,7 @@ Expr * EvalState::parse(
basePath,
positions.addOrigin(origin, length),
exprSymbols,
+ xpSettings
};
parser::ExprState x;
diff --git a/src/libexpr/parser/state.hh b/src/libexpr/parser/state.hh
index 29889152e..30803a37e 100644
--- a/src/libexpr/parser/state.hh
+++ b/src/libexpr/parser/state.hh
@@ -19,6 +19,7 @@ struct State
SourcePath basePath;
PosTable::Origin origin;
const Expr::AstSymbols & s;
+ const ExperimentalFeatureSettings & xpSettings;
void dupAttr(const AttrPath & attrPath, const PosIdx pos, const PosIdx prevPos);
void dupAttr(Symbol attr, const PosIdx pos, const PosIdx prevPos);
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 0951a54de..561492f86 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1213,6 +1213,20 @@ drvName, Bindings * attrs, Value & v)
handleOutputs(ss);
}
+ if (i->name == state.sAllowedReferences)
+ warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedReferences'; use 'outputChecks.<output>.allowedReferences' instead", drvName);
+ if (i->name == state.sAllowedRequisites)
+ warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'allowedRequisites'; use 'outputChecks.<output>.allowedRequisites' instead", drvName);
+ if (i->name == state.sDisallowedReferences)
+ warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedReferences'; use 'outputChecks.<output>.disallowedReferences' instead", drvName);
+ if (i->name == state.sDisallowedRequisites)
+ warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedRequisites'; use 'outputChecks.<output>.disallowedRequisites' instead", drvName);
+ if (i->name == state.sMaxSize)
+ warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxSize'; use 'outputChecks.<output>.maxSize' instead", drvName);
+ if (i->name == state.sMaxClosureSize)
+ warn("In a derivation named '%s', 'structuredAttrs' disables the effect of the derivation attribute 'maxClosureSize'; use 'outputChecks.<output>.maxClosureSize' instead", drvName);
+
+
} else {
auto s = state.coerceToString(pos, *i->value, context, context_below, true).toOwned();
drv.env.emplace(key, s);
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 23903117a..db380e07c 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2517,6 +2517,24 @@ void LocalDerivationGoal::checkOutputs(const std::map<std::string, ValidPathInfo
};
if (auto structuredAttrs = parsedDrv->getStructuredAttrs()) {
+ if (get(*structuredAttrs, "allowedReferences")){
+ warn("'structuredAttrs' disables the effect of the top-level attribute 'allowedReferences'; use 'outputChecks' instead");
+ }
+ if (get(*structuredAttrs, "allowedRequisites")){
+ warn("'structuredAttrs' disables the effect of the top-level attribute 'allowedRequisites'; use 'outputChecks' instead");
+ }
+ if (get(*structuredAttrs, "disallowedRequisites")){
+ warn("'structuredAttrs' disables the effect of the top-level attribute 'disallowedRequisites'; use 'outputChecks' instead");
+ }
+ if (get(*structuredAttrs, "disallowedReferences")){
+ warn("'structuredAttrs' disables the effect of the top-level attribute 'disallowedReferences'; use 'outputChecks' instead");
+ }
+ if (get(*structuredAttrs, "maxSize")){
+ warn("'structuredAttrs' disables the effect of the top-level attribute 'maxSize'; use 'outputChecks' instead");
+ }
+ if (get(*structuredAttrs, "maxClosureSize")){
+ warn("'structuredAttrs' disables the effect of the top-level attribute 'maxClosureSize'; use 'outputChecks' instead");
+ }
if (auto outputChecks = get(*structuredAttrs, "outputChecks")) {
if (auto output = get(*outputChecks, outputName)) {
Checks checks;
diff --git a/tests/functional/lang/eval-okay-derivation-legacy.err.exp b/tests/functional/lang/eval-okay-derivation-legacy.err.exp
new file mode 100644
index 000000000..94f0854dd
--- /dev/null
+++ b/tests/functional/lang/eval-okay-derivation-legacy.err.exp
@@ -0,0 +1,6 @@
+warning: In a derivation named 'eval-okay-derivation-legacy', 'structuredAttrs' disables the effect of the derivation attribute 'allowedReferences'; use 'outputChecks.<output>.allowedReferences' instead
+warning: In a derivation named 'eval-okay-derivation-legacy', 'structuredAttrs' disables the effect of the derivation attribute 'allowedRequisites'; use 'outputChecks.<output>.allowedRequisites' instead
+warning: In a derivation named 'eval-okay-derivation-legacy', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedReferences'; use 'outputChecks.<output>.disallowedReferences' instead
+warning: In a derivation named 'eval-okay-derivation-legacy', 'structuredAttrs' disables the effect of the derivation attribute 'disallowedRequisites'; use 'outputChecks.<output>.disallowedRequisites' instead
+warning: In a derivation named 'eval-okay-derivation-legacy', 'structuredAttrs' disables the effect of the derivation attribute 'maxClosureSize'; use 'outputChecks.<output>.maxClosureSize' instead
+warning: In a derivation named 'eval-okay-derivation-legacy', 'structuredAttrs' disables the effect of the derivation attribute 'maxSize'; use 'outputChecks.<output>.maxSize' instead
diff --git a/tests/functional/lang/eval-okay-derivation-legacy.exp b/tests/functional/lang/eval-okay-derivation-legacy.exp
new file mode 100644
index 000000000..4f374a1aa
--- /dev/null
+++ b/tests/functional/lang/eval-okay-derivation-legacy.exp
@@ -0,0 +1 @@
+"/nix/store/mzgwvrjjir216ra58mwwizi8wj6y9ddr-eval-okay-derivation-legacy"
diff --git a/tests/functional/lang/eval-okay-derivation-legacy.nix b/tests/functional/lang/eval-okay-derivation-legacy.nix
new file mode 100644
index 000000000..b529cdf90
--- /dev/null
+++ b/tests/functional/lang/eval-okay-derivation-legacy.nix
@@ -0,0 +1,12 @@
+(builtins.derivationStrict {
+ name = "eval-okay-derivation-legacy";
+ system = "x86_64-linux";
+ builder = "/dontcare";
+ __structuredAttrs = true;
+ allowedReferences = [ ];
+ disallowedReferences = [ ];
+ allowedRequisites = [ ];
+ disallowedRequisites = [ ];
+ maxSize = 1234;
+ maxClosureSize = 12345;
+}).out
diff --git a/tests/unit/libexpr-support/tests/libexpr.hh b/tests/unit/libexpr-support/tests/libexpr.hh
index 01dcbb34c..745aa168d 100644
--- a/tests/unit/libexpr-support/tests/libexpr.hh
+++ b/tests/unit/libexpr-support/tests/libexpr.hh
@@ -26,9 +26,9 @@ namespace nix {
, state({}, store)
{
}
- Value eval(std::string input, bool forceValue = true) {
+ Value eval(std::string input, bool forceValue = true, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings) {
Value v;
- Expr & e = state.parseExprFromString(input, state.rootPath(CanonPath::root));
+ Expr & e = state.parseExprFromString(input, state.rootPath(CanonPath::root), xpSettings);
state.eval(e, v);
if (forceValue)
state.forceValue(v, noPos);
diff --git a/tests/unit/libexpr/trivial.cc b/tests/unit/libexpr/trivial.cc
index 171727ac7..19b62aff8 100644
--- a/tests/unit/libexpr/trivial.cc
+++ b/tests/unit/libexpr/trivial.cc
@@ -59,6 +59,11 @@ namespace nix {
ASSERT_THAT(v, IsFloatEq(1.234));
}
+ TEST_F(TrivialExpressionTest, pointfloat) {
+ auto v = eval(".234");
+ ASSERT_THAT(v, IsFloatEq(0.234));
+ }
+
TEST_F(TrivialExpressionTest, updateAttrs) {
auto v = eval("{ a = 1; } // { b = 2; a = 3; }");
ASSERT_THAT(v, IsAttrsOfSize(2));
@@ -81,6 +86,18 @@ namespace nix {
ASSERT_THAT(v, IsTrue());
}
+ TEST_F(TrivialExpressionTest, urlLiteral) {
+ auto v = eval("https://nixos.org");
+ ASSERT_THAT(v, IsStringEq("https://nixos.org"));
+ }
+
+ TEST_F(TrivialExpressionTest, noUrlLiteral) {
+ ExperimentalFeatureSettings mockXpSettings;
+ mockXpSettings.set("experimental-features", "no-url-literals");
+
+ ASSERT_THROW(eval("https://nixos.org", true, mockXpSettings), Error);
+ }
+
TEST_F(TrivialExpressionTest, withFound) {
auto v = eval("with { a = 23; }; a");
ASSERT_THAT(v, IsIntEq(23));