From aab0116a9c10a681512a28a101c20893088e8def Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Fri, 2 Feb 2024 20:07:42 -0800 Subject: [PATCH] Forbid nested debuggers --- src/libcmd/repl.cc | 8 +------- src/libexpr/eval.cc | 5 +++-- src/libexpr/eval.hh | 19 +++++++++++++++++++ 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/libcmd/repl.cc b/src/libcmd/repl.cc index c9df1c257568..7223350f29d1 100644 --- a/src/libcmd/repl.cc +++ b/src/libcmd/repl.cc @@ -304,13 +304,7 @@ void NixRepl::mainLoop() printMsg(lvlError, e.msg()); } } catch (EvalError & e) { - // in debugger mode, an EvalError should trigger another repl session. - // when that session returns the exception will land here. No need to show it again; - // show the error for this repl session instead. - if (state->debugRepl && !state->debugTraces.empty()) - showDebugTrace(std::cout, state->positions, state->debugTraces.front()); - else - printMsg(lvlError, e.msg()); + printMsg(lvlError, e.msg()); } catch (Error & e) { printMsg(lvlError, e.msg()); } catch (Interrupted & e) { diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 5bc62589c8fe..a8f6728f64d3 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -764,8 +764,8 @@ std::unique_ptr mapStaticEnvBindings(const SymbolTable & st, const Stati void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr & expr) { - // double check we've got the debugRepl function pointer. - if (!debugRepl) + // Make sure we have a debugger to run and we're not already in a debugger. + if (!debugRepl || inDebugger) return; auto dts = @@ -792,6 +792,7 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr & auto se = getStaticEnv(expr); if (se) { auto vm = mapStaticEnvBindings(symbols, *se.get(), env); + DebuggerGuard _guard(inDebugger); (debugRepl)(ref(shared_from_this()), *vm); } } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 3c7c5da2741c..08d53403d94d 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -152,6 +152,24 @@ struct DebugTrace { bool isError; }; + +namespace { +/** + * Sets `inDebugger` to true on construction and false on destruction. + */ +class DebuggerGuard { + bool & inDebugger; +public: + DebuggerGuard(bool & inDebugger) : inDebugger(inDebugger) { + inDebugger = true; + } + ~DebuggerGuard() { + inDebugger = false; + } +}; +} + + class EvalState : public std::enable_shared_from_this { public: @@ -222,6 +240,7 @@ public: void (* debugRepl)(ref es, const ValMap & extraEnv); bool debugStop; bool debugQuit; + bool inDebugger = false; int trylevel; std::list debugTraces; std::map> exprEnvs;