Commits:
3 changed files:
Changes:
toolkit/components/tor-integration/tor_provider/src/ctor/controller/escape.rs
| ... |
... |
@@ -58,9 +58,56 @@ mod tests { |
|
58
|
58
|
}
|
|
59
|
59
|
|
|
60
|
60
|
#[test]
|
|
61
|
|
- fn escaped() {
|
|
|
61
|
+ fn escaped_special_chars() {
|
|
|
62
|
+ assert_eq!(tor_escape("'"), "\"\\'\"");
|
|
|
63
|
+ assert_eq!(tor_escape("\""), "\"\\\"\"");
|
|
|
64
|
+ assert_eq!(tor_escape("\\"), "\"\\\\\"");
|
|
62
|
65
|
assert_eq!(tor_escape("'\"\\\r\n\t"), "\"\\'\\\"\\\\\\r\\n\\t\"");
|
|
|
66
|
+ }
|
|
|
67
|
+
|
|
|
68
|
+ #[test]
|
|
|
69
|
+ fn escaped_control_chars() {
|
|
|
70
|
+ assert_eq!(tor_escape("\n"), "\"\\n\"");
|
|
|
71
|
+ assert_eq!(tor_escape("\t"), "\"\\t\"");
|
|
|
72
|
+ assert_eq!(tor_escape("\r"), "\"\\r\"");
|
|
|
73
|
+ }
|
|
|
74
|
+
|
|
|
75
|
+ #[test]
|
|
|
76
|
+ fn ascii_printable_boundaries() {
|
|
|
77
|
+ // 0x1F is just below the printable range and must be hex-escaped.
|
|
|
78
|
+ assert_eq!(tor_escape(b"\x1F"), "\"\\x1F\"");
|
|
|
79
|
+ // 0x20 (space) is the first byte of the printable range.
|
|
|
80
|
+ assert_eq!(tor_escape(b"\x20"), "\" \"");
|
|
|
81
|
+ // 0x7E ('~') is the last byte of the printable range.
|
|
|
82
|
+ assert_eq!(tor_escape(b"\x7E"), "\"~\"");
|
|
|
83
|
+ // 0x7F (DEL) is just above the printable range and must be hex-escaped.
|
|
|
84
|
+ assert_eq!(tor_escape(b"\x7F"), "\"\\x7F\"");
|
|
|
85
|
+ }
|
|
|
86
|
+
|
|
|
87
|
+ #[test]
|
|
|
88
|
+ fn hex_zero_padding() {
|
|
63
|
89
|
assert_eq!(tor_escape("\0"), "\"\\x00\"");
|
|
|
90
|
+ assert_eq!(tor_escape(b"\x0B"), "\"\\x0B\"");
|
|
|
91
|
+ assert_eq!(tor_escape(b"\x01"), "\"\\x01\"");
|
|
|
92
|
+ }
|
|
|
93
|
+
|
|
|
94
|
+ #[test]
|
|
|
95
|
+ fn hex_uppercase() {
|
|
|
96
|
+ assert_eq!(tor_escape(b"\xAB"), "\"\\xAB\"");
|
|
|
97
|
+ assert_eq!(tor_escape(b"\xFF"), "\"\\xFF\"");
|
|
|
98
|
+ }
|
|
|
99
|
+
|
|
|
100
|
+ #[test]
|
|
|
101
|
+ fn non_utf8_bytes() {
|
|
|
102
|
+ // Raw invalid UTF-8 bytes are escaped byte-by-byte, same as any
|
|
|
103
|
+ // other non-printable byte.
|
|
|
104
|
+ assert_eq!(tor_escape(b"\xF5"), "\"\\xF5\"");
|
|
|
105
|
+ assert_eq!(tor_escape(b"\xFF\xFE"), "\"\\xFF\\xFE\"");
|
|
|
106
|
+ assert_eq!(tor_escape(b"te\xF5st"), "\"te\\xF5st\"");
|
|
|
107
|
+ }
|
|
|
108
|
+
|
|
|
109
|
+ #[test]
|
|
|
110
|
+ fn unicode() {
|
|
64
|
111
|
assert_eq!(tor_escape("\u{1F9C5}"), "\"\\xF0\\x9F\\xA7\\x85\"");
|
|
65
|
112
|
}
|
|
66
|
113
|
} |
toolkit/components/tor-integration/tor_provider/src/ctor/controller/mod.rs
| ... |
... |
@@ -8,3 +8,42 @@ mod unescape; |
|
8
|
8
|
|
|
9
|
9
|
use escape::*;
|
|
10
|
10
|
use unescape::*;
|
|
|
11
|
+
|
|
|
12
|
+#[cfg(test)]
|
|
|
13
|
+mod tests {
|
|
|
14
|
+ use super::*;
|
|
|
15
|
+
|
|
|
16
|
+ fn round_trip(buf: &[u8]) {
|
|
|
17
|
+ let mut escaped = String::new();
|
|
|
18
|
+ tor_escape_into(buf, &mut escaped);
|
|
|
19
|
+ assert_eq!(&*tor_unescape(escaped.as_bytes()).unwrap(), buf);
|
|
|
20
|
+ }
|
|
|
21
|
+
|
|
|
22
|
+ #[test]
|
|
|
23
|
+ fn round_trip_simple() {
|
|
|
24
|
+ round_trip(b"test");
|
|
|
25
|
+ }
|
|
|
26
|
+
|
|
|
27
|
+ #[test]
|
|
|
28
|
+ fn round_trip_empty() {
|
|
|
29
|
+ round_trip(b"");
|
|
|
30
|
+ }
|
|
|
31
|
+
|
|
|
32
|
+ #[test]
|
|
|
33
|
+ fn round_trip_special_chars() {
|
|
|
34
|
+ round_trip(b"'\"\\\r\n\t");
|
|
|
35
|
+ }
|
|
|
36
|
+
|
|
|
37
|
+ #[test]
|
|
|
38
|
+ fn round_trip_non_utf8() {
|
|
|
39
|
+ round_trip(b"\xF5\xFF\xFE");
|
|
|
40
|
+ }
|
|
|
41
|
+
|
|
|
42
|
+ #[test]
|
|
|
43
|
+ fn round_trip_all_bytes() {
|
|
|
44
|
+ // Every possible byte value, escaped then unescaped,
|
|
|
45
|
+ // must come back unchanged.
|
|
|
46
|
+ let all_bytes: Vec<u8> = (0..=255).collect();
|
|
|
47
|
+ round_trip(&all_bytes);
|
|
|
48
|
+ }
|
|
|
49
|
+} |
toolkit/components/tor-integration/tor_provider/src/ctor/controller/unescape.rs
| ... |
... |
@@ -140,6 +140,26 @@ mod tests { |
|
140
|
140
|
assert_eq!(&*tor_unescape(b"\"\"").unwrap(), &[]);
|
|
141
|
141
|
}
|
|
142
|
142
|
|
|
|
143
|
+ #[test]
|
|
|
144
|
+ fn lone_quote() {
|
|
|
145
|
+ // A single quote character is not a valid empty quoted string: there
|
|
|
146
|
+ // is no closing quote.
|
|
|
147
|
+ assert_eq!(
|
|
|
148
|
+ tor_unescape(b"\"").unwrap_err(),
|
|
|
149
|
+ UnescapeError::Unterminated
|
|
|
150
|
+ );
|
|
|
151
|
+ }
|
|
|
152
|
+
|
|
|
153
|
+ #[test]
|
|
|
154
|
+ fn quoted_spaces() {
|
|
|
155
|
+ // Spaces are only rejected in unquoted strings, so they must be
|
|
|
156
|
+ // preserved as-is once inside quotes.
|
|
|
157
|
+ assert_eq!(&*tor_unescape(b"\"test test\"").unwrap(), b"test test");
|
|
|
158
|
+ assert_eq!(&*tor_unescape(b"\" test\"").unwrap(), b" test");
|
|
|
159
|
+ assert_eq!(&*tor_unescape(b"\"test \"").unwrap(), b"test ");
|
|
|
160
|
+ assert_eq!(&*tor_unescape(b"\"t e s t\"").unwrap(), b"t e s t");
|
|
|
161
|
+ }
|
|
|
162
|
+
|
|
143
|
163
|
#[test]
|
|
144
|
164
|
fn unescape_simple() {
|
|
145
|
165
|
assert_eq!(&*tor_unescape(b"\"\\n\"").unwrap(), b"\n");
|
| ... |
... |
@@ -190,6 +210,23 @@ mod tests { |
|
190
|
210
|
assert_eq!(&*tor_unescape(b"\"\\40test\\0\"").unwrap(), b" test\0");
|
|
191
|
211
|
}
|
|
192
|
212
|
|
|
|
213
|
+ #[test]
|
|
|
214
|
+ fn unescape_octal_max_digits() {
|
|
|
215
|
+ // Only up to 3 octal digits are consumed per escape, even if a 4th
|
|
|
216
|
+ // digit-looking byte follows.
|
|
|
217
|
+ assert_eq!(&*tor_unescape(b"\"\\0004\"").unwrap(), b"\x004");
|
|
|
218
|
+ assert_eq!(&*tor_unescape(b"\"\\0007\"").unwrap(), b"\x007");
|
|
|
219
|
+ }
|
|
|
220
|
+
|
|
|
221
|
+ #[test]
|
|
|
222
|
+ fn unescape_octal_ambiguous_digit() {
|
|
|
223
|
+ // '8' and '9' are not valid octal digits, so they end the escape
|
|
|
224
|
+ // early and are then treated as literal characters, even though at
|
|
|
225
|
+ // a glance "\048" looks like it could mean octal 048.
|
|
|
226
|
+ assert_eq!(&*tor_unescape(b"\"\\048\"").unwrap(), b"\x048");
|
|
|
227
|
+ assert_eq!(&*tor_unescape(b"\"\\09\"").unwrap(), b"\x009");
|
|
|
228
|
+ }
|
|
|
229
|
+
|
|
193
|
230
|
#[test]
|
|
194
|
231
|
fn invalid_unicode() {
|
|
195
|
232
|
// Raw invalid sequence, without quotes
|
| ... |
... |
@@ -287,4 +324,13 @@ mod tests { |
|
287
|
324
|
UnescapeError::OctalOverflow,
|
|
288
|
325
|
);
|
|
289
|
326
|
}
|
|
|
327
|
+
|
|
|
328
|
+ #[test]
|
|
|
329
|
+ fn stress() {
|
|
|
330
|
+ // A mix of literals, spaces, and every kind of escape back to back.
|
|
|
331
|
+ assert_eq!(
|
|
|
332
|
+ &*tor_unescape(b"\"a \\n b\\tc\\r\\\\d\\'e\\\"f\\x20g\\040h\\048\"").unwrap(),
|
|
|
333
|
+ b"a \n b\tc\r\\d'e\"f g h\x048"
|
|
|
334
|
+ );
|
|
|
335
|
+ }
|
|
290
|
336
|
} |
|