Files
nix/tests/repl-completion.nix
Amaan Qureshi be6e72f11b repl: prevent exceptions from escaping editline callbacks
The tab completion handler in `completePrefix` only caught `ParseError`,
`EvalError`, `BadURL`, and `FileNotFound`. Other error types like
`JSONParseError` (which derives from `Error`, not `EvalError`) escaped
the catch block and propagated through editline's C code as undefined
behavior, crashing the REPL. This happened when tab-completing
expressions like `(builtins.fromJSON "invalid").` where evaluation
throws a non-`EvalError` exception.

This commit marks `completionCallback` and `listPossibleCallback` as
`noexcept` with function-try-blocks that catch all exceptions at the
C/C++ boundary, preventing any exception from reaching editline.

Fixes #15133.
2026-02-16 16:02:37 -05:00

65 lines
1.6 KiB
Nix

{
runCommand,
nix,
expect,
}:
# We only use expect when necessary, e.g. for testing tab completion in nix repl.
# See also tests/functional/repl.sh
runCommand "repl-completion"
{
nativeBuildInputs = [
expect
nix
];
expectScript = ''
# Regression https://github.com/NixOS/nix/pull/10778
spawn nix repl --offline --extra-experimental-features nix-command
expect "nix-repl>"
send "foo = import ./does-not-exist.nix\n"
expect "nix-repl>"
send "foo.\t"
expect {
"nix-repl>" {
puts "Got another prompt. Good."
}
eof {
puts "Got EOF. Bad."
exit 1
}
}
# Regression https://github.com/NixOS/nix/issues/15133
# Tab-completing an expression that throws a non-EvalError (e.g.
# JSONParseError from fromJSON) should not crash the REPL.
send "err1 = builtins.fromJSON \"nixnix\"\n"
expect "nix-repl>"
send "err1.\t"
sleep 0.5
# Send Ctrl-C to cancel the current line and get a fresh prompt,
# since tab with no completions leaves the cursor on the same line.
send "\x03"
expect {
"nix-repl>" {
puts "Got another prompt after fromJSON error."
}
eof {
puts "REPL crashed after fromJSON tab-complete."
exit 1
}
}
exit 0
'';
passAsFile = [ "expectScript" ];
}
''
export NIX_STORE=$TMPDIR/store
export NIX_STATE_DIR=$TMPDIR/state
export HOME=$TMPDIR/home
mkdir $HOME
nix-store --init
expect $expectScriptPath
touch $out
''