Merge changes Id0e651e4,I0ed20da8,I76bd6d22,I5d8ffb7b into main
* changes: store: fix null reference from DerivationGoal::waiteeDone libmain: fix UB in verbosity assignment build: make UBSan work :) libexpr: fix accessing uninitialized values and fix pure-eval docs
This commit is contained in:
commit
85f282ef57
|
@ -437,7 +437,9 @@ add_project_arguments(
|
||||||
language : 'cpp',
|
language : 'cpp',
|
||||||
)
|
)
|
||||||
|
|
||||||
if cxx.get_id() in ['gcc', 'clang']
|
# We turn off the production UBSan if the slower dev UBSan is requested, to
|
||||||
|
# give better diagnostics.
|
||||||
|
if cxx.get_id() in ['gcc', 'clang'] and 'undefined' not in get_option('b_sanitize')
|
||||||
# 2024-03-24: jade benchmarked the default sanitize reporting in clang and got
|
# 2024-03-24: jade benchmarked the default sanitize reporting in clang and got
|
||||||
# a regression of about 10% on hackage-packages.nix with clang. So we are trapping instead.
|
# a regression of about 10% on hackage-packages.nix with clang. So we are trapping instead.
|
||||||
#
|
#
|
||||||
|
@ -452,6 +454,11 @@ if cxx.get_id() in ['gcc', 'clang']
|
||||||
add_project_arguments(sanitize_args, language: 'cpp')
|
add_project_arguments(sanitize_args, language: 'cpp')
|
||||||
add_project_link_arguments(sanitize_args, language: 'cpp')
|
add_project_link_arguments(sanitize_args, language: 'cpp')
|
||||||
endif
|
endif
|
||||||
|
# Clang's default of -no-shared-libsan on Linux causes link errors; on macOS it defaults to shared.
|
||||||
|
# GCC defaults to shared libsan so is fine.
|
||||||
|
if cxx.get_id() == 'clang' and get_option('b_sanitize') != ''
|
||||||
|
add_project_link_arguments('-shared-libsan', language : 'cpp')
|
||||||
|
endif
|
||||||
|
|
||||||
add_project_link_arguments('-pthread', language : 'cpp')
|
add_project_link_arguments('-pthread', language : 'cpp')
|
||||||
if cxx.get_linker_id() in ['ld.bfd', 'ld.gold']
|
if cxx.get_linker_id() in ['ld.bfd', 'ld.gold']
|
||||||
|
|
|
@ -63,11 +63,9 @@ Strings EvalSettings::getDefaultNixPath()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!evalSettings.restrictEval && !evalSettings.pureEval) {
|
|
||||||
add(getNixDefExpr() + "/channels");
|
add(getNixDefExpr() + "/channels");
|
||||||
add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
|
add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
|
||||||
add(rootChannelsDir());
|
add(rootChannelsDir());
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,8 +75,17 @@ struct EvalSettings : Config
|
||||||
R"(
|
R"(
|
||||||
Pure evaluation mode ensures that the result of Nix expressions is fully determined by explicitly declared inputs, and not influenced by external state:
|
Pure evaluation mode ensures that the result of Nix expressions is fully determined by explicitly declared inputs, and not influenced by external state:
|
||||||
|
|
||||||
- Restrict file system and network access to files specified by cryptographic hash
|
- File system and network access is restricted to accesses to immutable data only:
|
||||||
- Disable [`builtins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem) and [`builtins.currentTime`](@docroot@/language/builtin-constants.md#builtins-currentTime)
|
- Path literals relative to the home directory like `~/lix` are rejected at parse time.
|
||||||
|
- Access to absolute paths that did not result from Nix language evaluation is rejected when such paths are given as parameters to builtins like, for example, [`builtins.readFile`](@docroot@/language/builtins.md#builtins-readFile).
|
||||||
|
|
||||||
|
Access is nonetheless allowed to (absolute) paths in the Nix store that are returned by builtins like [`builtins.filterSource`](@docroot@/language/builtins.md#builtins-filterSource), [`builtins.fetchTarball`](@docroot@/language/builtins.md#builtins-fetchTarball) and similar.
|
||||||
|
- Impure fetches such as not specifying a commit ID for `builtins.fetchGit` or not specifying a hash for `builtins.fetchTarball` are rejected.
|
||||||
|
- In flakes, access to relative paths outside of the root of the flake's source tree (often, a git repository) is rejected.
|
||||||
|
- The evaluator ignores `NIX_PATH`, `-I` and the `nix-path` setting. Thus, [`builtins.nixPath`](@docroot@/language/builtin-constants.md#builtins-nixPath) is an empty list.
|
||||||
|
- The builtins [`builtins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem) and [`builtins.currentTime`](@docroot@/language/builtin-constants.md#builtins-currentTime) are absent from `builtins`.
|
||||||
|
- [`builtins.getEnv`](@docroot@/language/builtin-constants.md#builtins-currentSystem) always returns empty string for any variable.
|
||||||
|
- [`builtins.storePath`](@docroot@/language/builtins.md#builtins-storePath) throws an error (Lix may change this, tracking issue: <https://git.lix.systems/lix-project/lix/issues/402>)
|
||||||
)"
|
)"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -98,6 +107,7 @@ struct EvalSettings : Config
|
||||||
allowed to access `https://github.com/NixOS/patchelf.git`.
|
allowed to access `https://github.com/NixOS/patchelf.git`.
|
||||||
)"};
|
)"};
|
||||||
|
|
||||||
|
|
||||||
Setting<bool> traceFunctionCalls{this, false, "trace-function-calls",
|
Setting<bool> traceFunctionCalls{this, false, "trace-function-calls",
|
||||||
R"(
|
R"(
|
||||||
If set to `true`, the Nix evaluator will trace every function call.
|
If set to `true`, the Nix evaluator will trace every function call.
|
||||||
|
|
|
@ -418,7 +418,7 @@ EvalState::EvalState(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evalSettings.restrictEval || evalSettings.pureEval) {
|
if (evalSettings.restrictEval || evalSettings.pureEval) {
|
||||||
allowedPaths = PathSet();
|
allowedPaths = std::optional(PathSet());
|
||||||
|
|
||||||
for (auto & i : searchPath.elements) {
|
for (auto & i : searchPath.elements) {
|
||||||
auto r = resolveSearchPathPath(i.path);
|
auto r = resolveSearchPathPath(i.path);
|
||||||
|
|
|
@ -923,14 +923,15 @@ static RegisterPrimOp primop_getEnv({
|
||||||
.args = {"s"},
|
.args = {"s"},
|
||||||
.doc = R"(
|
.doc = R"(
|
||||||
`getEnv` returns the value of the environment variable *s*, or an
|
`getEnv` returns the value of the environment variable *s*, or an
|
||||||
empty string if the variable doesn’t exist. This function should be
|
empty string if the variable doesn't exist. This function should be
|
||||||
used with care, as it can introduce all sorts of nasty environment
|
used with care, as it can introduce all sorts of nasty environment
|
||||||
dependencies in your Nix expression.
|
dependencies in your Nix expression.
|
||||||
|
|
||||||
`getEnv` is used in Nix Packages to locate the file
|
`getEnv` is used in nixpkgs for evil impurities such as locating the file
|
||||||
`~/.nixpkgs/config.nix`, which contains user-local settings for Nix
|
`~/.config/nixpkgs/config.nix` which contains user-local settings for nixpkgs.
|
||||||
Packages. (That is, it does a `getEnv "HOME"` to locate the user’s
|
(That is, it does a `getEnv "HOME"` to locate the user's home directory.)
|
||||||
home directory.)
|
|
||||||
|
When in [pure evaluation mode](@docroot@/command-ref/conf-file.md#conf-pure-eval), this function always returns an empty string.
|
||||||
)",
|
)",
|
||||||
.fun = prim_getEnv,
|
.fun = prim_getEnv,
|
||||||
});
|
});
|
||||||
|
@ -1506,6 +1507,7 @@ static RegisterPrimOp primop_storePath({
|
||||||
in a new path (e.g. `/nix/store/ld01dnzc…-source-source`).
|
in a new path (e.g. `/nix/store/ld01dnzc…-source-source`).
|
||||||
|
|
||||||
Not available in [pure evaluation mode](@docroot@/command-ref/conf-file.md#conf-pure-eval).
|
Not available in [pure evaluation mode](@docroot@/command-ref/conf-file.md#conf-pure-eval).
|
||||||
|
Lix may change this, tracking issue: <https://git.lix.systems/lix-project/lix/issues/402>
|
||||||
|
|
||||||
See also [`builtins.fetchClosure`](#builtins-fetchClosure).
|
See also [`builtins.fetchClosure`](#builtins-fetchClosure).
|
||||||
)",
|
)",
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "args/root.hh"
|
#include "args/root.hh"
|
||||||
|
#include "error.hh"
|
||||||
#include "globals.hh"
|
#include "globals.hh"
|
||||||
#include "loggers.hh"
|
#include "loggers.hh"
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
|
@ -14,14 +15,14 @@ MixCommonArgs::MixCommonArgs(const std::string & programName)
|
||||||
.shortName = 'v',
|
.shortName = 'v',
|
||||||
.description = "Increase the logging verbosity level.",
|
.description = "Increase the logging verbosity level.",
|
||||||
.category = loggingCategory,
|
.category = loggingCategory,
|
||||||
.handler = {[]() { verbosity = (Verbosity) (verbosity + 1); }},
|
.handler = {[]() { verbosity = verbosityFromIntClamped(int(verbosity) + 1); }},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
.longName = "quiet",
|
.longName = "quiet",
|
||||||
.description = "Decrease the logging verbosity level.",
|
.description = "Decrease the logging verbosity level.",
|
||||||
.category = loggingCategory,
|
.category = loggingCategory,
|
||||||
.handler = {[]() { verbosity = verbosity > lvlError ? (Verbosity) (verbosity - 1) : lvlError; }},
|
.handler = {[]() { verbosity = verbosityFromIntClamped(int(verbosity) - 1); }},
|
||||||
});
|
});
|
||||||
|
|
||||||
addFlag({
|
addFlag({
|
||||||
|
|
|
@ -1553,11 +1553,12 @@ void DerivationGoal::waiteeDone(GoalPtr waitee, ExitCode result)
|
||||||
Goal::waiteeDone(waitee, result);
|
Goal::waiteeDone(waitee, result);
|
||||||
|
|
||||||
if (!useDerivation) return;
|
if (!useDerivation) return;
|
||||||
auto & fullDrv = *dynamic_cast<Derivation *>(drv.get());
|
|
||||||
|
|
||||||
auto * dg = dynamic_cast<DerivationGoal *>(&*waitee);
|
auto * dg = dynamic_cast<DerivationGoal *>(&*waitee);
|
||||||
if (!dg) return;
|
if (!dg) return;
|
||||||
|
|
||||||
|
auto & fullDrv = *dynamic_cast<Derivation *>(drv.get());
|
||||||
|
|
||||||
auto * nodeP = fullDrv.inputDrvs.findSlot(DerivedPath::Opaque { .path = dg->drvPath });
|
auto * nodeP = fullDrv.inputDrvs.findSlot(DerivedPath::Opaque { .path = dg->drvPath });
|
||||||
if (!nodeP) return;
|
if (!nodeP) return;
|
||||||
auto & outputs = nodeP->value;
|
auto & outputs = nodeP->value;
|
||||||
|
|
|
@ -45,6 +45,8 @@ typedef enum {
|
||||||
lvlVomit
|
lvlVomit
|
||||||
} Verbosity;
|
} Verbosity;
|
||||||
|
|
||||||
|
Verbosity verbosityFromIntClamped(int val);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The lines of code surrounding an error.
|
* The lines of code surrounding an error.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "position.hh"
|
#include "position.hh"
|
||||||
#include "terminal.hh"
|
#include "terminal.hh"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
@ -110,6 +111,12 @@ public:
|
||||||
|
|
||||||
Verbosity verbosity = lvlInfo;
|
Verbosity verbosity = lvlInfo;
|
||||||
|
|
||||||
|
Verbosity verbosityFromIntClamped(int val)
|
||||||
|
{
|
||||||
|
int clamped = std::clamp(val, int(lvlError), int(lvlVomit));
|
||||||
|
return static_cast<Verbosity>(clamped);
|
||||||
|
}
|
||||||
|
|
||||||
void writeToStderr(std::string_view s)
|
void writeToStderr(std::string_view s)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in a new issue