]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/json: only output printable characters
authorJason Ish <ish@unx.ca>
Fri, 16 Jun 2017 05:38:04 +0000 (23:38 -0600)
committerJason Ish <ish@unx.ca>
Sat, 17 Jun 2017 16:32:37 +0000 (10:32 -0600)
Rust strings are UTF8 and we cannot yet rely on jansson
having json_stringn on all supported OS distributions yet
so sanitize strings to ascii before printing.

Also add set_string_from_bytes which is like set_string, but
accepts a byte array as input.

rust/src/json.rs

index 0ac4d04bad582923777544722356f27f6a9d1c35..4f9af2f11a264333c472fb59ac48db2118ef8112 100644 (file)
@@ -68,11 +68,19 @@ impl Json {
         }
     }
 
+    pub fn set_string_from_bytes(&self, key: &str, val: &[u8]) {
+        unsafe {
+            json_object_set_new(self.js,
+                                CString::new(key).unwrap().as_ptr(),
+                                json_string(to_cstring(val).as_ptr()));
+        }
+    }
+
     pub fn set_string(&self, key: &str, val: &str) {
-        unsafe{
+        unsafe {
             json_object_set_new(self.js,
                                 CString::new(key).unwrap().as_ptr(),
-                                json_string(CString::new(val).unwrap().as_ptr()));
+                                json_string(to_cstring(val.as_bytes()).as_ptr()));
         }
     }
 
@@ -98,3 +106,43 @@ impl Json {
         }
     }
 }
+
+/// Convert an array of bytes into an ascii printable string replacing
+/// non-printable characters (including NULL) with hex value.
+///
+/// Newer versions of Jansson have a json_stringn that will allow us
+/// to create a string out of a byte array of unicode compliant bytes,
+/// but until we can use it across all platforms this is probably the
+/// best we can do.
+fn to_cstring(val: &[u8]) -> CString {
+    let mut safe = Vec::with_capacity(val.len());
+    for c in val {
+        if *c == 0 || *c > 0x7f {
+            safe.extend(format!("\\x{:02x}", *c).as_bytes());
+        } else {
+            safe.push(*c);
+        }
+    }
+    match CString::new(safe) {
+        Ok(cstr) => cstr,
+        _ => {
+            CString::new("<failed to encode string>").unwrap()
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+
+    use json::to_cstring;
+
+    #[test]
+    fn test_to_string() {
+        assert_eq!("A\\x00A",
+                   to_cstring(&[0x41, 0x00, 0x41]).into_string().unwrap());
+        assert_eq!("", to_cstring(&[]).into_string().unwrap());
+        assert_eq!("\\x80\\xf1\\xf2\\xf3",
+                   to_cstring(&[0x80, 0xf1, 0xf2, 0xf3]).into_string().unwrap());
+    }
+
+}