diff --git a/doc/manual/rl-next/reject-json-structured-attrs.md b/doc/manual/rl-next/reject-json-structured-attrs.md new file mode 100644 index 000000000..eff3ba8c9 --- /dev/null +++ b/doc/manual/rl-next/reject-json-structured-attrs.md @@ -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. diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 635fd169a..51ab47f6f 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -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( + "a `__json` attribute cannot be passed to builtins.derivationStrict when structured " + "attributes are enabled" + ) + .debugThrow(); + } jsonObject = JSON::object(); } diff --git a/lix/libexpr/symbol-table.hh b/lix/libexpr/symbol-table.hh index a5e23c864..ca4d3758d 100644 --- a/lix/libexpr/symbol-table.hh +++ b/lix/libexpr/symbol-table.hh @@ -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"); diff --git a/tests/functional2/build/test_structured_attrs.py b/tests/functional2/build/test_structured_attrs.py new file mode 100644 index 000000000..11b9a8754 --- /dev/null +++ b/tests/functional2/build/test_structured_attrs.py @@ -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