prevent panic with format command (#7522)

Related: #7211.

Prevents numeric underflow in span.

Co-authored-by: sholderbach <sholderbach@users.noreply.github.com>
This commit is contained in:
pwygab 2022-12-19 20:10:02 +08:00 committed by GitHub
parent a21af0ade4
commit dae1b9a996
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 3 deletions

View File

@ -55,7 +55,11 @@ impl Command for Format {
let string_span = pattern.span()?;
// the string span is start as `"`, we don't need the character
// to generate proper span for sub expression.
let ops = extract_formatting_operations(string_pattern, string_span.start + 1);
let ops = extract_formatting_operations(
string_pattern,
call.head,
string_span.start + 1,
)?;
format(
input_val,
@ -112,7 +116,11 @@ enum FormatOperation {
/// formatted according to the input pattern.
/// FormatOperation::ValueNeedEval contains expression which need to eval, it has the following form:
/// "$it.column1.column2" or "$variable"
fn extract_formatting_operations(input: String, span_start: usize) -> Vec<FormatOperation> {
fn extract_formatting_operations(
input: String,
error_span: Span,
span_start: usize,
) -> Result<Vec<FormatOperation>, ShellError> {
let mut output = vec![];
let mut characters = input.char_indices();
@ -148,6 +156,13 @@ fn extract_formatting_operations(input: String, span_start: usize) -> Vec<Format
column_name.push(ch);
}
if column_span_end < column_span_start {
return Err(ShellError::DelimiterError(
"there are unmatched curly braces".to_string(),
error_span,
));
}
if !column_name.is_empty() {
if column_need_eval {
output.push(FormatOperation::ValueNeedEval(
@ -166,7 +181,7 @@ fn extract_formatting_operations(input: String, span_start: usize) -> Vec<Format
break;
}
}
output
Ok(output)
}
/// Format the incoming PipelineData according to the pattern

View File

@ -42,6 +42,19 @@ fn can_use_variables() {
assert_eq!(actual.out, "nu is a new type of shell");
}
#[test]
fn error_unmatched_brace() {
let actual = nu!(
cwd: "tests/fixtures/formats", pipeline(
r#"
open cargo_sample.toml
| format "{$it.package.name"
"#
));
assert!(actual.err.contains("unmatched curly brace"));
}
#[test]
fn format_filesize_works() {
Playground::setup("format_filesize_test_1", |dirs, sandbox| {