Fix #3090: let binding in command leaks when error occurs (#4022)

This commit is contained in:
Tom Panton 2021-09-19 03:57:20 +01:00 committed by GitHub
parent 1297499d7a
commit f7043bf690
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -101,17 +101,14 @@ fn if_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
//FIXME: should we use the scope that's brought in as well?
let condition = evaluate_baseline_expr(cond, &context);
match condition {
let result = match condition {
Ok(condition) => match condition.as_bool() {
Ok(b) => {
let result = if b {
if b {
run_block(&then_case.block, &context, input, external_redirection)
} else {
run_block(&else_case.block, &context, input, external_redirection)
};
context.scope.exit_scope();
result
}
}
Err(e) => Ok(OutputStream::from_stream(
vec![UntaggedValue::Error(e).into_untagged_value()].into_iter(),
@ -120,13 +117,16 @@ fn if_command(args: CommandArgs) -> Result<OutputStream, ShellError> {
Err(e) => Ok(OutputStream::from_stream(
vec![UntaggedValue::Error(e).into_untagged_value()].into_iter(),
)),
}
};
context.scope.exit_scope();
result
}
#[cfg(test)]
mod tests {
use super::If;
use super::ShellError;
use nu_test_support::nu;
#[test]
fn examples_work_as_expected() -> Result<(), ShellError> {
@ -134,4 +134,21 @@ mod tests {
test_examples(If {})
}
#[test]
fn if_doesnt_leak_on_error() {
let actual = nu!(
".",
r#"
def test-leak [] {
let var = "hello"
if 0 == "" {echo ok} {echo not}
}
test-leak
echo $var
"#
);
assert!(actual.err.contains("unknown variable"));
}
}