aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/derivations.cc
diff options
context:
space:
mode:
authorFelix Uhl <felix.uhl@netlight.com>2023-07-28 22:23:56 +0200
committerFelix Uhl <felix.uhl@netlight.com>2023-08-05 01:34:30 +0200
commit3fefc2b28494468c7a6078430eaaf8a6c8f17230 (patch)
treea17322e65bc9186b44b34d0dc262067c8b31880d /src/libstore/derivations.cc
parentdcdd5fed74445c526a361202a9e6c8459a38726b (diff)
Fix derivation load assertion errors
When loading a derivation from a JSON, malformed input would trigger cryptic "assertion failed" errors. Simply replacing calls to `operator []` with calls to `.at()` was not enough, as this would cause json.execptions to be printed verbatim. Display nice error messages instead and give some indication where the error happened. *Before:* ``` $ echo 4 | nix derivation add error: [json.exception.type_error.305] cannot use operator[] with a string argument with number $ nix derivation show nixpkgs#hello | nix derivation add Assertion failed: (it != m_value.object->end()), function operator[], file /nix/store/8h9pxgq1776ns6qi5arx08ifgnhmgl22-nlohmann_json-3.11.2/include/nlohmann/json.hpp, line 2135. $ nix derivation show nixpkgs#hello | jq '.[] | .name = 5' | nix derivation add error: [json.exception.type_error.302] type must be string, but is object $ nix derivation show nixpkgs#hello | jq '.[] | .outputs = { out: "/nix/store/8j3f8j-hello" }' | nix derivation add error: [json.exception.type_error.302] type must be object, but is string ``` *After:* ``` $ echo 4 | nix derivation add error: Expected JSON of derivation to be of type 'object', but it is of type 'number' $ nix derivation show nixpkgs#hello | nix derivation add error: Expected JSON object to contain key 'name' but it doesn't $ nix derivation show nixpkgs#hello | jq '.[] | .name = 5' | nix derivation add error: Expected JSON value to be of type 'string' but it is of type 'number' $ nix derivation show nixpkgs#hello | jq '.[] | .outputs = { out: "/nix/store/8j3f8j-hello" }' | nix derivation add error: … while reading key 'outputs' error: Expected JSON value to be of type 'object' but it is of type 'string' ```
Diffstat (limited to 'src/libstore/derivations.cc')
-rw-r--r--src/libstore/derivations.cc40
1 files changed, 28 insertions, 12 deletions
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index b831b2fe5..8a84bb1c5 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -993,6 +993,7 @@ DerivationOutput DerivationOutput::fromJSON(
const ExperimentalFeatureSettings & xpSettings)
{
std::set<std::string_view> keys;
+ ensureType(_json, nlohmann::detail::value_t::object);
auto json = (std::map<std::string, nlohmann::json>) _json;
for (const auto & [key, _] : json)
@@ -1097,36 +1098,51 @@ Derivation Derivation::fromJSON(
const Store & store,
const nlohmann::json & json)
{
+ using nlohmann::detail::value_t;
+
Derivation res;
- res.name = json["name"];
+ ensureType(json, value_t::object);
- {
- auto & outputsObj = json["outputs"];
+ res.name = ensureType(valueAt(json, "name"), value_t::string);
+
+ try {
+ auto & outputsObj = ensureType(valueAt(json, "outputs"), value_t::object);
for (auto & [outputName, output] : outputsObj.items()) {
res.outputs.insert_or_assign(
outputName,
DerivationOutput::fromJSON(store, res.name, outputName, output));
}
+ } catch (Error & e) {
+ e.addTrace({}, "while reading key 'outputs'");
+ throw;
}
- {
- auto & inputsList = json["inputSrcs"];
+ try {
+ auto & inputsList = ensureType(valueAt(json, "inputSrcs"), value_t::array);
for (auto & input : inputsList)
res.inputSrcs.insert(store.parseStorePath(static_cast<const std::string &>(input)));
+ } catch (Error & e) {
+ e.addTrace({}, "while reading key 'inputSrcs'");
+ throw;
}
- {
- auto & inputDrvsObj = json["inputDrvs"];
- for (auto & [inputDrvPath, inputOutputs] : inputDrvsObj.items())
+ try {
+ auto & inputDrvsObj = ensureType(valueAt(json, "inputDrvs"), value_t::object);
+ for (auto & [inputDrvPath, inputOutputs] : inputDrvsObj.items()) {
+ ensureType(inputOutputs, value_t::array);
res.inputDrvs[store.parseStorePath(inputDrvPath)] =
static_cast<const StringSet &>(inputOutputs);
+ }
+ } catch (Error & e) {
+ e.addTrace({}, "while reading key 'inputDrvs'");
+ throw;
}
- res.platform = json["system"];
- res.builder = json["builder"];
- res.args = json["args"];
- res.env = json["env"];
+ res.platform = ensureType(valueAt(json, "system"), value_t::string);
+ res.builder = ensureType(valueAt(json, "builder"), value_t::string);
+ res.args = ensureType(valueAt(json, "args"), value_t::array);
+ res.env = ensureType(valueAt(json, "env"), value_t::object);
return res;
}