fix handling of escaped chars in json backend and frontend
authorN. Engelhardt <nak@yosyshq.com>
Fri, 18 Feb 2022 16:13:09 +0000 (17:13 +0100)
committerN. Engelhardt <nak@yosyshq.com>
Fri, 18 Feb 2022 16:13:09 +0000 (17:13 +0100)
Makefile
backends/json/json.cc
frontends/json/jsonparse.cc
tests/various/.gitignore
tests/various/json_escape_chars.ys [new file with mode: 0644]

index eb22138982bf52b892720fa638c1bdf4d5352d86..46d3efe44b6a22c50f2a88634371da64995baeae 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -915,7 +915,7 @@ clean:
        rm -rf tests/simple/*.out tests/simple/*.log
        rm -rf tests/memories/*.out tests/memories/*.log tests/memories/*.dmp
        rm -rf tests/sat/*.log tests/techmap/*.log tests/various/*.log
-       rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp
+       rm -rf tests/bram/temp tests/fsm/temp tests/realmath/temp tests/share/temp tests/smv/temp tests/various/temp
        rm -rf vloghtb/Makefile vloghtb/refdat vloghtb/rtl vloghtb/scripts vloghtb/spec vloghtb/check_yosys vloghtb/vloghammer_tb.tar.bz2 vloghtb/temp vloghtb/log_test_*
        rm -f tests/svinterfaces/*.log_stdout tests/svinterfaces/*.log_stderr tests/svinterfaces/dut_result.txt tests/svinterfaces/reference_result.txt tests/svinterfaces/a.out tests/svinterfaces/*_syn.v tests/svinterfaces/*.diff
        rm -f  tests/tools/cmp_tbdata
index 4aa8046d602e45371fd642481cc75052914a3fc9..42eedc606273c15ea477b7c6269b6dff00af0515 100644 (file)
@@ -52,8 +52,23 @@ struct JsonWriter
                string newstr = "\"";
                for (char c : str) {
                        if (c == '\\')
+                               newstr += "\\\\";
+                       else if (c == '"')
+                               newstr += "\\\"";
+                       else if (c == '\b')
+                               newstr += "\\b";
+                       else if (c == '\f')
+                               newstr += "\\f";
+                       else if (c == '\n')
+                               newstr += "\\n";
+                       else if (c == '\r')
+                               newstr += "\\r";
+                       else if (c == '\t')
+                               newstr += "\\t";
+                       else if (c < 0x20)
+                               newstr += stringf("\\u%04X", c);
+                       else
                                newstr += c;
-                       newstr += c;
                }
                return newstr + "\"";
        }
index 50c25abdadb89fc02dc3cf15e26e67aaa521c5fa..1aab810153d21f25556d786cd992913f3c394bb0 100644 (file)
@@ -60,10 +60,38 @@ struct JsonNode
                                                break;
 
                                        if (ch == '\\') {
-                                               int ch = f.get();
+                                               ch = f.get();
 
-                                               if (ch == EOF)
-                                                       log_error("Unexpected EOF in JSON string.\n");
+                                               switch (ch) {
+                                                       case EOF: log_error("Unexpected EOF in JSON string.\n"); break;
+                                                       case '"':
+                                                       case '/':
+                                                       case '\\':           break;
+                                                       case 'b': ch = '\b'; break;
+                                                       case 'f': ch = '\f'; break;
+                                                       case 'n': ch = '\n'; break;
+                                                       case 'r': ch = '\r'; break;
+                                                       case 't': ch = '\t'; break;
+                                                       case 'u':
+                                                               int val = 0;
+                                                               for (int i = 0; i < 4; i++) {
+                                                                       ch = f.get();
+                                                                       val <<= 4;
+                                                                       if (ch >= '0' && '9' >= ch) {
+                                                                               val += ch - '0';
+                                                                       } else if (ch >= 'A' && 'F' >= ch) {
+                                                                               val += 10 + ch - 'A';
+                                                                       } else if (ch >= 'a' && 'f' >= ch) {
+                                                                               val += 10 + ch - 'a';
+                                                                       } else
+                                                                               log_error("Unexpected non-digit character in \\uXXXX sequence: %c.\n", ch);
+                                                               }
+                                                               if (val < 128)
+                                                                       ch = val;
+                                                               else
+                                                                       log_error("Unsupported \\uXXXX sequence in JSON string: %04X.\n", val);
+                                                               break;
+                                               }
                                        }
 
                                        data_string += ch;
index 2bb6c71793ce6e35e51c9eb94829acdf53226925..c6373468a25438da8d77e03ea170b1943d0d19d5 100644 (file)
@@ -5,3 +5,4 @@
 /run-test.mk
 /plugin.so
 /plugin.so.dSYM
+/temp
diff --git a/tests/various/json_escape_chars.ys b/tests/various/json_escape_chars.ys
new file mode 100644 (file)
index 0000000..f118357
--- /dev/null
@@ -0,0 +1,14 @@
+! mkdir -p temp
+read_verilog <<EOT
+(* src = "\042 \057 \134 \010 \014 \012 \015 \011 \025 \033" *)
+module foo;
+endmodule
+EOT
+write_json temp/test_escapes.json
+design -reset
+read_json temp/test_escapes.json
+write_json temp/test_escapes.json
+design -reset
+read_json temp/test_escapes.json
+write_rtlil temp/test_escapes.json.il
+! grep -F 'attribute \src "\" / \\ \010 \014 \n \015 \t \025 \033"' temp/test_escapes.json.il