Skip to content

Commit 4d35f2e

Browse files
committed
join: "support" field numbers larger than usize::MAX
They silently get folded to usize::MAX, which is the official GNU behavior.
1 parent 4fc47ab commit 4d35f2e

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

src/uu/join/src/join.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,8 +775,11 @@ fn get_field_number(keys: Option<usize>, key: Option<usize>) -> UResult<usize> {
775775
/// Parse the specified field string as a natural number and return
776776
/// the zero-based field number.
777777
fn parse_field_number(value: &str) -> UResult<usize> {
778+
// TODO: use ParseIntError.kind() once MSRV >= 1.55
779+
let overflow = "184467440737095516150".parse::<usize>().err().unwrap();
778780
match value.parse::<usize>() {
779781
Ok(result) if result > 0 => Ok(result - 1),
782+
Err(ref e) if *e == overflow => Ok(usize::MAX),
780783
_ => Err(USimpleError::new(
781784
1,
782785
format!("invalid field number: {}", value.quote()),

tests/by-util/test_join.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,27 @@ fn different_field() {
7575
.stdout_only_fixture("different_field.expected");
7676
}
7777

78+
#[test]
79+
fn out_of_bounds_fields() {
80+
new_ucmd!()
81+
.arg("fields_1.txt")
82+
.arg("fields_4.txt")
83+
.arg("-1")
84+
.arg("3")
85+
.arg("-2")
86+
.arg("5")
87+
.succeeds()
88+
.stdout_only_fixture("out_of_bounds_fields.expected");
89+
90+
new_ucmd!()
91+
.arg("fields_1.txt")
92+
.arg("fields_4.txt")
93+
.arg("-j")
94+
.arg("100000000000000000000") // > usize::MAX for 64 bits
95+
.succeeds()
96+
.stdout_only_fixture("out_of_bounds_fields.expected");
97+
}
98+
7899
#[test]
79100
fn unpaired_lines() {
80101
new_ucmd!()
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
1 2 c 1 cd
2+
1 3 d 2 de
3+
1 5 e 3 ef
4+
1 7 f 4 fg
5+
1 11 g 5 gh
6+
2 2 c 1 cd
7+
2 3 d 2 de
8+
2 5 e 3 ef
9+
2 7 f 4 fg
10+
2 11 g 5 gh
11+
3 2 c 1 cd
12+
3 3 d 2 de
13+
3 5 e 3 ef
14+
3 7 f 4 fg
15+
3 11 g 5 gh
16+
5 2 c 1 cd
17+
5 3 d 2 de
18+
5 5 e 3 ef
19+
5 7 f 4 fg
20+
5 11 g 5 gh
21+
8 2 c 1 cd
22+
8 3 d 2 de
23+
8 5 e 3 ef
24+
8 7 f 4 fg
25+
8 11 g 5 gh

0 commit comments

Comments
 (0)