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:
jade 2024-06-19 03:31:47 +00:00 committed by Gerrit Code Review
commit 85f282ef57
9 changed files with 45 additions and 17 deletions

View file

@ -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']

View file

@ -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;
} }

View file

@ -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.

View file

@ -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);

View file

@ -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 doesnt 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 users (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).
)", )",

View file

@ -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({

View file

@ -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;

View file

@ -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.
*/ */

View file

@ -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 {