fix: Do not allow a raw newline in the middle of measurement / tag_set / field_key

pull/24376/head
Jake Goulding 2020-04-01 10:55:31 -04:00
parent 261528aeab
commit d7416da962
1 changed files with 67 additions and 5 deletions

View File

@ -381,7 +381,7 @@ fn series(i: &str) -> IResult<&str, Series<'_>> {
}
fn measurement(i: &str) -> IResult<&str, EscapedStr<'_>> {
let normal_char = take_while1(|c| c != ' ' && c != ',' && c != '\\');
let normal_char = take_while1(|c| !is_whitespace_boundary_char(c) && c != ',' && c != '\\');
let space = map(tag(" "), |_| " ");
let comma = map(tag(","), |_| ",");
@ -398,13 +398,13 @@ fn tag_set(i: &str) -> IResult<&str, TagSet<'_>> {
}
fn tag_key(i: &str) -> IResult<&str, EscapedStr<'_>> {
let normal_char = take_while1(|c| c != '=' && c != '\\');
let normal_char = take_while1(|c| !is_whitespace_boundary_char(c) && c != '=' && c != '\\');
escaped_value(normal_char)(i)
}
fn tag_value(i: &str) -> IResult<&str, EscapedStr<'_>> {
let normal_char = take_while1(|c| c != ',' && c != ' ' && c != '\\');
let normal_char = take_while1(|c| !is_whitespace_boundary_char(c) && c != ',' && c != '\\');
escaped_value(normal_char)(i)
}
@ -414,7 +414,7 @@ fn field_set(i: &str) -> IResult<&str, FieldSet<'_>> {
}
fn field_key(i: &str) -> IResult<&str, EscapedStr<'_>> {
let normal_char = take_while1(|c| c != '=' && c != '\\');
let normal_char = take_while1(|c| !is_whitespace_boundary_char(c) && c != '=' && c != '\\');
escaped_value(normal_char)(i)
}
@ -446,7 +446,7 @@ fn timestamp(i: &str) -> IResult<&str, i64> {
fn line_whitespace(mut i: &str) -> IResult<&str, ()> {
loop {
let offset = i
.find(|c| c != ' ' && c != '\t' && c != '\n')
.find(|c| !is_whitespace_boundary_char(c))
.unwrap_or_else(|| i.len());
i = &i[offset..];
@ -463,6 +463,10 @@ fn whitespace(i: &str) -> IResult<&str, &str> {
take_while1(|c| c == ' ')(i)
}
fn is_whitespace_boundary_char(c: char) -> bool {
c == ' ' || c == '\t' || c == '\n'
}
/// While not all of these escape characters are required to be
/// escaped, we support the client escaping them proactively to
/// provide a common experience.
@ -518,6 +522,16 @@ where
Err(nom::Err::Error(_)) => {
result.push(escape_char);
head = after;
// The Go parser assumes that *any* unknown escaped character is valid.
match head.chars().next() {
Some(c) => {
let (escaped, remaining) = head.split_at(c.len_utf8());
result.push(escaped);
head = remaining;
}
None => return Ok((head, EscapedStr(result))),
}
}
Err(e) => return Err(e),
}
@ -850,6 +864,18 @@ her"#
)
}
#[test]
fn measurement_disallows_literal_newline() -> Result {
let (remaining, parsed) = measurement(
r#"weat
her"#,
)?;
assert_eq!(parsed, "weat");
assert_eq!(remaining, "\nher");
Ok(())
}
#[test]
fn tag_key_allows_escaping_comma() -> Result {
assert_fully_parsed!(tag_key(r#"wea\,ther"#), r#"wea,ther"#)
@ -886,6 +912,18 @@ her"#
)
}
#[test]
fn tag_key_disallows_literal_newline() -> Result {
let (remaining, parsed) = tag_key(
r#"weat
her"#,
)?;
assert_eq!(parsed, "weat");
assert_eq!(remaining, "\nher");
Ok(())
}
#[test]
fn tag_value_allows_escaping_comma() -> Result {
assert_fully_parsed!(tag_value(r#"wea\,ther"#), r#"wea,ther"#)
@ -922,6 +960,18 @@ her"#
)
}
#[test]
fn tag_value_disallows_literal_newline() -> Result {
let (remaining, parsed) = tag_value(
r#"weat
her"#,
)?;
assert_eq!(parsed, "weat");
assert_eq!(remaining, "\nher");
Ok(())
}
#[test]
fn field_key_allows_escaping_comma() -> Result {
assert_fully_parsed!(field_key(r#"wea\,ther"#), r#"wea,ther"#)
@ -958,6 +1008,18 @@ her"#
)
}
#[test]
fn field_key_disallows_literal_newline() -> Result {
let (remaining, parsed) = field_key(
r#"weat
her"#,
)?;
assert_eq!(parsed, "weat");
assert_eq!(remaining, "\nher");
Ok(())
}
#[test]
fn index_pairs() {
let p = Point {