From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/json.c | 6 +++--- dlls/jscript/lex.c | 12 ++++++++++-- dlls/jscript/parser.h | 2 +- dlls/jscript/tests/api.js | 2 +- dlls/mshtml/tests/documentmode.js | 23 +++++++++++++++++++++++ 5 files changed, 38 insertions(+), 7 deletions(-)
diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c index b56d75d3570..d3177ab56a1 100644 --- a/dlls/jscript/json.c +++ b/dlls/jscript/json.c @@ -80,10 +80,10 @@ static HRESULT parse_json_string(json_parse_ctx_t *ctx, WCHAR **r) if(len) memcpy(buf, ptr, len*sizeof(WCHAR));
- if(!unescape(buf, &len)) { - FIXME("unescape failed\n"); + if(!unescape(buf, &len, ctx->ctx->html_mode)) { + WARN("unescape failed\n"); free(buf); - return E_FAIL; + return JS_E_INVALID_CHAR; }
buf[len] = 0; diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c index 3bb2040803d..99eb0bc4c77 100644 --- a/dlls/jscript/lex.c +++ b/dlls/jscript/lex.c @@ -224,7 +224,7 @@ static BOOL skip_spaces(parser_ctx_t *ctx) return ctx->ptr != ctx->end; }
-BOOL unescape(WCHAR *str, size_t *len) +BOOL unescape(WCHAR *str, size_t *len, BOOL json) { WCHAR *pd, *p, c, *end = str + *len; int i; @@ -241,8 +241,12 @@ BOOL unescape(WCHAR *str, size_t *len)
switch(*p) { case ''': + if(json) + return FALSE; + /* fall through */ case '"': case '\': + case '/': c = *p; break; case 'b': @@ -261,6 +265,8 @@ BOOL unescape(WCHAR *str, size_t *len) c = '\r'; break; case 'x': + if(json) + return FALSE; if(p + 2 >= end) return FALSE; i = hex_to_int(*++p); @@ -297,6 +303,8 @@ BOOL unescape(WCHAR *str, size_t *len) c += i; break; default: + if(json) + return FALSE; if(is_digit(*p)) { c = *p++ - '0'; if(p < end && is_digit(*p)) { @@ -362,7 +370,7 @@ static int parse_string_literal(parser_ctx_t *ctx, jsstr_t **ret, WCHAR endch) if(!unescape_str) return lex_error(ctx, E_OUTOFMEMORY); memcpy(unescape_str, ptr, len * sizeof(WCHAR)); - if(!unescape(unescape_str, &len)) { + if(!unescape(unescape_str, &len, FALSE)) { WARN("unescape failed\n"); return lex_error(ctx, E_FAIL); } diff --git a/dlls/jscript/parser.h b/dlls/jscript/parser.h index 3b616b43b07..f10dea93101 100644 --- a/dlls/jscript/parser.h +++ b/dlls/jscript/parser.h @@ -66,7 +66,7 @@ static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size) }
BOOL is_identifier_char(WCHAR); -BOOL unescape(WCHAR*,size_t*); +BOOL unescape(WCHAR*,size_t*,BOOL); HRESULT parse_decimal(const WCHAR**,const WCHAR*,double*);
typedef enum { diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index a82e4756c24..255418a6744 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -2010,7 +2010,7 @@ ok(isNaN(tmp), "Math.tan(-Infinity) is not NaN"); ["true", true], [" \nnull ", null], ["{}", {}], - [""\r\n test\u1111"", "\r\n test\u1111"], + [""\r\n test\u1111\/\x20\45\'"", "\r\n test\u1111/ %'"], ["{"x" :\n true}", {x:true}], ["{"x y": {}, "z": {"x":null}}", {"x y":{}, z:{x:null}}], ["[]", []], diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 73f54cd708b..a80a74f12ae 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -1838,6 +1838,29 @@ async_test("weakmap_obj", function() { window.setTimeout(retry); });
+sync_test("JSON.parse escapes", function() { + if(!window.JSON) + return; + + var i, valid = [ "b", "t", "n", "f", "r", "u1111", '"', "/" ]; + + for(i = 0; i < valid.length; i++) { + var a = JSON.parse('"\' + valid[i] + '"'), b = eval('"\' + valid[i] + '"'); + ok(a === b, "JSON.parse with \" + valid[i] + " returned " + a); + } + + var invalid = [ "0", "00", "05", "x20", "i", "'" ]; + + for(i = 0; i < invalid.length; i++) { + try { + JSON.parse('"\' + invalid[i] + '"'); + ok(false, "expected exception calling JSON.parse with \" + invalid[i]); + } catch(e) { + ok(e.number === 0xa03f6 - 0x80000000, "calling JSON.parse with \" + invalid[i] + " threw " + e.number); + } + } +}); + sync_test("storage", function() { var v = document.documentMode, i, r, list;