-- v2: jscript: Restrict the allowed escape characters of JSON.parse in html mode. jscript: Don't use call frame for indirect eval calls for storing variables.
From: Gabriel Ivăncescu gabrielopcode@gmail.com
They're global in scope.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/engine.c | 4 ++-- dlls/mshtml/tests/documentmode.js | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/engine.c b/dlls/jscript/engine.c index ca662ae99ff..c95fcace84a 100644 --- a/dlls/jscript/engine.c +++ b/dlls/jscript/engine.c @@ -3461,7 +3461,7 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi return hres; }
- if((flags & EXEC_EVAL) && ctx->call_ctx) { + if((flags & EXEC_EVAL) && scope) { variable_obj = jsdisp_addref(ctx->call_ctx->variable_obj); }else if(!(flags & (EXEC_GLOBAL | EXEC_EVAL))) { hres = create_dispex(ctx, NULL, NULL, &variable_obj); @@ -3516,7 +3516,7 @@ HRESULT exec_source(script_ctx_t *ctx, DWORD flags, bytecode_t *bytecode, functi this_obj = NULL; }
- if(ctx->call_ctx && (flags & EXEC_EVAL)) { + if(scope && (flags & EXEC_EVAL)) { hres = detach_variable_object(ctx, ctx->call_ctx, FALSE); if(FAILED(hres)) goto fail; diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 7fdf510ddd7..f967b36e562 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -862,6 +862,16 @@ sync_test("eval", function() { context = {}; (function(eval) { eval(code); })(function() { context.barfoo = 4321; }); ok(context.barfoo === 4321, "context.barfoo = " + context.barfoo); + + (0,eval)("var foobar = 'wine';"); + if(v < 9) { + ok(!("foobar" in window), "foobar in window"); + ok(foobar === "wine", "foobar = " + foobar); + }else { + ok("foobar" in window, "foobar not in window"); + ok(window.foobar === "wine", "foobar = " + window.foobar); + } + delete foobar; });
sync_test("for..in", function() {
From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/json.c | 77 +++++++++++++++++++++++++++++++++++++-- dlls/jscript/lex.c | 2 +- dlls/jscript/parser.h | 1 + dlls/jscript/tests/api.js | 2 +- dlls/mshtml/tests/es5.js | 20 ++++++++++ 5 files changed, 97 insertions(+), 5 deletions(-)
diff --git a/dlls/jscript/json.c b/dlls/jscript/json.c index b56d75d3570..9018687aba2 100644 --- a/dlls/jscript/json.c +++ b/dlls/jscript/json.c @@ -57,6 +57,77 @@ static BOOL is_keyword(json_parse_ctx_t *ctx, const WCHAR *keyword) return TRUE; }
+static BOOL unescape_json_string(WCHAR *str, size_t *len) +{ + WCHAR *pd, *p, c, *end = str + *len; + int i; + + pd = p = str; + while(p < end) { + if(*p != '\') { + *pd++ = *p++; + continue; + } + + if(++p == end) + return FALSE; + + switch(*p) { + case '"': + case '\': + case '/': + c = *p; + break; + case 'b': + c = '\b'; + break; + case 't': + c = '\t'; + break; + case 'n': + c = '\n'; + break; + case 'f': + c = '\f'; + break; + case 'r': + c = '\r'; + break; + case 'u': + if(p + 4 >= end) + return FALSE; + i = hex_to_int(*++p); + if(i == -1) + return FALSE; + c = i << 12; + + i = hex_to_int(*++p); + if(i == -1) + return FALSE; + c += i << 8; + + i = hex_to_int(*++p); + if(i == -1) + return FALSE; + c += i << 4; + + i = hex_to_int(*++p); + if(i == -1) + return FALSE; + c += i; + break; + default: + return FALSE; + } + + *pd++ = c; + p++; + } + + *len = pd - str; + return TRUE; +} + /* ECMA-262 5.1 Edition 15.12.1.1 */ static HRESULT parse_json_string(json_parse_ctx_t *ctx, WCHAR **r) { @@ -80,10 +151,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(!(ctx->ctx->html_mode ? unescape_json_string(buf, &len) : unescape(buf, &len))) { + 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..ee29bff1e37 100644 --- a/dlls/jscript/lex.c +++ b/dlls/jscript/lex.c @@ -117,7 +117,7 @@ static BOOL is_endline(WCHAR c) return c == '\n' || c == '\r' || c == 0x2028 || c == 0x2029; }
-static int hex_to_int(WCHAR c) +int hex_to_int(WCHAR c) { if('0' <= c && c <= '9') return c-'0'; diff --git a/dlls/jscript/parser.h b/dlls/jscript/parser.h index 3b616b43b07..406bedc6607 100644 --- a/dlls/jscript/parser.h +++ b/dlls/jscript/parser.h @@ -65,6 +65,7 @@ static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size) return heap_pool_alloc(&ctx->script->tmp_heap, size); }
+int hex_to_int(WCHAR); BOOL is_identifier_char(WCHAR); BOOL unescape(WCHAR*,size_t*); HRESULT parse_decimal(const WCHAR**,const WCHAR*,double*); 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/es5.js b/dlls/mshtml/tests/es5.js index 630d9079703..7496ea4c395 100644 --- a/dlls/mshtml/tests/es5.js +++ b/dlls/mshtml/tests/es5.js @@ -1676,6 +1676,26 @@ sync_test("isFrozen", function() { } });
+sync_test("JSON.parse escapes", function() { + 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("RegExp", function() { var r;
This merge request was approved by Jacek Caban.