Skip to content

Commit 0ae6d43

Browse files
authored
Refuse to translate if set2 contains more than one unique characters and set1 contains a character class (#6472)
* Refuse to translate if set2 contains > 1 unique characters
1 parent 7766257 commit 0ae6d43

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

src/uu/tr/src/operation.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub enum BadSequence {
3636
ClassExceptLowerUpperInSet2,
3737
ClassInSet2NotMatchedBySet1,
3838
Set1LongerSet2EndsInClass,
39+
ComplementMoreThanOneUniqueInSet2,
3940
}
4041

4142
impl Display for BadSequence {
@@ -66,6 +67,9 @@ impl Display for BadSequence {
6667
Self::Set1LongerSet2EndsInClass => {
6768
write!(f, "when translating with string1 longer than string2,\nthe latter string must not end with a character class")
6869
}
70+
Self::ComplementMoreThanOneUniqueInSet2 => {
71+
write!(f, "when translating with complemented character classes,\nstring2 must map all characters in the domain to one")
72+
}
6973
}
7074
}
7175
}
@@ -224,7 +228,6 @@ impl Sequence {
224228
.count();
225229

226230
let star_compensate_len = set1_len.saturating_sub(set2_len);
227-
228231
//Replace CharStar with CharRepeat
229232
set2 = set2
230233
.iter()
@@ -263,6 +266,21 @@ impl Sequence {
263266
.filter_map(to_u8)
264267
.collect();
265268

269+
// Calculate the set of unique characters in set2
270+
let mut set2_uniques = set2_solved.clone();
271+
set2_uniques.sort();
272+
set2_uniques.dedup();
273+
274+
//If the complement flag is used in translate mode, only one unique character may appear in
275+
//set2. Validate this with the set of uniques in set2 that we just generated.
276+
if set1.iter().any(|x| matches!(x, Self::Class(_)))
277+
&& translating
278+
&& complement_flag
279+
&& set2_uniques.len() > 1
280+
{
281+
return Err(BadSequence::ComplementMoreThanOneUniqueInSet2);
282+
}
283+
266284
if set2_solved.len() < set1_solved.len()
267285
&& !truncate_set1_flag
268286
&& matches!(

tests/by-util/test_tr.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,3 +1386,23 @@ fn check_set1_longer_set2_ends_in_class_with_trunc() {
13861386
.args(&["-t", "[:lower:]a", "[:upper:]"])
13871387
.succeeds();
13881388
}
1389+
1390+
#[test]
1391+
fn check_complement_2_unique_in_set2() {
1392+
let x226 = "x".repeat(226);
1393+
1394+
// [y*] is expanded tp "y" here
1395+
let arg = x226 + "[y*]xxx";
1396+
new_ucmd!().args(&["-c", "[:upper:]", arg.as_str()]).fails();
1397+
}
1398+
1399+
#[test]
1400+
fn check_complement_1_unique_in_set2() {
1401+
let x226 = "x".repeat(226);
1402+
1403+
// [y*] is expanded to "" here
1404+
let arg = x226 + "[y*]xxxx";
1405+
new_ucmd!()
1406+
.args(&["-c", "[:upper:]", arg.as_str()])
1407+
.succeeds();
1408+
}

0 commit comments

Comments
 (0)