mirror of
https://github.com/NixOS/nix.git
synced 2024-11-25 08:12:29 +00:00
fix(libexpr/eval-inline): get rid of references to nullptr env
When diagnosing infinite recursion references to nullptr `Env` can be formed. This happens only with `ExprBlackHole` is evaluated, which always leads to `InfiniteRecursionError`. UBSAN log for one such case: ``` ../src/libexpr/eval-inline.hh:94:31: runtime error: reference binding to null pointer of type 'Env' SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior ../src/libexpr/eval-inline.hh:94:31 in ```
This commit is contained in:
parent
32becc87fe
commit
1800853b2a
@ -87,11 +87,15 @@ void EvalState::forceValue(Value & v, const PosIdx pos)
|
|||||||
{
|
{
|
||||||
if (v.isThunk()) {
|
if (v.isThunk()) {
|
||||||
Env * env = v.payload.thunk.env;
|
Env * env = v.payload.thunk.env;
|
||||||
|
assert(env || v.isBlackhole());
|
||||||
Expr * expr = v.payload.thunk.expr;
|
Expr * expr = v.payload.thunk.expr;
|
||||||
try {
|
try {
|
||||||
v.mkBlackhole();
|
v.mkBlackhole();
|
||||||
//checkInterrupt();
|
//checkInterrupt();
|
||||||
|
if (env) [[likely]]
|
||||||
expr->eval(*this, *env, v);
|
expr->eval(*this, *env, v);
|
||||||
|
else
|
||||||
|
ExprBlackHole::throwInfiniteRecursionError(*this, v);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
v.mkThunk(env, expr);
|
v.mkThunk(env, expr);
|
||||||
tryFixupBlackHolePos(v, pos);
|
tryFixupBlackHolePos(v, pos);
|
||||||
|
@ -2052,9 +2052,12 @@ void ExprPos::eval(EvalState & state, Env & env, Value & v)
|
|||||||
state.mkPos(v, pos);
|
state.mkPos(v, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExprBlackHole::eval(EvalState & state, [[maybe_unused]] Env & env, Value & v)
|
||||||
void ExprBlackHole::eval(EvalState & state, Env & env, Value & v)
|
|
||||||
{
|
{
|
||||||
|
throwInfiniteRecursionError(state, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[gnu::noinline]] [[noreturn]] void ExprBlackHole::throwInfiniteRecursionError(EvalState & state, Value &v) {
|
||||||
state.error<InfiniteRecursionError>("infinite recursion encountered")
|
state.error<InfiniteRecursionError>("infinite recursion encountered")
|
||||||
.atPos(v.determinePos(noPos))
|
.atPos(v.determinePos(noPos))
|
||||||
.debugThrow();
|
.debugThrow();
|
||||||
|
@ -468,6 +468,7 @@ struct ExprBlackHole : Expr
|
|||||||
void show(const SymbolTable & symbols, std::ostream & str) const override {}
|
void show(const SymbolTable & symbols, std::ostream & str) const override {}
|
||||||
void eval(EvalState & state, Env & env, Value & v) override;
|
void eval(EvalState & state, Env & env, Value & v) override;
|
||||||
void bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env) override {}
|
void bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> & env) override {}
|
||||||
|
[[noreturn]] static void throwInfiniteRecursionError(EvalState & state, Value & v);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern ExprBlackHole eBlackHole;
|
extern ExprBlackHole eBlackHole;
|
||||||
|
Loading…
Reference in New Issue
Block a user