diff --git a/CHANGELOG.md b/CHANGELOG.md index 01737ca..a80dacd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## 0.4.0 [unreleased] +### Bug Fixes + +1. [#49](https://github.com/InfluxCommunity/influxdb3-rust/pull/49): Extra validation on `Point#write_line_protocol()` to error out if fields contains any newline (`\n`) character. + ## 0.3.0 [2026-08-27] > ⚠️ This release requires Rust 1.91 or later. diff --git a/src/point.rs b/src/point.rs index c6423df..44edf38 100644 --- a/src/point.rs +++ b/src/point.rs @@ -259,6 +259,37 @@ impl Point { self.measurement ))); } + // VALIDATION: '\n' characters are not supported + for (k, v) in self.tags() { + if k.contains('\n') || v.contains('\n') { + return Err(Error::Config( + format!( + "tag '{k}' contains a line break which is unsupported in line protocol; point '{}'", + self.measurement + ) + )); + } + } + for (k, v) in self.fields() { + if k.contains('\n') { + return Err(Error::Config( + format!( + "field '{k}' contains a line break which is unsupported in line protocol; point '{}'", + self.measurement + ) + )); + } + if let FieldValue::String(s) = v { + if s.contains('\n') { + return Err(Error::Config( + format!( + "field '{k}' contains a line break which is unsupported in line protocol; point '{}'", + self.measurement + ) + )); + } + } + } // Measurement write_escaped_measurement(buf, &self.measurement); diff --git a/tests/point_tests.rs b/tests/point_tests.rs index 4c2bd73..ae588a4 100644 --- a/tests/point_tests.rs +++ b/tests/point_tests.rs @@ -80,3 +80,40 @@ fn last_write_wins() { assert_eq!(lp.matches("v=").count(), 1); assert!(lp.contains("v=2i")); } + +#[test] +#[should_panic = "contains a line break"] +fn tag_names_should_reject_newlines() { + Point::new("m") + .tag("t\nag", "value") + .field("v", 1) + .to_line_protocol(Precision::Nanosecond) + .unwrap(); +} +#[test] +#[should_panic = "contains a line break"] +fn tag_values_should_reject_newlines() { + Point::new("m") + .tag("tag", "val\nue") + .field("v", 1) + .to_line_protocol(Precision::Nanosecond) + .unwrap(); +} +#[test] +#[should_panic = "contains a line break"] +fn field_names_should_reject_newlines() { + Point::new("m") + .tag("tag", "value") + .field("fi\neld", 1) + .to_line_protocol(Precision::Nanosecond) + .unwrap(); +} + +#[test] +#[should_panic = "contains a line break"] +fn field_values_should_reject_newlines() { + Point::new("m") + .field("field", "val\nue") + .to_line_protocol(Precision::Nanosecond) + .unwrap(); +}