Jacek Caban : jscript: Add support for string literals with embedded null bytes.

Alexandre Julliard julliard at winehq.org
Mon Mar 4 15:08:25 CST 2019


Module: wine
Branch: master
Commit: 922049a21d69333a8c5b58654103fde914a4737a
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=922049a21d69333a8c5b58654103fde914a4737a

Author: Jacek Caban <jacek at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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);




More information about the wine-cvs mailing list