From 4785f5f252cac223e66fc27b31d9638f0490431e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Riegel?= Date: Mon, 3 Mar 2025 19:17:26 +0100 Subject: [PATCH] bugfix: math commands now return error with infinite range [#15135] --- crates/nu-command/src/math/utils.rs | 25 +++++++++++++++++-- crates/nu-command/tests/commands/math/abs.rs | 7 ++++++ crates/nu-command/tests/commands/math/avg.rs | 14 +++++++++++ crates/nu-command/tests/commands/math/ceil.rs | 7 ++++++ .../nu-command/tests/commands/math/floor.rs | 7 ++++++ crates/nu-command/tests/commands/math/log.rs | 7 ++++++ crates/nu-command/tests/commands/math/max.rs | 7 ++++++ .../nu-command/tests/commands/math/median.rs | 7 ++++++ crates/nu-command/tests/commands/math/min.rs | 7 ++++++ crates/nu-command/tests/commands/math/mode.rs | 7 ++++++ .../nu-command/tests/commands/math/product.rs | 7 ++++++ .../nu-command/tests/commands/math/round.rs | 7 ++++++ crates/nu-command/tests/commands/math/sqrt.rs | 7 ++++++ .../nu-command/tests/commands/math/stddev.rs | 7 ++++++ crates/nu-command/tests/commands/math/sum.rs | 7 ++++++ .../tests/commands/math/variance.rs | 7 ++++++ crates/nu-pretty-hex/README.md | 2 +- 17 files changed, 136 insertions(+), 3 deletions(-) diff --git a/crates/nu-command/src/math/utils.rs b/crates/nu-command/src/math/utils.rs index 62f96ea073..e9b87b2df1 100644 --- a/crates/nu-command/src/math/utils.rs +++ b/crates/nu-command/src/math/utils.rs @@ -1,6 +1,8 @@ -use core::slice; +use core::{ops::Bound, slice}; use indexmap::IndexMap; -use nu_protocol::{engine::Call, IntoPipelineData, PipelineData, ShellError, Signals, Span, Value}; +use nu_protocol::{ + engine::Call, IntoPipelineData, PipelineData, Range, ShellError, Signals, Span, Value, +}; pub fn run_with_function( call: &Call, @@ -91,6 +93,10 @@ pub fn calculate( Ok(Value::record(record, span)) } PipelineData::Value(Value::Range { val, .. }, ..) => { + match *val { + Range::IntRange(range) => ensure_bounded(range.end(), span, name)?, + Range::FloatRange(range) => ensure_bounded(range.end(), span, name)?, + } let new_vals: Result, ShellError> = val .into_range_iter(span, Signals::empty()) .map(|val| mf(&[val], span, name)) @@ -110,3 +116,18 @@ pub fn calculate( }), } } + +pub fn ensure_bounded( + bound: Bound, + val_span: Span, + call_span: Span, +) -> Result<(), ShellError> { + match bound { + Bound::::Unbounded => Err(ShellError::IncorrectValue { + msg: "Range must be bounded".to_string(), + val_span, + call_span, + }), + _ => Ok(()), + } +} diff --git a/crates/nu-command/tests/commands/math/abs.rs b/crates/nu-command/tests/commands/math/abs.rs index 4d61c8ed11..de5c7551aa 100644 --- a/crates/nu-command/tests/commands/math/abs.rs +++ b/crates/nu-command/tests/commands/math/abs.rs @@ -5,3 +5,10 @@ fn const_abs() { let actual = nu!("const ABS = -5.5 | math abs; $ABS"); assert_eq!(actual.out, "5.5"); } + +#[test] +fn cannot_abs_range() { + let actual = nu!("0..5 | math abs"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/avg.rs b/crates/nu-command/tests/commands/math/avg.rs index 744b2f6067..ec9a124b7b 100644 --- a/crates/nu-command/tests/commands/math/avg.rs +++ b/crates/nu-command/tests/commands/math/avg.rs @@ -21,6 +21,20 @@ fn can_average_bytes() { assert_eq!(actual.out, "34985870"); } +#[test] +fn can_average_range() { + let actual = nu!("0..5 | math avg"); + + assert_eq!(actual.out, "2.5"); +} + +#[test] +fn cannot_average_infinite_range() { + let actual = nu!("0.. | math avg"); + + assert!(actual.err.contains("nu::shell::incorrect_value")); +} + #[test] fn const_avg() { let actual = nu!("const AVG = [1 3 5] | math avg; $AVG"); diff --git a/crates/nu-command/tests/commands/math/ceil.rs b/crates/nu-command/tests/commands/math/ceil.rs index 760fb0a503..f9c753d1dd 100644 --- a/crates/nu-command/tests/commands/math/ceil.rs +++ b/crates/nu-command/tests/commands/math/ceil.rs @@ -5,3 +5,10 @@ fn const_ceil() { let actual = nu!("const CEIL = 1.5 | math ceil; $CEIL"); assert_eq!(actual.out, "2"); } + +#[test] +fn cannot_ceil_range() { + let actual = nu!("0..5 | math ceil"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/floor.rs b/crates/nu-command/tests/commands/math/floor.rs index 91184c8f58..5517233caa 100644 --- a/crates/nu-command/tests/commands/math/floor.rs +++ b/crates/nu-command/tests/commands/math/floor.rs @@ -5,3 +5,10 @@ fn const_floor() { let actual = nu!("const FLOOR = 15.5 | math floor; $FLOOR"); assert_eq!(actual.out, "15"); } + +#[test] +fn cannot_floor_range() { + let actual = nu!("0.. | math floor"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/log.rs b/crates/nu-command/tests/commands/math/log.rs index a8e54689b5..db69378e41 100644 --- a/crates/nu-command/tests/commands/math/log.rs +++ b/crates/nu-command/tests/commands/math/log.rs @@ -5,3 +5,10 @@ fn const_log() { let actual = nu!("const LOG = 16 | math log 2; $LOG"); assert_eq!(actual.out, "4"); } + +#[test] +fn cannot_log_range() { + let actual = nu!("0.. | math log 2"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/max.rs b/crates/nu-command/tests/commands/math/max.rs index cd940d3811..1ad715b68f 100644 --- a/crates/nu-command/tests/commands/math/max.rs +++ b/crates/nu-command/tests/commands/math/max.rs @@ -5,3 +5,10 @@ fn const_max() { let actual = nu!("const MAX = [1 3 5] | math max; $MAX"); assert_eq!(actual.out, "5"); } + +#[test] +fn cannot_max_infinite_range() { + let actual = nu!("0.. | math max"); + + assert!(actual.err.contains("nu::shell::incorrect_value")); +} diff --git a/crates/nu-command/tests/commands/math/median.rs b/crates/nu-command/tests/commands/math/median.rs index 5e118e3b06..ba98305326 100644 --- a/crates/nu-command/tests/commands/math/median.rs +++ b/crates/nu-command/tests/commands/math/median.rs @@ -41,3 +41,10 @@ fn const_median() { let actual = nu!("const MEDIAN = [1 3 5] | math median; $MEDIAN"); assert_eq!(actual.out, "3"); } + +#[test] +fn cannot_median_infinite_range() { + let actual = nu!("0.. | math median"); + + assert!(actual.err.contains("nu::shell::incorrect_value")); +} diff --git a/crates/nu-command/tests/commands/math/min.rs b/crates/nu-command/tests/commands/math/min.rs index 1384562c08..f7d4ab7317 100644 --- a/crates/nu-command/tests/commands/math/min.rs +++ b/crates/nu-command/tests/commands/math/min.rs @@ -5,3 +5,10 @@ fn const_min() { let actual = nu!("const MIN = [1 3 5] | math min; $MIN"); assert_eq!(actual.out, "1"); } + +#[test] +fn cannot_min_infinite_range() { + let actual = nu!("0.. | math min"); + + assert!(actual.err.contains("nu::shell::incorrect_value")); +} diff --git a/crates/nu-command/tests/commands/math/mode.rs b/crates/nu-command/tests/commands/math/mode.rs index 160d2b6897..8a8f235257 100644 --- a/crates/nu-command/tests/commands/math/mode.rs +++ b/crates/nu-command/tests/commands/math/mode.rs @@ -5,3 +5,10 @@ fn const_avg() { let actual = nu!("const MODE = [1 3 3 5] | math mode; $MODE"); assert_eq!(actual.out, "╭───┬───╮│ 0 │ 3 │╰───┴───╯"); } + +#[test] +fn cannot_mode_range() { + let actual = nu!("0..5 | math mode"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/product.rs b/crates/nu-command/tests/commands/math/product.rs index f31ba9c6bc..c51db825a8 100644 --- a/crates/nu-command/tests/commands/math/product.rs +++ b/crates/nu-command/tests/commands/math/product.rs @@ -5,3 +5,10 @@ fn const_product() { let actual = nu!("const PROD = [1 3 5] | math product; $PROD"); assert_eq!(actual.out, "15"); } + +#[test] +fn cannot_product_infinite_range() { + let actual = nu!("0.. | math product"); + + assert!(actual.err.contains("nu::shell::incorrect_value")); +} diff --git a/crates/nu-command/tests/commands/math/round.rs b/crates/nu-command/tests/commands/math/round.rs index 61a3199701..2c3badad5e 100644 --- a/crates/nu-command/tests/commands/math/round.rs +++ b/crates/nu-command/tests/commands/math/round.rs @@ -40,3 +40,10 @@ fn const_round() { let actual = nu!("const ROUND = 18.345 | math round; $ROUND"); assert_eq!(actual.out, "18"); } + +#[test] +fn cannot_round_infinite_range() { + let actual = nu!("0..5 | math round"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/sqrt.rs b/crates/nu-command/tests/commands/math/sqrt.rs index a0ba35b233..9f5cc55f88 100644 --- a/crates/nu-command/tests/commands/math/sqrt.rs +++ b/crates/nu-command/tests/commands/math/sqrt.rs @@ -26,3 +26,10 @@ fn const_sqrt() { let actual = nu!("const SQRT = 4 | math sqrt; $SQRT"); assert_eq!(actual.out, "2"); } + +#[test] +fn cannot_sqrt_range() { + let actual = nu!("0..5 | math sqrt"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/stddev.rs b/crates/nu-command/tests/commands/math/stddev.rs index 83fc472396..f1688c2d7a 100644 --- a/crates/nu-command/tests/commands/math/stddev.rs +++ b/crates/nu-command/tests/commands/math/stddev.rs @@ -5,3 +5,10 @@ fn const_avg() { let actual = nu!("const SDEV = [1 2] | math stddev; $SDEV"); assert_eq!(actual.out, "0.5"); } + +#[test] +fn cannot_stddev_range() { + let actual = nu!("0..5 | math stddev"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-command/tests/commands/math/sum.rs b/crates/nu-command/tests/commands/math/sum.rs index 020ce552c9..0a367f839b 100644 --- a/crates/nu-command/tests/commands/math/sum.rs +++ b/crates/nu-command/tests/commands/math/sum.rs @@ -81,3 +81,10 @@ fn const_sum() { let actual = nu!("const SUM = [1 3] | math sum; $SUM"); assert_eq!(actual.out, "4"); } + +#[test] +fn cannot_sum_infinite_range() { + let actual = nu!("0.. | math sum"); + + assert!(actual.err.contains("nu::shell::incorrect_value")); +} diff --git a/crates/nu-command/tests/commands/math/variance.rs b/crates/nu-command/tests/commands/math/variance.rs index 1e27484bf0..1573a131bb 100644 --- a/crates/nu-command/tests/commands/math/variance.rs +++ b/crates/nu-command/tests/commands/math/variance.rs @@ -5,3 +5,10 @@ fn const_variance() { let actual = nu!("const VAR = [1 2 3 4 5] | math variance; $VAR"); assert_eq!(actual.out, "2"); } + +#[test] +fn cannot_variance_range() { + let actual = nu!("0..5 | math variance"); + + assert!(actual.err.contains("nu::parser::input_type_mismatch")); +} diff --git a/crates/nu-pretty-hex/README.md b/crates/nu-pretty-hex/README.md index 7c640cc28f..3a485a2701 100644 --- a/crates/nu-pretty-hex/README.md +++ b/crates/nu-pretty-hex/README.md @@ -1,6 +1,6 @@ # nu-pretty-hex -An update of prett-hex to make it prettier +An update of pretty-hex to make it prettier [![crates.io](https://img.shields.io/crates/v/pretty-hex.svg)](https://crates.io/crates/pretty-hex) [![docs.rs](https://docs.rs/pretty-hex/badge.svg)](https://docs.rs/pretty-hex)