From: Dmitry Volyntsev Date: Fri, 4 Oct 2019 14:19:06 +0000 (+0300) Subject: Fixed Regexp.prototype.test() for regexps with backreferences. X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=70d7701e556d6f047c64b85a9630ac692f14c8be;p=njs.git Fixed Regexp.prototype.test() for regexps with backreferences. This closes #225 issue on Github. --- diff --git a/src/njs_pcre.c b/src/njs_pcre.c index f3016f48..f3537c92 100644 --- a/src/njs_pcre.c +++ b/src/njs_pcre.c @@ -111,6 +111,17 @@ njs_regex_compile(njs_regex_t *regex, u_char *source, size_t len, goto done; } + err = pcre_fullinfo(regex->code, NULL, PCRE_INFO_BACKREFMAX, + ®ex->backrefmax); + + if (njs_slow_path(err < 0)) { + njs_alert(ctx->trace, NJS_LEVEL_ERROR, + "pcre_fullinfo(\"%s\", PCRE_INFO_BACKREFMAX) failed: %d", + pattern, err); + + goto done; + } + /* Reserve additional elements for the first "$0" capture. */ regex->ncaptures++; @@ -175,6 +186,13 @@ njs_regex_ncaptures(njs_regex_t *regex) } +njs_uint_t +njs_regex_backrefs(njs_regex_t *regex) +{ + return regex->backrefmax; +} + + njs_int_t njs_regex_named_captures(njs_regex_t *regex, njs_str_t *name, int n) { diff --git a/src/njs_pcre.h b/src/njs_pcre.h index 41b8f075..0f65ae2f 100644 --- a/src/njs_pcre.h +++ b/src/njs_pcre.h @@ -18,6 +18,7 @@ struct njs_regex_s { pcre *code; pcre_extra *extra; int ncaptures; + int backrefmax; int nentries; int entry_size; char *entries; diff --git a/src/njs_regex.h b/src/njs_regex.h index fab19cdf..99e1587c 100644 --- a/src/njs_regex.h +++ b/src/njs_regex.h @@ -31,6 +31,7 @@ NJS_EXPORT njs_int_t njs_regex_compile(njs_regex_t *regex, u_char *source, size_t len, njs_uint_t options, njs_regex_context_t *ctx); NJS_EXPORT njs_bool_t njs_regex_is_valid(njs_regex_t *regex); NJS_EXPORT njs_uint_t njs_regex_ncaptures(njs_regex_t *regex); +NJS_EXPORT njs_uint_t njs_regex_backrefs(njs_regex_t *regex); NJS_EXPORT njs_int_t njs_regex_named_captures(njs_regex_t *regex, njs_str_t *name, int n); NJS_EXPORT njs_regex_match_data_t *njs_regex_match_data(njs_regex_t *regex, diff --git a/src/njs_regexp.c b/src/njs_regexp.c index 038cbfef..00e85d3d 100644 --- a/src/njs_regexp.c +++ b/src/njs_regexp.c @@ -842,11 +842,13 @@ static njs_int_t njs_regexp_prototype_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused) { - njs_int_t ret; - njs_uint_t n; - const njs_value_t *value, *retval; - njs_string_prop_t string; - njs_regexp_pattern_t *pattern; + njs_int_t ret; + njs_uint_t n; + njs_regex_t *regex; + const njs_value_t *value, *retval; + njs_string_prop_t string; + njs_regexp_pattern_t *pattern; + njs_regex_match_data_t *match_data; if (!njs_is_regexp(njs_arg(args, nargs, 0))) { njs_type_error(vm, "\"this\" argument is not a regexp"); @@ -866,20 +868,40 @@ njs_regexp_prototype_test(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, pattern = njs_regexp_pattern(&args[0]); - if (njs_regex_is_valid(&pattern->regex[n])) { - ret = njs_regexp_match(vm, &pattern->regex[n], string.start, - string.size, vm->single_match_data); + regex = &pattern->regex[n]; + match_data = vm->single_match_data; + + if (njs_regex_is_valid(regex)) { + if (njs_regex_backrefs(regex) != 0) { + match_data = njs_regex_match_data(regex, vm->regex_context); + if (njs_slow_path(match_data == NULL)) { + njs_memory_error(vm); + return NJS_ERROR; + } + } + + ret = njs_regexp_match(vm, regex, string.start, string.size, + match_data); if (ret >= 0) { retval = &njs_value_true; } else if (ret != NJS_REGEX_NOMATCH) { - return NJS_ERROR; + ret = NJS_ERROR; + goto done; } } + ret = NJS_OK; + vm->retval = *retval; - return NJS_OK; +done: + + if (match_data != vm->single_match_data) { + njs_regex_match_data_free(match_data, vm->regex_context); + } + + return ret; } diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index 8511763a..3ac242b1 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -8178,6 +8178,10 @@ static njs_unit_test_t njs_test[] = njs_str("true") }, #endif + { njs_str("var re = /<(?[\\w\\-\\.\\:]+)>(?.*?)<\\/\\1>/g;" + "['XXX', 'XX'].map(s=>re.test(s))"), + njs_str("true,false") }, + { njs_str("/\\x80/.test('\\u0080')"), njs_str("true") },