From 36d61f69edac058193c155ee97089a76cecc02d4 Mon Sep 17 00:00:00 2001 From: YuNing Chen Date: Thu, 15 Aug 2024 17:15:38 +0800 Subject: [PATCH] fix: escape json for string input (#858) --- builtin/json.mbt | 36 +++++++++++++++++++++++++++++++++++- json/json_test.mbt | 3 ++- json/to_json_test.mbt | 24 ++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/builtin/json.mbt b/builtin/json.mbt index e3233d43c..3ab1da5d6 100644 --- a/builtin/json.mbt +++ b/builtin/json.mbt @@ -47,8 +47,42 @@ pub fn Double::to_json(self : Double) -> Json { Number(self) } +fn escape_json_string(str : String) -> String { + fn to_hex_digit(i : Int) -> Char { + if i < 10 { + Char::from_int('0'.to_int() + i) + } else { + Char::from_int('a'.to_int() + (i - 10)) + } + } + + let buf = Buffer::new(size_hint=str.length()) + for i = 0; i < str.length(); i = i + 1 { + let c = str[i] + match c { + '\n' => buf.write_string("\\n") + '\r' => buf.write_string("\\r") + '\b' => buf.write_string("\\b") + '\t' => buf.write_string("\\t") + _ => { + let code = c.to_int() + if code == 0x0C { + buf.write_string("\\f") + } else if code < 0x20 { + buf.write_string("\\u00") + buf.write_char(to_hex_digit(code / 16)) + buf.write_char(to_hex_digit(code % 16)) + } else { + buf.write_char(c) + } + } + } + } + buf.to_string() +} + pub fn String::to_json(self : String) -> Json { - String(self) + String(escape_json_string(self)) } pub fn Char::to_json(self : Char) -> Json { diff --git a/json/json_test.mbt b/json/json_test.mbt index de0c53093..8f83a4d63 100644 --- a/json/json_test.mbt +++ b/json/json_test.mbt @@ -295,11 +295,12 @@ test "stringify escape" { "\n": "\n\r\t\x0C", "\\": "/", "\x1F": "\x01", + "actual": "\x00", } inspect!( json.stringify(), content= - #|{"\b":"\"hello\"","\n":"\n\r\t\f","\\":"\/","\u001f":"\u0001"} + #|{"\b":"\"hello\"","\n":"\n\r\t\f","\\":"\/","\u001f":"\u0001","actual":"\u0000"} , ) match @json.parse?(json.stringify()) { diff --git a/json/to_json_test.mbt b/json/to_json_test.mbt index acdb92d85..83a4c8386 100644 --- a/json/to_json_test.mbt +++ b/json/to_json_test.mbt @@ -42,6 +42,30 @@ test "String::to_json" { #|String("a,\"b\",c") , ) + inspect!( + "\"".to_json(), + content= + #|String("\"") + , + ) + inspect!( + "\x00".to_json(), + content= + #|String("\\u0000") + , + ) + inspect!( + "\n".to_json(), + content= + #|String("\\n") + , + ) + inspect!( + "\\".to_json(), + content= + #|String("\\") + , + ) } test "Char::to_json" {