Skip to content

Commit

Permalink
nixd/attrs-eval: check value is in valid state (#423)
Browse files Browse the repository at this point in the history
  • Loading branch information
inclyc authored Apr 16, 2024
1 parent 4ba76d8 commit c280691
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 6 deletions.
16 changes: 15 additions & 1 deletion nixd/include/nixd/Eval/AttrSetProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,28 @@ class AttrSetProvider : public lspserver::LSPServer {

std::unique_ptr<nix::EvalState> State;

nix::Value Nixpkgs;
nix::Value Val;

// If this value is valid
bool ValueValid = false;

/// Convenient method for get state. Basically assume this->State is not null
nix::EvalState &state() {
assert(State && "State should be allocated by ctor!");
return *State;
}

/// \brief Check if the value is valid. \throw an exception if it is not.
void checkValueValid() const {
if (!ValueValid)
throw std::runtime_error("value is invalid");
}

nix::Value &validValue() {
checkValueValid();
return Val;
}

public:
AttrSetProvider(std::unique_ptr<lspserver::InboundPort> In,
std::unique_ptr<lspserver::OutboundPort> Out);
Expand Down
14 changes: 9 additions & 5 deletions nixd/lib/Eval/AttrSetProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,11 @@ void AttrSetProvider::onEvalExpr(
const std::string &Name,
lspserver::Callback<std::optional<std::string>> Reply) {
try {
ValueValid = false;
nix::Expr *AST = state().parseExprFromString(
Name, state().rootPath(nix::CanonPath::fromCwd()));
state().eval(AST, Nixpkgs);
state().eval(AST, Val);
ValueValid = true;
Reply(std::nullopt);
return;
} catch (const nix::BaseError &Err) {
Expand All @@ -149,7 +151,7 @@ void AttrSetProvider::onAttrPathInfo(
return;
}

nix::Value &Package = nixt::selectStrings(state(), Nixpkgs, AttrPath);
nix::Value &Package = nixt::selectStrings(state(), validValue(), AttrPath);

AttrPathInfoResponse R;
fillPackageDescription(state(), Package, R);
Expand All @@ -169,7 +171,8 @@ void AttrSetProvider::onAttrPathComplete(
const AttrPathCompleteParams &Params,
lspserver::Callback<AttrPathCompleteResponse> Reply) {
try {
nix::Value &Scope = nixt::selectStrings(state(), Nixpkgs, Params.Scope);
nix::Value &Scope =
nixt::selectStrings(state(), validValue(), Params.Scope);

state().forceValue(Scope, nix::noPos);

Expand Down Expand Up @@ -217,7 +220,7 @@ void AttrSetProvider::onOptionInfo(
return;
}

nix::Value &Option = nixt::selectStrings(state(), Nixpkgs, AttrPath);
nix::Value &Option = nixt::selectStrings(state(), validValue(), AttrPath);

OptionInfoResponse R;

Expand All @@ -238,7 +241,8 @@ void AttrSetProvider::onOptionComplete(
const AttrPathCompleteParams &Params,
lspserver::Callback<OptionCompleteResponse> Reply) {
try {
nix::Value &Scope = nixt::selectStrings(state(), Nixpkgs, Params.Scope);
nix::Value &Scope =
nixt::selectStrings(state(), validValue(), Params.Scope);

state().forceValue(Scope, nix::noPos);

Expand Down
32 changes: 32 additions & 0 deletions nixd/tools/nixd-attrset-eval/test/invalid-value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# RUN: nixd-attrset-eval --lit-test < %s | FileCheck %s


```json
{
"jsonrpc":"2.0",
"id":0,
"method":"attrset/evalExpr",
"params": "fuck $$@"
}
```


```json
{
"jsonrpc":"2.0",
"id":1,
"method":"attrset/attrpathInfo",
"params": [ "hello" ]
}
```

```
CHECK: "message": "value is invalid"
CHECK-NEXT: },
CHECK-NEXT: "id": 1,
```

```json
{"jsonrpc":"2.0","method":"exit"}
```

0 comments on commit c280691

Please sign in to comment.