[njs] Fixed Regexp.prototype.test() for regexps with backreferences.
Dmitry Volyntsev
xeioex at nginx.com
Fri Oct 4 14:19:29 UTC 2019
details: https://hg.nginx.org/njs/rev/d62db2c99851
branches:
changeset: 1170:d62db2c99851
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Fri Oct 04 17:19:06 2019 +0300
description:
Fixed Regexp.prototype.test() for regexps with backreferences.
This closes #225 issue on Github.
diffstat:
src/njs_pcre.c | 18 ++++++++++++++++++
src/njs_pcre.h | 1 +
src/njs_regex.h | 1 +
src/njs_regexp.c | 42 ++++++++++++++++++++++++++++++++----------
src/test/njs_unit_test.c | 4 ++++
5 files changed, 56 insertions(+), 10 deletions(-)
diffs (139 lines):
diff -r 956b24477d59 -r d62db2c99851 src/njs_pcre.c
--- a/src/njs_pcre.c Thu Oct 03 16:59:22 2019 +0300
+++ b/src/njs_pcre.c Fri Oct 04 17:19:06 2019 +0300
@@ -111,6 +111,17 @@ njs_regex_compile(njs_regex_t *regex, u_
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 -r 956b24477d59 -r d62db2c99851 src/njs_pcre.h
--- a/src/njs_pcre.h Thu Oct 03 16:59:22 2019 +0300
+++ b/src/njs_pcre.h Fri Oct 04 17:19:06 2019 +0300
@@ -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 -r 956b24477d59 -r d62db2c99851 src/njs_regex.h
--- a/src/njs_regex.h Thu Oct 03 16:59:22 2019 +0300
+++ b/src/njs_regex.h Fri Oct 04 17:19:06 2019 +0300
@@ -31,6 +31,7 @@ NJS_EXPORT njs_int_t njs_regex_compile(n
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 -r 956b24477d59 -r d62db2c99851 src/njs_regexp.c
--- a/src/njs_regexp.c Thu Oct 03 16:59:22 2019 +0300
+++ b/src/njs_regexp.c Fri Oct 04 17:19:06 2019 +0300
@@ -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,
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 -r 956b24477d59 -r d62db2c99851 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Thu Oct 03 16:59:22 2019 +0300
+++ b/src/test/njs_unit_test.c Fri Oct 04 17:19:06 2019 +0300
@@ -8178,6 +8178,10 @@ static njs_unit_test_t njs_test[] =
njs_str("true") },
#endif
+ { njs_str("var re = /<(?<key>[\\w\\-\\.\\:]+)>(?<body>.*?)<\\/\\1>/g;"
+ "['<A>XXX</A>', '<A>XX</B>'].map(s=>re.test(s))"),
+ njs_str("true,false") },
+
{ njs_str("/\\x80/.test('\\u0080')"),
njs_str("true") },
More information about the nginx-devel
mailing list