We got UBSan working on Lix, so we of course immediately found a bug and some definitely nonsense behaviour. Accessing `pureEval` or `restrictEval` from a default setting value is nonsense, since they would never be actually set by the time that value is set so they are not going to do anything. The configuration is not applied in an initializer (and even if it were, it's not going to be in the right order). After looking into *that*, we hunted down what actually was applying these, since clearly this code did not do anything. The EvalState constructor should have a "search path added and removed here :)" sign on it, because that's where it is done. We added an explicit initialization of the optional in there because it was otherwise unclear why pureEval also has the search path to allowed paths setup code run. We then realized that the `pureEval` documentation was *also* bogus, and we rewrote it. In so doing, we realized that we forgot to file a bug to make `builtins.storePath` work in pure eval mode, so we filed one of those: https://git.lix.systems/lix-project/lix/issues/402 Yaks have been thoroughly shorn. UBSan report: ../src/libexpr/eval-settings.cc:66:10: runtime error: member call on address 0x752fa9a13060 which does not point to an object of type 'nix::BaseSetting<b ool>' 0x752fa9a13060: note: object has invalid vptr 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ^~~~~~~~~~~~~~~~~~~~~~~ invalid vptr 0 0x752fa95106a6 in nix::EvalSettings::getDefaultNixPath[abi:cxx11]() /home/jade/lix/lix2/build/src/libexpr/eval-settings.cc:66:10 1 0x752fa950e420 in nix::EvalSettings::EvalSettings() /home/jade/lix/lix2/build/src/libexpr/eval-settings.hh:36:15 2 0x752fa9469f1f in __cxx_global_var_init.50 /home/jade/lix/lix2/build/src/libexpr/eval-settings.cc:98:14 3 0x752fa9469f1f in _GLOBAL__sub_I_eval_settings.cc /home/jade/lix/lix2/build/src/libexpr/eval-settings.cc 4 0x752fabbd308d in call_init (/nix/store/k7zgvzp2r31zkg9xqgjim7mbknryv6bs-glibc-2.39-52/lib/ld-linux-x86-64.so.2+0x508d) (BuildId: a5b8228edc9f16078ac3c894af964eeb990ecb4c) 5 0x752fabbd317b in _dl_init (/nix/store/k7zgvzp2r31zkg9xqgjim7mbknryv6bs-glibc-2.39-52/lib/ld-linux-x86-64.so.2+0x517b) (BuildId: a5b8228edc9f16078ac3c894af964eeb990ecb4c) 6 0x752fabbe9c2f in _dl_start_user (/nix/store/k7zgvzp2r31zkg9xqgjim7mbknryv6bs-glibc-2.39-52/lib/ld-linux-x86-64.so.2+0x1bc2f) (BuildId: a5b8228edc9f16078ac3c894af964eeb990ecb4c) Change-Id: I5d8ffb7bfbe24b6584020ac74eed93d9f2e6d111
107 lines
2.6 KiB
C++
107 lines
2.6 KiB
C++
#include "file-system.hh"
|
|
#include "globals.hh"
|
|
#include "profiles.hh"
|
|
#include "users.hh"
|
|
#include "eval-settings.hh"
|
|
|
|
namespace nix {
|
|
|
|
/* Very hacky way to parse $NIX_PATH, which is colon-separated, but
|
|
can contain URLs (e.g. "nixpkgs=https://bla...:foo=https://"). */
|
|
static Strings parseNixPath(const std::string & s)
|
|
{
|
|
Strings res;
|
|
|
|
auto p = s.begin();
|
|
|
|
while (p != s.end()) {
|
|
auto start = p;
|
|
auto start2 = p;
|
|
|
|
while (p != s.end() && *p != ':') {
|
|
if (*p == '=') start2 = p + 1;
|
|
++p;
|
|
}
|
|
|
|
if (p == s.end()) {
|
|
if (p != start) res.push_back(std::string(start, p));
|
|
break;
|
|
}
|
|
|
|
if (*p == ':') {
|
|
auto prefix = std::string(start2, s.end());
|
|
if (EvalSettings::isPseudoUrl(prefix) || prefix.starts_with("flake:")) {
|
|
++p;
|
|
while (p != s.end() && *p != ':') ++p;
|
|
}
|
|
res.push_back(std::string(start, p));
|
|
if (p == s.end()) break;
|
|
}
|
|
|
|
++p;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
EvalSettings::EvalSettings()
|
|
{
|
|
auto var = getEnv("NIX_PATH");
|
|
if (var) nixPath = parseNixPath(*var);
|
|
}
|
|
|
|
Strings EvalSettings::getDefaultNixPath()
|
|
{
|
|
Strings res;
|
|
auto add = [&](const Path & p, const std::string & s = std::string()) {
|
|
if (pathAccessible(p)) {
|
|
if (s.empty()) {
|
|
res.push_back(p);
|
|
} else {
|
|
res.push_back(s + "=" + p);
|
|
}
|
|
}
|
|
};
|
|
|
|
add(getNixDefExpr() + "/channels");
|
|
add(rootChannelsDir() + "/nixpkgs", "nixpkgs");
|
|
add(rootChannelsDir());
|
|
|
|
return res;
|
|
}
|
|
|
|
bool EvalSettings::isPseudoUrl(std::string_view s)
|
|
{
|
|
if (s.compare(0, 8, "channel:") == 0) return true;
|
|
size_t pos = s.find("://");
|
|
if (pos == std::string::npos) return false;
|
|
std::string scheme(s, 0, pos);
|
|
return scheme == "http" || scheme == "https" || scheme == "file" || scheme == "channel" || scheme == "git" || scheme == "s3" || scheme == "ssh";
|
|
}
|
|
|
|
std::string EvalSettings::resolvePseudoUrl(std::string_view url)
|
|
{
|
|
if (url.starts_with("channel:"))
|
|
return "https://nixos.org/channels/" + std::string(url.substr(8)) + "/nixexprs.tar.xz";
|
|
else
|
|
return std::string(url);
|
|
}
|
|
|
|
const std::string & EvalSettings::getCurrentSystem()
|
|
{
|
|
const auto & evalSystem = currentSystem.get();
|
|
return evalSystem != "" ? evalSystem : settings.thisSystem.get();
|
|
}
|
|
|
|
EvalSettings evalSettings;
|
|
|
|
static GlobalConfig::Register rEvalSettings(&evalSettings);
|
|
|
|
Path getNixDefExpr()
|
|
{
|
|
return settings.useXDGBaseDirectories
|
|
? getStateDir() + "/nix/defexpr"
|
|
: getHome() + "/.nix-defexpr";
|
|
}
|
|
|
|
}
|