validation: reject control characters in bio and sync device name (ultra-fuzz NOTE tail)
Closes the Run 2 NOTE that validate_bio and validate_sync_device_name accepted
control characters, while display-name and sync-app-name already rejected them.
Bio allows newlines/tabs (multi-line) but not other control chars; device name
rejects all control chars, mirroring validate_sync_app_name. Tests cover NUL and
escape. (Bidi/format chars are a separate Trojan-source concern, out of scope
for this NOTE; is_control() matches the existing validators' policy.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2 files changed,
+21 insertions,
-0 deletions
| 133 |
133 |
|
limits::SYNC_DEVICE_NAME_MAX
|
| 134 |
134 |
|
)));
|
| 135 |
135 |
|
}
|
|
136 |
+ |
// Reject control characters, mirroring `validate_sync_app_name`.
|
|
137 |
+ |
if name.chars().any(|c| c.is_control()) {
|
|
138 |
+ |
return Err(AppError::validation(
|
|
139 |
+ |
"Device name must not contain control characters".to_string(),
|
|
140 |
+ |
));
|
|
141 |
+ |
}
|
| 136 |
142 |
|
Ok(())
|
| 137 |
143 |
|
}
|
| 138 |
144 |
|
|
| 234 |
240 |
|
assert!(validate_sync_device_name("Max's MacBook").is_ok());
|
| 235 |
241 |
|
assert!(validate_sync_device_name("").is_err());
|
| 236 |
242 |
|
assert!(validate_sync_device_name(&"a".repeat(101)).is_err());
|
|
243 |
+ |
// Control characters (NUL, escape) are rejected.
|
|
244 |
+ |
assert!(validate_sync_device_name("laptop\u{0}").is_err());
|
|
245 |
+ |
assert!(validate_sync_device_name("laptop\u{1b}evil").is_err());
|
| 237 |
246 |
|
}
|
| 238 |
247 |
|
|
| 239 |
248 |
|
#[test]
|
| 29 |
29 |
|
limits::BIO_MAX
|
| 30 |
30 |
|
)));
|
| 31 |
31 |
|
}
|
|
32 |
+ |
// Reject control characters (NUL, escape, etc.) while allowing normal
|
|
33 |
+ |
// whitespace (newlines/tabs) so multi-line bios still work. Mirrors the
|
|
34 |
+ |
// display-name and sync-app-name validators.
|
|
35 |
+ |
if bio.chars().any(|c| c.is_control() && !matches!(c, '\n' | '\r' | '\t')) {
|
|
36 |
+ |
return Err(AppError::validation(
|
|
37 |
+ |
"Bio must not contain control characters".to_string(),
|
|
38 |
+ |
));
|
|
39 |
+ |
}
|
| 32 |
40 |
|
Ok(())
|
| 33 |
41 |
|
}
|
| 34 |
42 |
|
|
| 233 |
241 |
|
assert!(validate_bio("I make music").is_ok());
|
| 234 |
242 |
|
assert!(validate_bio("").is_ok());
|
| 235 |
243 |
|
assert!(validate_bio(&"a".repeat(2001)).is_err());
|
|
244 |
+ |
// Newlines/tabs are fine (multi-line bios); other control chars aren't.
|
|
245 |
+ |
assert!(validate_bio("line one\nline two\ttabbed").is_ok());
|
|
246 |
+ |
assert!(validate_bio("evil\u{0}nul").is_err());
|
|
247 |
+ |
assert!(validate_bio("esc\u{1b}ape").is_err());
|
| 236 |
248 |
|
}
|
| 237 |
249 |
|
|
| 238 |
250 |
|
#[test]
|