jscript: Support embedded null bytes in unescape.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-03-01 17:44:07 +01:00 committed by Alexandre Julliard
parent e70825b014
commit 79557db981
3 changed files with 18 additions and 13 deletions

View File

@ -89,14 +89,14 @@ static HRESULT parse_json_string(json_parse_ctx_t *ctx, WCHAR **r)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
if(len) if(len)
memcpy(buf, ptr, len*sizeof(WCHAR)); memcpy(buf, ptr, len*sizeof(WCHAR));
buf[len] = 0;
if(!unescape(buf)) { if(!unescape(buf, &len)) {
FIXME("unescape failed\n"); FIXME("unescape failed\n");
heap_free(buf); heap_free(buf);
return E_FAIL; return E_FAIL;
} }
buf[len] = 0;
ctx->ptr++; ctx->ptr++;
*r = buf; *r = buf;
return S_OK; return S_OK;

View File

@ -260,19 +260,20 @@ static BOOL skip_spaces(parser_ctx_t *ctx)
return ctx->ptr != ctx->end; return ctx->ptr != ctx->end;
} }
BOOL unescape(WCHAR *str) BOOL unescape(WCHAR *str, size_t *len)
{ {
WCHAR *pd, *p, c; WCHAR *pd, *p, c, *end = str + *len;
int i; int i;
pd = p = str; pd = p = str;
while(*p) { while(p < end) {
if(*p != '\\') { if(*p != '\\') {
*pd++ = *p++; *pd++ = *p++;
continue; continue;
} }
p++; if(++p == end)
return FALSE;
switch(*p) { switch(*p) {
case '\'': case '\'':
@ -296,6 +297,8 @@ BOOL unescape(WCHAR *str)
c = '\r'; c = '\r';
break; break;
case 'x': case 'x':
if(p + 2 >= end)
return FALSE;
i = hex_to_int(*++p); i = hex_to_int(*++p);
if(i == -1) if(i == -1)
return FALSE; return FALSE;
@ -307,6 +310,8 @@ BOOL unescape(WCHAR *str)
c += i; c += i;
break; break;
case 'u': case 'u':
if(p + 4 >= end)
return FALSE;
i = hex_to_int(*++p); i = hex_to_int(*++p);
if(i == -1) if(i == -1)
return FALSE; return FALSE;
@ -330,9 +335,9 @@ BOOL unescape(WCHAR *str)
default: default:
if(isdigitW(*p)) { if(isdigitW(*p)) {
c = *p++ - '0'; c = *p++ - '0';
if(isdigitW(*p)) { if(p < end && isdigitW(*p)) {
c = c*8 + (*p++ - '0'); c = c*8 + (*p++ - '0');
if(isdigitW(*p)) if(p < end && isdigitW(*p))
c = c*8 + (*p++ - '0'); c = c*8 + (*p++ - '0');
} }
p--; p--;
@ -345,7 +350,7 @@ BOOL unescape(WCHAR *str)
p++; p++;
} }
*pd = 0; *len = pd - str;
return TRUE; return TRUE;
} }
@ -372,7 +377,7 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endc
{ {
const WCHAR *ptr = ++ctx->ptr; const WCHAR *ptr = ++ctx->ptr;
WCHAR *wstr; WCHAR *wstr;
int 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++ == '\\')
@ -386,15 +391,15 @@ static int parse_string_literal(parser_ctx_t *ctx, const WCHAR **ret, WCHAR endc
*ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR)); *ret = wstr = parser_alloc(ctx, (len+1)*sizeof(WCHAR));
memcpy(wstr, ptr, len*sizeof(WCHAR)); memcpy(wstr, ptr, len*sizeof(WCHAR));
wstr[len] = 0;
ctx->ptr++; ctx->ptr++;
if(!unescape(wstr)) { if(!unescape(wstr, &len)) {
WARN("unescape failed\n"); WARN("unescape failed\n");
return lex_error(ctx, E_FAIL); return lex_error(ctx, E_FAIL);
} }
wstr[len] = 0;
return tStringLiteral; return tStringLiteral;
} }

View File

@ -63,7 +63,7 @@ static inline void *parser_alloc_tmp(parser_ctx_t *ctx, DWORD size)
} }
BOOL is_identifier_char(WCHAR) DECLSPEC_HIDDEN; BOOL is_identifier_char(WCHAR) DECLSPEC_HIDDEN;
BOOL unescape(WCHAR*) DECLSPEC_HIDDEN; BOOL unescape(WCHAR*,size_t*) DECLSPEC_HIDDEN;
HRESULT parse_decimal(const WCHAR**,const WCHAR*,double*) DECLSPEC_HIDDEN; HRESULT parse_decimal(const WCHAR**,const WCHAR*,double*) DECLSPEC_HIDDEN;
typedef enum { typedef enum {