Skip to main content

sofie_core/
display.rs

1/// They reorder or hide text where it is shown (CVE-2021-42574). Unicode 16.0's format (Cf) list,
2/// written out to need no dependency, keeps ZWJ and ZWNJ, which Persian and Devanagari spell with.
3#[must_use]
4pub fn misleads_display(character: char) -> bool {
5    character.is_control()
6        || matches!(
7            character,
8            '\u{00AD}'
9                | '\u{0600}'..='\u{0605}'
10                | '\u{061C}'
11                | '\u{06DD}'
12                | '\u{070F}'
13                | '\u{0890}'..='\u{0891}'
14                | '\u{08E2}'
15                | '\u{115F}'..='\u{1160}'
16                | '\u{180E}'
17                | '\u{200B}'
18                | '\u{200E}'..='\u{200F}'
19                | '\u{2028}'..='\u{202E}'
20                | '\u{2060}'..='\u{2064}'
21                | '\u{2066}'..='\u{206F}'
22                | '\u{3164}'
23                | '\u{FEFF}'
24                | '\u{FFA0}'
25                | '\u{FFF9}'..='\u{FFFB}'
26                | '\u{110BD}'
27                | '\u{110CD}'
28                | '\u{13430}'..='\u{1343F}'
29                | '\u{1BCA0}'..='\u{1BCA3}'
30                | '\u{1D173}'..='\u{1D17A}'
31                | '\u{E0001}'
32                | '\u{E0020}'..='\u{E007F}'
33        )
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39
40    #[test]
41    fn refuses_reordering_and_hiding_but_keeps_joiners() {
42        for refused in [
43            '\u{0}', '\n', '\u{1B}', '\u{202E}', '\u{2067}', '\u{200B}', '\u{FEFF}', '\u{200F}',
44            '\u{061C}', '\u{2028}',
45        ] {
46            assert!(misleads_display(refused), "{refused:?}");
47        }
48        for kept in ['a', 'é', 'ş', '\u{200C}', '\u{200D}', ' '] {
49            assert!(!misleads_display(kept), "{kept:?}");
50        }
51    }
52
53    #[test]
54    fn refuses_every_format_character_and_the_hangul_fillers() {
55        for invisible in [
56            '\u{00AD}',
57            '\u{3164}',
58            '\u{E0067}',
59            '\u{2062}',
60            '\u{180E}',
61            '\u{206A}',
62            '\u{FFFB}',
63            '\u{0601}',
64            '\u{1BCA0}',
65            '\u{1D173}',
66        ] {
67            assert!(misleads_display(invisible), "{invisible:?}");
68        }
69    }
70}