review: a key split by an invisible character is still a secret
has_secret masked each character a character rule matches to a space, so one zero-width space inside a key cut it into two runs too short to match. The secret rules now also run on the text with those characters deleted, and the text is a secret if either matches. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -78,21 +78,24 @@ pub fn peer_name(speaker: &str) -> String {
|
||||
|
||||
/// Whether `text` holds a known-prefix secret, by `refuse`'s secret rules alone. `refuse` gives
|
||||
/// only the first rule a text breaks, and its character rules come first, so each character they
|
||||
/// match is first replaced by a space: it is not a key character and not a letter, so a secret's
|
||||
/// prefix and run are found as before, and a carriage return cannot hide a key.
|
||||
/// match is taken out of the way, in two ways, and the text is a secret if either is: replaced by
|
||||
/// a space, which is not a key character and not a letter, so a secret's prefix and run are found
|
||||
/// as before and a carriage return cannot hide a key; and deleted, so that one inside a key cannot
|
||||
/// split it into two runs too short to match.
|
||||
pub fn has_secret(text: &str) -> bool {
|
||||
let mut buf = [0u8; 4];
|
||||
let masked: String = text
|
||||
.chars()
|
||||
.map(|c| {
|
||||
if refuse(c.encode_utf8(&mut buf)).is_some() {
|
||||
' '
|
||||
} else {
|
||||
c
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
refuse(&masked).is_some_and(|r| r.rule.starts_with("secret-"))
|
||||
let mut masked = String::with_capacity(text.len());
|
||||
let mut deleted = String::with_capacity(text.len());
|
||||
for c in text.chars() {
|
||||
if refuse(c.encode_utf8(&mut buf)).is_some() {
|
||||
masked.push(' ');
|
||||
} else {
|
||||
masked.push(c);
|
||||
deleted.push(c);
|
||||
}
|
||||
}
|
||||
let secret = |t: &str| refuse(t).is_some_and(|r| r.rule.starts_with("secret-"));
|
||||
secret(&masked) || secret(&deleted)
|
||||
}
|
||||
|
||||
/// The turn's user text and its speaker, from its first record, the `User` one.
|
||||
|
||||
Reference in New Issue
Block a user