libexpr/primops: reject __json in structured attrs derivations
In structured attrs derivations, __json is used to serialize the `env` attribute into a JSON object. If the derivation enables structured attributes AND specify its own `__json`, one of the field will take precedence (the reader can have fun by guessing which one). To reduce underspecification, we disallow `__json` in structured attributes derivations. Fixes #380. Change-Id: I51c3b2af1ff9449471ba81d4c72df6a7a263eef7 Signed-off-by: Raito Bezarius <raito@lix.systems>
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
---
|
||||
synopsis: "Reject `__json` in structured attributes derivations"
|
||||
cls: [5286]
|
||||
issues: [fj#380]
|
||||
category: "Improvements"
|
||||
credits: [raito]
|
||||
---
|
||||
|
||||
In structured attributes derivations, `__json` is used internally to store the
|
||||
JSON representation of the `env` attribute field that users can set.
|
||||
|
||||
Unfortunately, a user can set `__json` *and* enable structured attributes,
|
||||
resulting in a broken derivation from a semantic point of view.
|
||||
|
||||
As no user can benefit from setting `__json` *and* enable structured attributes,
|
||||
we disallow that possibility and throw an error from now on.
|
||||
|
||||
This is not seen as a breaking change because there's no user code that can
|
||||
benefit from this behavior, hence, it's an improvement to user experience.
|
||||
@@ -903,6 +903,14 @@ drvName, Bindings * attrs, Value & v)
|
||||
"attribute passed to builtins.derivationStrict"
|
||||
))
|
||||
{
|
||||
if (attrs->get(state.ctx.symbols.sym___json)) {
|
||||
state.ctx.errors
|
||||
.make<EvalError>(
|
||||
"a `__json` attribute cannot be passed to builtins.derivationStrict when structured "
|
||||
"attributes are enabled"
|
||||
)
|
||||
.debugThrow();
|
||||
}
|
||||
jsonObject = JSON::object();
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +217,7 @@ public:
|
||||
const Symbol sym___structuredAttrs = create("__structuredAttrs");
|
||||
const Symbol sym___contentAddressed = create("__contentAddressed");
|
||||
const Symbol sym___impure = create("__impure");
|
||||
const Symbol sym___json = create("__json");
|
||||
/* Derivation */
|
||||
const Symbol sym_outPath = create("outPath");
|
||||
const Symbol sym_drvPath = create("drvPath");
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from testlib.fixtures.nix import Nix
|
||||
|
||||
|
||||
evil_drv = """
|
||||
builtins.derivation {
|
||||
name = "foo";
|
||||
builder = "/bin/sh";
|
||||
system = builtins.currentSystem;
|
||||
__structuredAttrs = true;
|
||||
|
||||
__json.hello = "1";
|
||||
env.hello = "2";
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def test_improper_structured_attrs_drv(nix: Nix):
|
||||
result = nix.nix_build(["--expr", evil_drv]).run().expect(1)
|
||||
assert "a `__json` attribute cannot be passed" in result.stderr_s
|
||||
Reference in New Issue
Block a user