From 08df4436182a12a25aa45fcab2a13dbe71f7f10a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 10 Mar 2005 11:33:46 +0000 Subject: [PATCH] * Check for duplicate attributes and formal parameters in Nix expressions. --- blacklisting/check-env.pl | 2 +- src/libexpr/parser.cc | 61 +++++++++++++++++++ tests/lang/parse-fail-dup-attrs-1.nix | 4 ++ tests/lang/parse-fail-dup-attrs-2.nix | 13 ++++ tests/lang/parse-fail-dup-attrs-3.nix | 13 ++++ tests/lang/parse-fail-dup-formals.nix | 1 + ...se-fail-1.nix => parse-fail-undef-var.nix} | 0 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 tests/lang/parse-fail-dup-attrs-1.nix create mode 100644 tests/lang/parse-fail-dup-attrs-2.nix create mode 100644 tests/lang/parse-fail-dup-attrs-3.nix create mode 100644 tests/lang/parse-fail-dup-formals.nix rename tests/lang/{parse-fail-1.nix => parse-fail-undef-var.nix} (100%) diff --git a/blacklisting/check-env.pl b/blacklisting/check-env.pl index 0d76156e..6eb792a5 100755 --- a/blacklisting/check-env.pl +++ b/blacklisting/check-env.pl @@ -232,7 +232,7 @@ foreach my $userEnvElem (@userEnvElems) { # Evaluate each blacklist item. foreach my $item ($blacklist->getChildrenByTagName("item")) { my $itemId = $item->getAttributeNode("id")->getValue; - print " CHECKING FOR $itemId\n"; +# print " CHECKING FOR $itemId\n"; my $condition = ($item->getChildrenByTagName("condition"))[0]; die unless $condition; diff --git a/src/libexpr/parser.cc b/src/libexpr/parser.cc index 8232b0de..16b94fa6 100644 --- a/src/libexpr/parser.cc +++ b/src/libexpr/parser.cc @@ -75,6 +75,65 @@ int yyparse(yyscan_t scanner, ParseData * data); } +static void checkAttrs(ATermMap & names, ATermList bnds) +{ + for (ATermIterator i(bnds); i; ++i) { + ATerm name; + Expr e; + ATerm pos; + if (!matchBind(*i, name, e, pos)) abort(); /* can't happen */ + if (names.get(name)) + throw Error(format("duplicate attribute `%1%' at %2%") + % aterm2String(name) % showPos(pos)); + names.set(name, name); + } +} + + +static void checkAttrSets(ATerm e) +{ + ATermList formals; + ATerm body, pos; + if (matchFunction(e, formals, body, pos)) { + ATermMap names; + for (ATermIterator i(formals); i; ++i) { + ATerm name; + Expr deflt; + if (!matchNoDefFormal(*i, name) && + !matchDefFormal(*i, name, deflt)) + abort(); + if (names.get(name)) + throw Error(format("duplicate formal function argument `%1%' at %2%") + % aterm2String(name) % showPos(pos)); + names.set(name, name); + } + } + + ATermList bnds; + if (matchAttrs(e, bnds)) { + ATermMap names; + checkAttrs(names, bnds); + } + + ATermList rbnds, nrbnds; + if (matchRec(e, rbnds, nrbnds)) { + ATermMap names; + checkAttrs(names, rbnds); + checkAttrs(names, nrbnds); + } + + if (ATgetType(e) == AT_APPL) { + int arity = ATgetArity(ATgetAFun(e)); + for (int i = 0; i < arity; ++i) + checkAttrSets(ATgetArgument(e, i)); + } + + else if (ATgetType(e) == AT_LIST) + for (ATermIterator i((ATermList) e); i; ++i) + checkAttrSets(*i); +} + + static Expr parse(EvalState & state, const char * text, const Path & path, const Path & basePath) @@ -96,6 +155,8 @@ static Expr parse(EvalState & state, } catch (Error & e) { throw Error(format("%1%, in `%2%'") % e.msg() % path); } + + checkAttrSets(data.result); return data.result; } diff --git a/tests/lang/parse-fail-dup-attrs-1.nix b/tests/lang/parse-fail-dup-attrs-1.nix new file mode 100644 index 00000000..2c02317d --- /dev/null +++ b/tests/lang/parse-fail-dup-attrs-1.nix @@ -0,0 +1,4 @@ +{ x = 123; + y = 456; + x = 789; +} diff --git a/tests/lang/parse-fail-dup-attrs-2.nix b/tests/lang/parse-fail-dup-attrs-2.nix new file mode 100644 index 00000000..864d9865 --- /dev/null +++ b/tests/lang/parse-fail-dup-attrs-2.nix @@ -0,0 +1,13 @@ +let { + + as = { + x = 123; + y = 456; + }; + + bs = { + x = 789; + inherit (as) x; + }; + +} diff --git a/tests/lang/parse-fail-dup-attrs-3.nix b/tests/lang/parse-fail-dup-attrs-3.nix new file mode 100644 index 00000000..114d1977 --- /dev/null +++ b/tests/lang/parse-fail-dup-attrs-3.nix @@ -0,0 +1,13 @@ +let { + + as = { + x = 123; + y = 456; + }; + + bs = rec { + x = 789; + inherit (as) x; + }; + +} diff --git a/tests/lang/parse-fail-dup-formals.nix b/tests/lang/parse-fail-dup-formals.nix new file mode 100644 index 00000000..a0edd91a --- /dev/null +++ b/tests/lang/parse-fail-dup-formals.nix @@ -0,0 +1 @@ +{x, y, x}: x \ No newline at end of file diff --git a/tests/lang/parse-fail-1.nix b/tests/lang/parse-fail-undef-var.nix similarity index 100% rename from tests/lang/parse-fail-1.nix rename to tests/lang/parse-fail-undef-var.nix