fix: Do not allow a raw newline in the middle of measurement / tag_set / field_key
parent
261528aeab
commit
d7416da962
|
@ -381,7 +381,7 @@ fn series(i: &str) -> IResult<&str, Series<'_>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measurement(i: &str) -> IResult<&str, EscapedStr<'_>> {
|
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 space = map(tag(" "), |_| " ");
|
||||||
let comma = 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<'_>> {
|
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)
|
escaped_value(normal_char)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tag_value(i: &str) -> IResult<&str, EscapedStr<'_>> {
|
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)
|
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<'_>> {
|
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)
|
escaped_value(normal_char)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +446,7 @@ fn timestamp(i: &str) -> IResult<&str, i64> {
|
||||||
fn line_whitespace(mut i: &str) -> IResult<&str, ()> {
|
fn line_whitespace(mut i: &str) -> IResult<&str, ()> {
|
||||||
loop {
|
loop {
|
||||||
let offset = i
|
let offset = i
|
||||||
.find(|c| c != ' ' && c != '\t' && c != '\n')
|
.find(|c| !is_whitespace_boundary_char(c))
|
||||||
.unwrap_or_else(|| i.len());
|
.unwrap_or_else(|| i.len());
|
||||||
i = &i[offset..];
|
i = &i[offset..];
|
||||||
|
|
||||||
|
@ -463,6 +463,10 @@ fn whitespace(i: &str) -> IResult<&str, &str> {
|
||||||
take_while1(|c| c == ' ')(i)
|
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
|
/// While not all of these escape characters are required to be
|
||||||
/// escaped, we support the client escaping them proactively to
|
/// escaped, we support the client escaping them proactively to
|
||||||
/// provide a common experience.
|
/// provide a common experience.
|
||||||
|
@ -518,6 +522,16 @@ where
|
||||||
Err(nom::Err::Error(_)) => {
|
Err(nom::Err::Error(_)) => {
|
||||||
result.push(escape_char);
|
result.push(escape_char);
|
||||||
head = after;
|
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),
|
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]
|
#[test]
|
||||||
fn tag_key_allows_escaping_comma() -> Result {
|
fn tag_key_allows_escaping_comma() -> Result {
|
||||||
assert_fully_parsed!(tag_key(r#"wea\,ther"#), r#"wea,ther"#)
|
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]
|
#[test]
|
||||||
fn tag_value_allows_escaping_comma() -> Result {
|
fn tag_value_allows_escaping_comma() -> Result {
|
||||||
assert_fully_parsed!(tag_value(r#"wea\,ther"#), r#"wea,ther"#)
|
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]
|
#[test]
|
||||||
fn field_key_allows_escaping_comma() -> Result {
|
fn field_key_allows_escaping_comma() -> Result {
|
||||||
assert_fully_parsed!(field_key(r#"wea\,ther"#), r#"wea,ther"#)
|
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]
|
#[test]
|
||||||
fn index_pairs() {
|
fn index_pairs() {
|
||||||
let p = Point {
|
let p = Point {
|
||||||
|
|
Loading…
Reference in New Issue