]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
jsonbuilder: fix serialization of nan and inf 10774/head
authorJason Ish <jason.ish@oisf.net>
Fri, 5 Apr 2024 14:35:36 +0000 (08:35 -0600)
committerJason Ish <jason.ish@oisf.net>
Fri, 5 Apr 2024 15:29:01 +0000 (09:29 -0600)
When outputting a float, check if its infinity, or not a number and
output a null instead.

Using a null was chosen as this is what serde_yaml, Firefox, Chrome,
Node, etc. do.

Ticket: #6921

rust/src/jsonbuilder.rs

index 7264be5c6b33bfe8af7de0a3d6202269dd739426..8b4296663689fa9179befd404b3154dc023bc0a1 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020 Open Information Security Foundation
+/* Copyright (C) 2020-2024 Open Information Security Foundation
  *
  * You can copy, redistribute or modify this Program under the terms of
  * the GNU General Public License version 2 as published by the Free
@@ -435,7 +435,7 @@ impl JsonBuilder {
                 return Err(JsonError::InvalidState);
             }
         }
-        self.push_str(&val.to_string())?;
+        self.push_float(val)?;
         Ok(self)
     }
 
@@ -650,7 +650,7 @@ impl JsonBuilder {
         self.push('"')?;
         self.push_str(key)?;
         self.push_str("\":")?;
-        self.push_str(&val.to_string())?;
+        self.push_float(val)?;
         Ok(self)
     }
 
@@ -681,6 +681,15 @@ impl JsonBuilder {
         self.buf.capacity()
     }
 
+    fn push_float(&mut self, val: f64) -> Result<(), JsonError> {
+       if val.is_nan() || val.is_infinite() {
+           self.push_str("null")?;
+       } else {
+           self.push_str(&val.to_string())?;
+       }
+       Ok(())
+    }
+
     /// Encode a string into the buffer, escaping as needed.
     ///
     /// The string is encoded into an intermediate vector as its faster
@@ -1339,6 +1348,48 @@ mod test {
         jb.close().unwrap();
         assert_eq!(jb.buf, r#"[1.1,2.2]"#);
     }
+
+    #[test]
+    fn test_set_nan() {
+        let mut jb = JsonBuilder::try_new_object().unwrap();
+        jb.set_float("nan", f64::NAN).unwrap();
+        jb.close().unwrap();
+        assert_eq!(jb.buf, r#"{"nan":null}"#);
+    }
+
+    #[test]
+    fn test_append_nan() {
+        let mut jb = JsonBuilder::try_new_array().unwrap();
+        jb.append_float(f64::NAN).unwrap();
+        jb.close().unwrap();
+        assert_eq!(jb.buf, r#"[null]"#);
+    }
+
+    #[test]
+    fn test_set_inf() {
+        let mut jb = JsonBuilder::try_new_object().unwrap();
+        jb.set_float("inf", f64::INFINITY).unwrap();
+        jb.close().unwrap();
+        assert_eq!(jb.buf, r#"{"inf":null}"#);
+
+        let mut jb = JsonBuilder::try_new_object().unwrap();
+        jb.set_float("inf", f64::NEG_INFINITY).unwrap();
+        jb.close().unwrap();
+        assert_eq!(jb.buf, r#"{"inf":null}"#);
+    }
+
+    #[test]
+    fn test_append_inf() {
+        let mut jb = JsonBuilder::try_new_array().unwrap();
+        jb.append_float(f64::INFINITY).unwrap();
+        jb.close().unwrap();
+        assert_eq!(jb.buf, r#"[null]"#);
+
+        let mut jb = JsonBuilder::try_new_array().unwrap();
+        jb.append_float(f64::NEG_INFINITY).unwrap();
+        jb.close().unwrap();
+        assert_eq!(jb.buf, r#"[null]"#);
+    }
 }
 
 // Escape table as seen in serde-json (MIT/Apache license)