From ce3df12eaac8e0f1a6ea913343bf0b9a94f576a3 Mon Sep 17 00:00:00 2001 From: Justin Tracey Date: Sun, 16 Jan 2022 23:21:39 -0500 Subject: [PATCH] join: "support" field numbers larger than usize::MAX They silently get folded to usize::MAX, which is the official GNU behavior. --- src/uu/join/src/join.rs | 5 ++++ tests/by-util/test_join.rs | 21 ++++++++++++++++ .../join/out_of_bounds_fields.expected | 25 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 tests/fixtures/join/out_of_bounds_fields.expected diff --git a/src/uu/join/src/join.rs b/src/uu/join/src/join.rs index a338a22c4e6..f9d9444b8c6 100644 --- a/src/uu/join/src/join.rs +++ b/src/uu/join/src/join.rs @@ -809,8 +809,13 @@ fn get_field_number(keys: Option, key: Option) -> UResult { /// Parse the specified field string as a natural number and return /// the zero-based field number. fn parse_field_number(value: &str) -> UResult { + // TODO: use ParseIntError.kind() once MSRV >= 1.55 + // For now, store an overflow Err from parsing a value 10x 64 bit usize::MAX + // Adapted from https://github.com/rust-lang/rust/issues/22639 + let overflow = "184467440737095516150".parse::().err().unwrap(); match value.parse::() { Ok(result) if result > 0 => Ok(result - 1), + Err(ref e) if *e == overflow => Ok(usize::MAX), _ => Err(USimpleError::new( 1, format!("invalid field number: {}", value.quote()), diff --git a/tests/by-util/test_join.rs b/tests/by-util/test_join.rs index 4b2d1bbbaee..86e60b69f70 100644 --- a/tests/by-util/test_join.rs +++ b/tests/by-util/test_join.rs @@ -75,6 +75,27 @@ fn different_field() { .stdout_only_fixture("different_field.expected"); } +#[test] +fn out_of_bounds_fields() { + new_ucmd!() + .arg("fields_1.txt") + .arg("fields_4.txt") + .arg("-1") + .arg("3") + .arg("-2") + .arg("5") + .succeeds() + .stdout_only_fixture("out_of_bounds_fields.expected"); + + new_ucmd!() + .arg("fields_1.txt") + .arg("fields_4.txt") + .arg("-j") + .arg("100000000000000000000") // > usize::MAX for 64 bits + .succeeds() + .stdout_only_fixture("out_of_bounds_fields.expected"); +} + #[test] fn unpaired_lines() { new_ucmd!() diff --git a/tests/fixtures/join/out_of_bounds_fields.expected b/tests/fixtures/join/out_of_bounds_fields.expected new file mode 100644 index 00000000000..98b0f84fe7d --- /dev/null +++ b/tests/fixtures/join/out_of_bounds_fields.expected @@ -0,0 +1,25 @@ + 1 2 c 1 cd + 1 3 d 2 de + 1 5 e 3 ef + 1 7 f 4 fg + 1 11 g 5 gh + 2 2 c 1 cd + 2 3 d 2 de + 2 5 e 3 ef + 2 7 f 4 fg + 2 11 g 5 gh + 3 2 c 1 cd + 3 3 d 2 de + 3 5 e 3 ef + 3 7 f 4 fg + 3 11 g 5 gh + 5 2 c 1 cd + 5 3 d 2 de + 5 5 e 3 ef + 5 7 f 4 fg + 5 11 g 5 gh + 8 2 c 1 cd + 8 3 d 2 de + 8 5 e 3 ef + 8 7 f 4 fg + 8 11 g 5 gh