From 0b70253e86a84e7b8cf93e4f447fb39c9ccb3d3b Mon Sep 17 00:00:00 2001 From: Daniel McCarney Date: Mon, 15 Apr 2024 23:38:20 -0400 Subject: [PATCH] rdata_parsers: fix handling of escaped list delim 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. --- .../src/serialize/txt/rdata_parsers/svcb.rs | 39 ++++++++++++++----- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs b/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs index d66f4def7..1840f1ec7 100644 --- a/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs +++ b/crates/proto/src/serialize/txt/rdata_parsers/svcb.rs @@ -325,12 +325,36 @@ where T::Err: Into, { let mut result = Vec::new(); + let mut current_value = String::new(); + let mut escaping = false; + + for c in value.chars() { + match (c, escaping) { + // End of value + (',', false) => { + result.push(T::from_str(&parse_char_data(¤t_value)?).map_err(Into::into)?); + current_value.clear() + } + // Start of escape sequence + ('\\', false) => escaping = true, + // Comma inside escape sequence + (',', true) => { + current_value.push(','); + escaping = false + } + // Regular character inside escape sequence + (_, true) => { + current_value.push(c); + escaping = false + } + // Regular character + (_, false) => 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())?; - result.push(value); + // Push the remaining value if there's any + if !current_value.is_empty() { + result.push(T::from_str(&parse_char_data(¤t_value)?).map_err(Into::into)?); } Ok(result) @@ -452,7 +476,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 { @@ -553,8 +577,6 @@ mod tests { ], }, // Figure 10: An "alpn" Value with an Escaped Comma and an Escaped Backslash in Two Presentation Formats - /* - * TODO(XXX): Parser does not support escaped list delimiter. TestVector { record: r#"example.com. 42 SVCB 16 foo.example.org. alpn="f\\\\oo\,bar,h2""#, record_type: RecordType::SVCB, @@ -565,7 +587,6 @@ mod tests { 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.