git.delta.rocks / jrsonnet / refs/commits / 52a24f69aae7

difftreelog

fix(nixlike) string roundtrips

Yaroslav Bolyukin2021-10-01parent: #a9e03a3.patch.diff
in: trunk

6 files changed

addedcrates/nixlike/fuzz/.gitignorediffbeforeafterboth
--- /dev/null
+++ b/crates/nixlike/fuzz/.gitignore
@@ -0,0 +1,4 @@
+
+target
+corpus
+artifacts
addedcrates/nixlike/fuzz/Cargo.lockdiffbeforeafterboth

no changes

addedcrates/nixlike/fuzz/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/crates/nixlike/fuzz/Cargo.toml
@@ -0,0 +1,26 @@
+
+[package]
+name = "nixlike-fuzz"
+version = "0.0.0"
+authors = ["Automatically generated"]
+publish = false
+edition = "2018"
+
+[package.metadata]
+cargo-fuzz = true
+
+[dependencies]
+libfuzzer-sys = "0.4"
+
+[dependencies.nixlike]
+path = ".."
+
+# Prevent this from interfering with workspaces
+[workspace]
+members = ["."]
+
+[[bin]]
+name = "fuzz_target_1"
+path = "fuzz_targets/fuzz_target_1.rs"
+test = false
+doc = false
addedcrates/nixlike/fuzz/fuzz_targets/fuzz_target_1.rsdiffbeforeafterboth
--- /dev/null
+++ b/crates/nixlike/fuzz/fuzz_targets/fuzz_target_1.rs
@@ -0,0 +1,9 @@
+#![no_main]
+use libfuzzer_sys::fuzz_target;
+
+fuzz_target!(|data: String| {
+    let serialized = nixlike::serialize(data.clone()).unwrap();
+    let deserialized: String = nixlike::parse_str(&serialized).unwrap();
+    
+    assert_eq!(data, deserialized);
+});
modifiedcrates/nixlike/src/lib.rsdiffbeforeafterboth
--- a/crates/nixlike/src/lib.rs
+++ b/crates/nixlike/src/lib.rs
@@ -40,6 +40,10 @@
 	rule string_char() -> &'input str
 		= "\\\"" { "\"" }
 		/ "\\\\" { "\\" }
+		/ "\\n" { "\n" }
+		/ "\\t" { "\t" }
+		/ "\\r" { "\r" }
+		/ "''$" { "$" }
 		/ c:$([_]) { c }
 	rule string() -> String
 		= quiet! { "\"" v:(!"\"" c:string_char() {c})* "\"" { v.into_iter().collect() } } / expected!("<string>")
@@ -47,7 +51,10 @@
 		= quiet! { "true" {true}
 		/ "false" {false} } / expected!("<boolean>")
 	rule indent() -> String
-		= quiet! { s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() } } / expected!("<identifier>")
+		= quiet! {
+			s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-']+) { s.to_owned() }
+			/ "\"" s:$(['a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '-' | '.']+) "\"" { s.to_owned() }
+		} / expected!("<identifier>")
 	rule object() -> LinkedHashMap<String, Value>
 		= "{" _
 			e:(k:indent()++(_ "." _) _ "=" _ v:value() _ ";" _ {(k, v)})*
@@ -111,20 +118,5 @@
 
 #[test]
 fn test() {
-	let v: serde_json::Value = parse_str(
-		r#"
-			{
-				b.c = 2;
-				b.d = "hello";
-				c = {
-					k = 123;
-					p = 231;
-					ll = [1 2 3 [] [[4 5 6]] ];
-				};
-			}
-		"#,
-	)
-	.unwrap();
-	let s: String = serialize(v).unwrap();
-	println!("{}", s);
+	assert_eq!(serialize("Hello\nworld").unwrap(), "\"Hello\\nworld\"");
 }
modifiedcrates/nixlike/src/to_string.rsdiffbeforeafterboth
--- a/crates/nixlike/src/to_string.rs
+++ b/crates/nixlike/src/to_string.rs
@@ -5,7 +5,13 @@
 };
 
 fn write_nix_obj_key_buf(k: &str, v: &Value, out: &mut PrintItems) {
-	out.push_str(k);
+	if k.contains(".") {
+		out.push_str("\"");
+		out.push_str(k);
+		out.push_str("\"");
+	} else {
+		out.push_str(k);
+	}
 	match v {
 		Value::Object(o) if o.len() == 1 => {
 			let (k, v) = o.iter().next().unwrap();
@@ -26,7 +32,15 @@
 		Value::Null => out.push_str("null"),
 		Value::Boolean(v) => out.push_str(if *v { "true" } else { "false" }),
 		Value::Number(n) => out.push_str(&format!("{}", n)),
-		Value::String(s) => out.push_str(&format!("{:?}", s)),
+		Value::String(s) => out.push_str(&format!(
+			"\"{}\"",
+			s.replace('\\', "\\\\")
+				.replace('"', "\\\"")
+				.replace('\n', "\\n")
+				.replace('\t', "\\t")
+				.replace('\r', "\\r")
+				.replace("$", "''$")
+		)),
 		Value::Array(a) => {
 			if a.is_empty() {
 				out.push_str("[ ]");