Module: wine Branch: master Commit: b48cc9614e924198d41569db6a3a36295904f9c9 URL: https://source.winehq.org/git/wine.git/?a=commit;h=b48cc9614e924198d41569db6...
Author: Jacek Caban jacek@codeweavers.com Date: Mon Apr 22 13:04:37 2019 +0200
jscript: Fix handling empty string regexp matches in String.prototype.split implementation.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/jscript/string.c | 49 ++++++++++++++++++++++++++++++++--------------- dlls/jscript/tests/api.js | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/dlls/jscript/string.c b/dlls/jscript/string.c index 79d7884..d88ed1c 100644 --- a/dlls/jscript/string.c +++ b/dlls/jscript/string.c @@ -1131,21 +1131,20 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi jsval_t *r) { match_state_t match_result, *match_ptr = &match_result; - DWORD length, i, match_len = 0; + size_t length, i = 0, match_len = 0; const WCHAR *ptr, *ptr2, *str, *match_str = NULL; unsigned limit = ~0u; jsdisp_t *array, *regexp = NULL; jsstr_t *jsstr, *match_jsstr, *tmp_str; HRESULT hres;
- TRACE("\n"); - hres = get_string_flat_val(ctx, jsthis, &jsstr, &str); if(FAILED(hres)) return hres; - length = jsstr_length(jsstr);
+ TRACE("%s\n", debugstr_wn(str, length)); + if(!argc || (is_undefined(argv[0]) && ctx->version >= SCRIPTLANGUAGEVERSION_ES5)) { if(!r) return S_OK; @@ -1203,11 +1202,29 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi if(SUCCEEDED(hres)) { ptr = str; match_result.cp = str; - for(i=0; i<limit; i++) { + while(i < limit) { if(regexp) { hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr); if(hres != S_OK) break; + TRACE("got match %d %d\n", (int)(match_result.cp - match_result.match_len - str), match_result.match_len); + if(!match_result.match_len) { + /* If an empty string is matched, prevent including any match in the result */ + if(!length) { + limit = 0; + break; + } + if(match_result.cp == ptr) { + match_result.cp++; + hres = regexp_match_next(ctx, regexp, REM_NO_PARENS, jsstr, &match_ptr); + if(hres != S_OK) + break; + TRACE("retried, got match %d %d\n", (int)(match_result.cp - match_result.match_len - str), + match_result.match_len); + } + if(!match_result.match_len && match_result.cp == str + length) + break; + } ptr2 = match_result.cp - match_result.match_len; }else if(match_str) { ptr2 = strstrW(ptr, match_str); @@ -1219,16 +1236,18 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi ptr2 = ptr+1; }
- tmp_str = jsstr_alloc_len(ptr, ptr2-ptr); - if(!tmp_str) { - hres = E_OUTOFMEMORY; - break; - } + if(!regexp || ptr2 > ptr) { + tmp_str = jsstr_alloc_len(ptr, ptr2-ptr); + if(!tmp_str) { + hres = E_OUTOFMEMORY; + break; + }
- hres = jsdisp_propput_idx(array, i, jsval_string(tmp_str)); - jsstr_release(tmp_str); - if(FAILED(hres)) - break; + hres = jsdisp_propput_idx(array, i++, jsval_string(tmp_str)); + jsstr_release(tmp_str); + if(FAILED(hres)) + break; + }
if(regexp) ptr = match_result.cp; @@ -1242,7 +1261,7 @@ static HRESULT String_split(script_ctx_t *ctx, vdisp_t *jsthis, WORD flags, unsi if(SUCCEEDED(hres) && (match_str || regexp) && i<limit) { DWORD len = (str+length) - ptr;
- if(len || match_str) { + if(len || match_str || !length) { tmp_str = jsstr_alloc_len(ptr, len);
if(tmp_str) { diff --git a/dlls/jscript/tests/api.js b/dlls/jscript/tests/api.js index 78c0958..f3d07f8 100644 --- a/dlls/jscript/tests/api.js +++ b/dlls/jscript/tests/api.js @@ -644,6 +644,43 @@ ok(typeof(r) === "object", "typeof(r) = " + typeof(r)); ok(r.length === 1, "r.length = " + r.length); ok(r[0] === "", "r[0] = " + r[0]);
+(function() { + function test(string, separator, result) { + var r = string.split(separator); + ok(r == result, """ + string + "".split(" + separator + ") returned " + r + " expected " + result); + } + + test("test", /^|\s+/, "test"); + test("test", /$|\s+/, "test"); + test("test", /^|./, "t"); + test("test", /.*/, ""); + test("test", /x*/, "t,e,s,t"); + test("test", /$|x*/, "t,e,s,t"); + test("test", /^|x*/, "t,e,s,t"); + test("test", /t*/, "e,s"); + test("xaabaax", /a*|b*/, "x,b,x"); + test("xaabaax", /a+|b+/, "x,x"); + test("xaabaax", /a+|b*/, "x,x"); + test("xaaxbaax", /b+|a+/, "x,x,x"); + test("test", /^|t/, "tes"); + test("test", /^|t/, "tes"); + test("a,,b", /,/, "a,b"); + test("ab", /a*/, "b"); + test("aab", "a", ",,b"); + test("a", "a", ","); + + function test_length(string, separator, len) { + var r = string.split(separator); + ok(r.length === len, """ + string + "".split(" + separator + ").length = " + + r.length + " expected " + len); + } + + test_length("", /a*/, 0); + test_length("", /a+/, 1); + test_length("", "", 0); + test_length("", "x", 1); +})(); + tmp = "abcd".indexOf("bc",0); ok(tmp === 1, "indexOf = " + tmp); tmp = "abcd".indexOf("bc",1);