Skip to content

Commit

Permalink
libexpr: quote reserved keys when printing
Browse files Browse the repository at this point in the history
This fixes a bug in commands like `nix eval' which would emit invalid attribute
sets if they contained reserved keywords such as "assert", "let", etc.

These keywords will not be quoted when printed, making them valid expressions.
All keywords recognized by the lexer are quoted, as well as "import"
and "throw".
  • Loading branch information
aakropotkin committed Mar 28, 2023
1 parent e00abd3 commit f93d833
Showing 1 changed file with 17 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ RootValue allocRootValue(Value * v)
#endif
}

// Returns `true' is a string is a reserved keyword which requires quotation
// when printing attribute set field names.
static inline bool isReservedKeyword(const std::string_view str)
{
static const std::unordered_set<std::string_view> reservedKeywords = {
"if", "then", "else", "assert", "with", "let", "in", "rec", "inherit",
"or", "throw", "import"
};
return reservedKeywords.contains(str);
}

void Value::print(const SymbolTable & symbols, std::ostream & str,
std::set<const void *> * seen) const
Expand Down Expand Up @@ -128,7 +138,13 @@ void Value::print(const SymbolTable & symbols, std::ostream & str,
else {
str << "{ ";
for (auto & i : attrs->lexicographicOrder(symbols)) {
str << symbols[i->name] << " = ";
// Quote reserved keywords so that the output can be
// re-evaluated later without upsetting the lexer.
if (isReservedKeyword(symbols[i->name])) {
str << "\"" << symbols[i->name] << "\" = ";
} else {
str << symbols[i->name] << " = ";
}
i->value->print(symbols, str, seen);
str << "; ";
}
Expand Down

0 comments on commit f93d833

Please sign in to comment.