Skip to content

Commit

Permalink
rdata_parsers: fix handling of escaped list delim
Browse files Browse the repository at this point in the history
The RFC 9460 presentation syntax allows escaping the ',' list separator
in a `SvcParamValue` by writing `\,`. This commit updates `parse_list`
to handle this case.

Once this is done, one of the RFC 9460 test vectors using this feature
can be added to the unit tests. We don't yet support the more
complicated escaped comma using an escaped backslash for delimiter
escape so one remaining test vector for this is left out.
  • Loading branch information
cpu committed Apr 16, 2024
1 parent c397b6a commit fdf246f
Showing 1 changed file with 61 additions and 8 deletions.
69 changes: 61 additions & 8 deletions crates/proto/src/serialize/txt/rdata_parsers/svcb.rs
Expand Up @@ -325,11 +325,43 @@ where
T::Err: Into<ParseError>,
{
let mut result = Vec::new();
let mut current_value = String::new();
let mut escaped = false;

for c in value.chars() {
match (c, escaped) {
(',', false) => {
// End of value
let parsed_value = parse_char_data(&current_value)?;
let value = T::from_str(&parsed_value).map_err(|e| e.into())?;
result.push(value);
current_value.clear();
}
('\\', false) => {
// Start of escape sequence
escaped = true;
}
(',', true) => {
// Comma inside escape sequence
current_value.push(',');
escaped = false;
}
(_, true) => {
// Regular character inside escape sequence
current_value.push(c);
escaped = false;
}
(_, false) => {
// Regular character
current_value.push(c);
}
}
}

let values = value.trim_end_matches(',').split(',');
for value in values {
let value = parse_char_data(value)?;
let value = T::from_str(&value).map_err(|e| e.into())?;
// Push the remaining value if there's any
if !current_value.is_empty() {
let parsed_value = parse_char_data(&current_value)?;
let value = T::from_str(&parsed_value).map_err(|e| e.into())?;
result.push(value);
}

Expand Down Expand Up @@ -452,7 +484,7 @@ mod tests {

// NOTE: In each case the test vector from the RFC was augmented with a TTL (42 in each
// case. The parser requires this but the test vectors do not include it.
let vectors: [TestVector; 8] = [
let vectors: [TestVector; 9] = [
// https://datatracker.ietf.org/doc/html/rfc9460#appendix-D.1
// Figure 2: AliasMode
TestVector {
Expand Down Expand Up @@ -553,9 +585,30 @@ mod tests {
],
},
// Figure 10: An "alpn" Value with an Escaped Comma and an Escaped Backslash in Two Presentation Formats
// example.com. SVCB 16 foo.example.org. alpn="f\\\\oo\\,bar,h2"
// example.com. SVCB 16 foo.example.org. alpn=f\\\092oo\092,bar,h2
// TODO(XXX): Parser does not handle escaped comma correctly and splits when it shouldn't.
TestVector {
record: r#"example.com. 42 SVCB 16 foo.example.org. alpn="f\\\\oo\,bar,h2""#,
record_type: RecordType::SVCB,
target_name: Name::from_str("foo.example.org.").unwrap(),
priority: 16,
params: vec![(
SvcParamKey::Alpn,
SvcParamValue::Alpn(Alpn(vec![r#"f\\oo,bar"#.to_owned(), "h2".to_owned()])),
)],
},
/*
* TODO(XXX): Parser does not replace escaped characters, does not see "\092," as
* an escaped delim.
TestVector {
record: r#"example.com. 42 SVCB 116 foo.example.org. alpn=f\\\092oo\092,bar,h2""#,
record_type: RecordType::SVCB,
target_name: Name::from_str("foo.example.org.").unwrap(),
priority: 16,
params: vec![(
SvcParamKey::Alpn,
SvcParamValue::Alpn(Alpn(vec![r#"f\\oo,bar"#.to_owned(), "h2".to_owned()])),
)],
},
*/
];

for record in vectors {
Expand Down

0 comments on commit fdf246f

Please sign in to comment.