message: parse on space (0x20) only per RFC — trim_start() also ate tabs, so a param containing a tab (e.g. a trailing ':\t') didn't round-trip through to_wire/parse; the parser fuzz proptest found it. trim_start_matches(' ') makes tabs ordinary param content; regression case pinned
This commit is contained in:
parent
98e5cf4d20
commit
11852332dc
2 changed files with 12 additions and 5 deletions
7
proptest-regressions/message.txt
Normal file
7
proptest-regressions/message.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Seeds for failure cases proptest has generated in the past. It is
|
||||||
|
# automatically read and these particular cases re-run before any
|
||||||
|
# novel cases are generated.
|
||||||
|
#
|
||||||
|
# It is recommended to check this file in to source control so that
|
||||||
|
# everyone who runs the test benefits from these saved cases.
|
||||||
|
cc 19cc356a7360943bfb23bdff0f579425f8957a37395bc952950f8f2250d047a3 # shrinks to line = "0 :\t"
|
||||||
|
|
@ -48,7 +48,7 @@ impl Message {
|
||||||
|
|
||||||
/// Parse one wire line. Returns `None` for an empty/garbage line.
|
/// Parse one wire line. Returns `None` for an empty/garbage line.
|
||||||
pub fn parse(line: &str) -> Option<Message> {
|
pub fn parse(line: &str) -> Option<Message> {
|
||||||
let mut rest = line.trim_start();
|
let mut rest = line.trim_start_matches(' ');
|
||||||
|
|
||||||
// IRCv3 message tags — keep the client-only (`+`) tags for relay, drop the rest.
|
// IRCv3 message tags — keep the client-only (`+`) tags for relay, drop the rest.
|
||||||
let mut ctags = String::new();
|
let mut ctags = String::new();
|
||||||
|
|
@ -71,18 +71,18 @@ pub fn parse(line: &str) -> Option<Message> {
|
||||||
.find_map(|t| t.strip_prefix("batch="))
|
.find_map(|t| t.strip_prefix("batch="))
|
||||||
.map(|v| v.to_string());
|
.map(|v| v.to_string());
|
||||||
concat = tags.split(';').any(|t| t == "draft/multiline-concat");
|
concat = tags.split(';').any(|t| t == "draft/multiline-concat");
|
||||||
rest = r.trim_start();
|
rest = r.trim_start_matches(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut source = None;
|
let mut source = None;
|
||||||
if let Some(after_colon) = rest.strip_prefix(':') {
|
if let Some(after_colon) = rest.strip_prefix(':') {
|
||||||
let (src, r) = after_colon.split_once(' ')?;
|
let (src, r) = after_colon.split_once(' ')?;
|
||||||
source = Some(src.to_string());
|
source = Some(src.to_string());
|
||||||
rest = r.trim_start();
|
rest = r.trim_start_matches(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
let (cmd, mut rest) = match rest.split_once(' ') {
|
let (cmd, mut rest) = match rest.split_once(' ') {
|
||||||
Some((c, r)) => (c, r.trim_start()),
|
Some((c, r)) => (c, r.trim_start_matches(' ')),
|
||||||
None => (rest, ""),
|
None => (rest, ""),
|
||||||
};
|
};
|
||||||
if cmd.is_empty() {
|
if cmd.is_empty() {
|
||||||
|
|
@ -98,7 +98,7 @@ pub fn parse(line: &str) -> Option<Message> {
|
||||||
match rest.split_once(' ') {
|
match rest.split_once(' ') {
|
||||||
Some((p, r)) => {
|
Some((p, r)) => {
|
||||||
params.push(p.to_string());
|
params.push(p.to_string());
|
||||||
rest = r.trim_start();
|
rest = r.trim_start_matches(' ');
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
params.push(rest.to_string());
|
params.push(rest.to_string());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue