Module: wine Branch: master Commit: 922049a21d69333a8c5b58654103fde914a4737a URL: https://source.winehq.org/git/wine.git/?a=commit;h=922049a21d69333a8c5b58654...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Mar 1 17:44:18 2019 +0100
jscript: Add support for string literals with embedded null bytes.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/compile.c | 4 ++-- dlls/jscript/lex.c | 34 +++++++++++++++++++++------------- dlls/jscript/parser.h | 2 +- dlls/jscript/parser.y | 12 ++++++------ dlls/jscript/tests/lang.js | 3 +++ 5 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/dlls/jscript/compile.c b/dlls/jscript/compile.c index 08975e2..9e71872 100644 --- a/dlls/jscript/compile.c +++ b/dlls/jscript/compile.c @@ -829,7 +829,7 @@ static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal) case LT_NULL: return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY; case LT_STRING: - return push_instr_str(ctx, OP_str, compiler_alloc_string(ctx, literal->u.wstr)); + return push_instr_str(ctx, OP_str, literal->u.str); case LT_REGEXP: return push_instr_str_uint(ctx, OP_regexp, literal->u.regexp.str, literal->u.regexp.flags); DEFAULT_UNREACHABLE; @@ -841,7 +841,7 @@ static HRESULT literal_as_string(compiler_ctx_t *ctx, literal_t *literal, jsstr_ { switch(literal->type) { case LT_STRING: - *str = compiler_alloc_string(ctx, literal->u.wstr); + *str = literal->u.str; break; case LT_DOUBLE: return double_to_string(literal->u.dval, str); diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c index b3a7923..a22a02b 100644 --- a/dlls/jscript/lex.c +++ b/dlls/jscript/lex.c @@ -373,33 +373,41 @@ static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret) return tIdentifier; }
-static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endch) +static int parse_string_literal(parser_ctx_t *ctx, jsstr_t **ret, WCHAR endch) { - const WCHAR *ptr = ++ctx->ptr; - WCHAR *wstr; + const WCHAR *ptr = ++ctx->ptr, *ret_str = ptr; + BOOL needs_unescape = FALSE; + WCHAR *unescape_str; size_t len;
while(ctx->ptr < ctx->end && *ctx->ptr != endch) { - if(*ctx->ptr++ == '\') + if(*ctx->ptr++ == '\') { ctx->ptr++; + needs_unescape = TRUE; + } }
if(ctx->ptr == ctx->end) return lex_error(ctx, JS_E_UNTERMINATED_STRING);
- len = ctx->ptr-ptr; - - *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR)); - memcpy(wstr, ptr, len*sizeof(WCHAR)); - + len = ctx->ptr - ptr; ctx->ptr++;
- if(!unescape(wstr, &len)) { - WARN("unescape failed\n"); - return lex_error(ctx, E_FAIL); + if(needs_unescape) { + ret_str = unescape_str = parser_alloc(ctx, len * sizeof(WCHAR)); + if(!unescape_str) + return lex_error(ctx, E_OUTOFMEMORY); + memcpy(unescape_str, ptr, len * sizeof(WCHAR)); + if(!unescape(unescape_str, &len)) { + WARN("unescape failed\n"); + return lex_error(ctx, E_FAIL); + } }
- wstr[len] = 0; + if(!(*ret = compiler_alloc_string_len(ctx->compiler, ret_str, len))) + return lex_error(ctx, E_OUTOFMEMORY); + + /* FIXME: leaking string */ return tStringLiteral; }
diff --git a/dlls/jscript/parser.h b/dlls/jscript/parser.h index 0be13d5..bceb556 100644 --- a/dlls/jscript/parser.h +++ b/dlls/jscript/parser.h @@ -79,7 +79,7 @@ typedef struct { literal_type_t type; union { double dval; - const WCHAR *wstr; + jsstr_t *str; BOOL bval; struct { jsstr_t *str; diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index 57aecf6..8fc0d37 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -37,7 +37,7 @@ typedef struct _statement_list_t { statement_t *tail; } statement_list_t;
-static literal_t *new_string_literal(parser_ctx_t*,const WCHAR*); +static literal_t *new_string_literal(parser_ctx_t*,jsstr_t*); static literal_t *new_null_literal(parser_ctx_t*);
typedef struct _property_list_t { @@ -147,7 +147,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state %union { int ival; const WCHAR *srcptr; - LPCWSTR wstr; + jsstr_t *str; literal_t *literal; struct _argument_list_t *argument_list; case_clausule_t *case_clausule; @@ -177,7 +177,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state %token <identifier> tIdentifier %token <ival> tAssignOper tEqOper tShiftOper tRelOper %token <literal> tNumericLiteral tBooleanLiteral -%token <wstr> tStringLiteral +%token <str> tStringLiteral %token tEOF
%type <source_elements> SourceElements @@ -813,7 +813,7 @@ GetterSetterMethod
/* Ecma-262 3rd Edition 11.1.5 */ PropertyName - : IdentifierName { $$ = new_string_literal(ctx, $1); } + : IdentifierName { $$ = new_string_literal(ctx, compiler_alloc_string_len(ctx->compiler, $1, strlenW($1))); } | tStringLiteral { $$ = new_string_literal(ctx, $1); } | tNumericLiteral { $$ = $1; }
@@ -921,12 +921,12 @@ static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size return stat; }
-static literal_t *new_string_literal(parser_ctx_t *ctx, const WCHAR *str) +static literal_t *new_string_literal(parser_ctx_t *ctx, jsstr_t *str) { literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
ret->type = LT_STRING; - ret->u.wstr = str; + ret->u.str = str;
return ret; } diff --git a/dlls/jscript/tests/lang.js b/dlls/jscript/tests/lang.js index 2a30ea3..0fb63f4 100644 --- a/dlls/jscript/tests/lang.js +++ b/dlls/jscript/tests/lang.js @@ -180,6 +180,9 @@ ok(tmp === "undefined", "typeof((new Object).doesnotexist = " + tmp); tmp = typeof(testObj.onlyDispID); ok(tmp === "unknown", "typeof(testObj.onlyDispID) = " + tmp);
+ok("\0\0x\0\0".length === 5, ""\0\0x\0\0".length = " + "\0\0x\0\0".length); +ok("\0\0x\0\0" === String.fromCharCode(0) + "\0x\0" + String.fromCharCode(0), ""\0\0x\0\0" unexpected"); + ok(testFunc1(true, "test") === true, "testFunc1 not returned true");
ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments);