Commit 922049a2 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

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

parent 1314140a
...@@ -829,7 +829,7 @@ static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal) ...@@ -829,7 +829,7 @@ static HRESULT compile_literal(compiler_ctx_t *ctx, literal_t *literal)
case LT_NULL: case LT_NULL:
return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY; return push_instr(ctx, OP_null) ? S_OK : E_OUTOFMEMORY;
case LT_STRING: 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: case LT_REGEXP:
return push_instr_str_uint(ctx, OP_regexp, literal->u.regexp.str, literal->u.regexp.flags); return push_instr_str_uint(ctx, OP_regexp, literal->u.regexp.str, literal->u.regexp.flags);
DEFAULT_UNREACHABLE; DEFAULT_UNREACHABLE;
...@@ -841,7 +841,7 @@ static HRESULT literal_as_string(compiler_ctx_t *ctx, literal_t *literal, jsstr_ ...@@ -841,7 +841,7 @@ static HRESULT literal_as_string(compiler_ctx_t *ctx, literal_t *literal, jsstr_
{ {
switch(literal->type) { switch(literal->type) {
case LT_STRING: case LT_STRING:
*str = compiler_alloc_string(ctx, literal->u.wstr); *str = literal->u.str;
break; break;
case LT_DOUBLE: case LT_DOUBLE:
return double_to_string(literal->u.dval, str); return double_to_string(literal->u.dval, str);
......
...@@ -373,33 +373,41 @@ static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret) ...@@ -373,33 +373,41 @@ static int parse_identifier(parser_ctx_t *ctx, const WCHAR **ret)
return tIdentifier; 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; const WCHAR *ptr = ++ctx->ptr, *ret_str = ptr;
WCHAR *wstr; BOOL needs_unescape = FALSE;
WCHAR *unescape_str;
size_t len; size_t len;
while(ctx->ptr < ctx->end && *ctx->ptr != endch) { while(ctx->ptr < ctx->end && *ctx->ptr != endch) {
if(*ctx->ptr++ == '\\') if(*ctx->ptr++ == '\\') {
ctx->ptr++; ctx->ptr++;
needs_unescape = TRUE;
}
} }
if(ctx->ptr == ctx->end) if(ctx->ptr == ctx->end)
return lex_error(ctx, JS_E_UNTERMINATED_STRING); return lex_error(ctx, JS_E_UNTERMINATED_STRING);
len = ctx->ptr-ptr; len = ctx->ptr - ptr;
*ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
memcpy(wstr, ptr, len*sizeof(WCHAR));
ctx->ptr++; ctx->ptr++;
if(!unescape(wstr, &len)) { if(needs_unescape) {
WARN("unescape failed\n"); ret_str = unescape_str = parser_alloc(ctx, len * sizeof(WCHAR));
return lex_error(ctx, E_FAIL); 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; return tStringLiteral;
} }
......
...@@ -79,7 +79,7 @@ typedef struct { ...@@ -79,7 +79,7 @@ typedef struct {
literal_type_t type; literal_type_t type;
union { union {
double dval; double dval;
const WCHAR *wstr; jsstr_t *str;
BOOL bval; BOOL bval;
struct { struct {
jsstr_t *str; jsstr_t *str;
......
...@@ -37,7 +37,7 @@ typedef struct _statement_list_t { ...@@ -37,7 +37,7 @@ typedef struct _statement_list_t {
statement_t *tail; statement_t *tail;
} statement_list_t; } 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*); static literal_t *new_null_literal(parser_ctx_t*);
typedef struct _property_list_t { typedef struct _property_list_t {
...@@ -147,7 +147,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state ...@@ -147,7 +147,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
%union { %union {
int ival; int ival;
const WCHAR *srcptr; const WCHAR *srcptr;
LPCWSTR wstr; jsstr_t *str;
literal_t *literal; literal_t *literal;
struct _argument_list_t *argument_list; struct _argument_list_t *argument_list;
case_clausule_t *case_clausule; case_clausule_t *case_clausule;
...@@ -177,7 +177,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state ...@@ -177,7 +177,7 @@ static source_elements_t *source_elements_add_statement(source_elements_t*,state
%token <identifier> tIdentifier %token <identifier> tIdentifier
%token <ival> tAssignOper tEqOper tShiftOper tRelOper %token <ival> tAssignOper tEqOper tShiftOper tRelOper
%token <literal> tNumericLiteral tBooleanLiteral %token <literal> tNumericLiteral tBooleanLiteral
%token <wstr> tStringLiteral %token <str> tStringLiteral
%token tEOF %token tEOF
%type <source_elements> SourceElements %type <source_elements> SourceElements
...@@ -813,7 +813,7 @@ GetterSetterMethod ...@@ -813,7 +813,7 @@ GetterSetterMethod
/* Ecma-262 3rd Edition 11.1.5 */ /* Ecma-262 3rd Edition 11.1.5 */
PropertyName 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); } | tStringLiteral { $$ = new_string_literal(ctx, $1); }
| tNumericLiteral { $$ = $1; } | tNumericLiteral { $$ = $1; }
...@@ -921,12 +921,12 @@ static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size ...@@ -921,12 +921,12 @@ static void *new_statement(parser_ctx_t *ctx, statement_type_t type, size_t size
return stat; 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)); literal_t *ret = parser_alloc(ctx, sizeof(literal_t));
ret->type = LT_STRING; ret->type = LT_STRING;
ret->u.wstr = str; ret->u.str = str;
return ret; return ret;
} }
......
...@@ -180,6 +180,9 @@ ok(tmp === "undefined", "typeof((new Object).doesnotexist = " + tmp); ...@@ -180,6 +180,9 @@ ok(tmp === "undefined", "typeof((new Object).doesnotexist = " + tmp);
tmp = typeof(testObj.onlyDispID); tmp = typeof(testObj.onlyDispID);
ok(tmp === "unknown", "typeof(testObj.onlyDispID) = " + tmp); 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(true, "test") === true, "testFunc1 not returned true");
ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments); ok(testFunc1.arguments === null, "testFunc1.arguments = " + testFunc1.arguments);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment