ref: 45208d7331a8df67970dbf796bc74e30128d1d29
parent: 05aeef461f7c52ff852cf84d81b1228ccdcb90d4
author: Tor Andersson <tor.andersson@gmail.com>
date: Mon Apr 3 08:31:11 EDT 2017
Be stricter when parsing JSON strings. JSON strings must use double quotes, and only support a subset of character escapes.
--- a/jslex.c
+++ b/jslex.c
@@ -762,6 +762,59 @@
return TK_NUMBER;
}
+static int lexjsonescape(js_State *J)
+{
+ int x = 0;
+
+ /* already consumed '\' */
+
+ switch (J->lexchar) {
+ default: jsY_error(J, "invalid escape sequence");
+ case 'u':
+ jsY_next(J);
+ if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 12; jsY_next(J); }
+ if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 8; jsY_next(J); }
+ if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar) << 4; jsY_next(J); }
+ if (!jsY_ishex(J->lexchar)) return 1; else { x |= jsY_tohex(J->lexchar); jsY_next(J); }
+ textpush(J, x);
+ break;
+ case '"': textpush(J, '"'); jsY_next(J); break;
+ case '\\': textpush(J, '\\'); jsY_next(J); break;
+ case 'b': textpush(J, '\b'); jsY_next(J); break;
+ case 'f': textpush(J, '\f'); jsY_next(J); break;
+ case 'n': textpush(J, '\n'); jsY_next(J); break;
+ case 'r': textpush(J, '\r'); jsY_next(J); break;
+ case 't': textpush(J, '\t'); jsY_next(J); break;
+ }
+ return 0;
+}
+
+static int lexjsonstring(js_State *J)
+{
+ const char *s;
+
+ textinit(J);
+
+ while (J->lexchar != '"') {
+ if (J->lexchar == 0)
+ jsY_error(J, "unterminated string");
+ else if (J->lexchar < 32)
+ jsY_error(J, "invalid control character in string");
+ else if (jsY_accept(J, '\\'))
+ lexjsonescape(J);
+ else {
+ textpush(J, J->lexchar);
+ jsY_next(J);
+ }
+ }
+ jsY_expect(J, '"');
+
+ s = textend(J);
+
+ J->text = js_intern(J, s);
+ return TK_STRING;
+}
+
int jsY_lexjson(js_State *J)
{
while (1) {
@@ -782,7 +835,8 @@
case '}': jsY_next(J); return '}';
case '"':
- return lexstring(J);
+ jsY_next(J);
+ return lexjsonstring(J);
case 'f':
jsY_next(J); jsY_expect(J, 'a'); jsY_expect(J, 'l'); jsY_expect(J, 's'); jsY_expect(J, 'e');