summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Egesdahl <ryan.egesdahl@mongodb.com>2021-09-29 20:55:40 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-09-29 21:20:23 +0000
commit46ba1b4ec34ddb0bdecaa8261f770bbf1c860216 (patch)
tree1992753f2aca2dd94a8c0c4dfaafe1fbfd3ac92e
parent2361822068027ab179bf0bbab15c5559612130a6 (diff)
downloadmongo-46ba1b4ec34ddb0bdecaa8261f770bbf1c860216.tar.gz
SERVER-60299 Backport PCRE bugfix for Bugzilla #2613
-rw-r--r--jstests/core/regex_error.js11
-rw-r--r--src/third_party/pcre-8.42/patches/0003-SERVER-60299-fix-compile-error-memory-leak.patch76
-rw-r--r--src/third_party/pcre-8.42/pcre_compile.c7
-rw-r--r--src/third_party/pcre-8.42/pcre_exec.c2
4 files changed, 93 insertions, 3 deletions
diff --git a/jstests/core/regex_error.js b/jstests/core/regex_error.js
index 4b0fd4c4cb4..072b006b241 100644
--- a/jstests/core/regex_error.js
+++ b/jstests/core/regex_error.js
@@ -14,4 +14,15 @@ assert.commandFailedWithCode(coll.runCommand("find", {filter: {a: {$regex: "ab\0
ErrorCodes.BadValue);
assert.commandFailedWithCode(
coll.runCommand("find", {filter: {a: {$regex: "ab", $options: "\0i"}}}), 51108);
+
+// SERVER-58705: Should fail without a memory leak
+assert.commandFailedWithCode(coll.runCommand("find", {
+ filter: {
+ a: {
+ $regex:
+ "(?JJJ)>?W((?<a>!)||(?<a><aR)|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!)|;|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR(?<a>!aR)|(?<a>!?!)|(?<a>W!| P(?<e>!) C(?<a>!)||(?<a>!aR)|(?<a>!?!)||(?<a>)|(?<a>!6]|P(?<a>!)|(?<aa>!?!);|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR|(?<a>!?!);|(?<a>W!) (?<a>!)||(?<a>)|(?<a>||(?<a><a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR(?<a>!aR)|(?<a>!?!);|(?<a>W(?<a>!) C(?<a>!)||(?<a>!aR)|(?<a>|1|t(?<a>)(?<a>!??<aR)|(?<a>!:aW ) C(?<a>!)||(?<a>!aR)|(?<a>!?!|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR)|(?<a>!(?<a>)(?<a><aR)|(?<a>!:aW ) C(?<a>!)|;|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR(?<a>!aR)|(?<a>!?!);|(?<aa>W!| P(?<a>!) C(?<a>!)||(?<a>!aR(?<a>!aR)|(?<a>!?!)|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR)|(?<a>!?!)||(?<a>)|(?<a>!2]|P(?<a>!)|C(?<a>!()|(?<aa>!?!);|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR|(?<a>!?!);|(?<a>W!) __P(?<a>!-||(?<a>)|(?<a>||(?<a><a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR(?<a>!aR)|(?<a>!?!);|(?<a>W(?<a>!) C(?<a>!)||(?<a>!aR)|(?<a>|1|t(?<a>)(?<a>!??<a!) __P(?<a>!|(?<a>)|(?<a>!3]|P(?<a>!)|C(?<a>!)||(?<a>!aR)|(?<a>!?!);|(?<a>W!| P(?<a>!) C(?<a>!)|;|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR(?<a>!aR)|(?<a>! m);|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR)|(?<a>!?!)||(?<a>)|(?<a>!6]|P(?<a>!)|C(?<a>!()(?<aa>!?!);|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!?!);|(?<a>W!) !)||(?<a>)|(?<a>!6]|P(?<a>!)|(?<aa>!?!);|(?<a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR|(?<a>!?!);|(?<a>W!) (?<a>!)||(?<a>)|(?<a>||(?<a><a>W!| P(?<a>!) C(?<a>!)||(?<a>!aR(?<a>!aR)|(?<a>!?!);|(?<a>W(?<a>!) C(?<a>!)||(?<a>!aR)|(?<a>|1|t(?<a>)(?<a>!??<__P(?<a>!||(?<a>)|(?<a>||(?<a>!?<"
+ }
+ }
+}),
+ 51091);
})();
diff --git a/src/third_party/pcre-8.42/patches/0003-SERVER-60299-fix-compile-error-memory-leak.patch b/src/third_party/pcre-8.42/patches/0003-SERVER-60299-fix-compile-error-memory-leak.patch
new file mode 100644
index 00000000000..5b86b347ed5
--- /dev/null
+++ b/src/third_party/pcre-8.42/patches/0003-SERVER-60299-fix-compile-error-memory-leak.patch
@@ -0,0 +1,76 @@
+From 27721e18b083fec4947391ec8edfad0e8dff2784 Mon Sep 17 00:00:00 2001
+From: Ryan Egesdahl <ryan.egesdahl@mongodb.com>
+Date: Tue, 28 Sep 2021 15:02:04 -0700
+Subject: [PATCH] SERVER-60299 Backport PCRE bugfix for Bugzilla #2613
+
+This is a backport of patches from PCRE 8.45 which fixed a memory leak
+that occurred whenever a pattern with 20 or more capture groups fails to
+compile. Both patches are from revision 1765 of the upstream Subversion
+repository.
+
+ * https://vcs.pcre.org/pcre/code/trunk/pcre_compile.c?view=patch&r1=1765&r2=1764&pathrev=1765
+ * https://vcs.pcre.org/pcre/code/trunk/pcre_exec.c?view=patch&r1=1765&r2=1764&pathrev=1765
+
+They have been modified slightly to omit the copyright header change,
+which did not apply cleanly.
+
+---
+ src/third_party/pcre-8.42/pcre_compile.c | 7 +++++--
+ src/third_party/pcre-8.42/pcre_exec.c | 2 +-
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/third_party/pcre-8.42/pcre_compile.c b/src/third_party/pcre-8.42/pcre_compile.c
+index 6dd88860638..6b61e10ccd1 100644
+--- a/src/third_party/pcre-8.42/pcre_compile.c
++++ b/src/third_party/pcre-8.42/pcre_compile.c
+@@ -9087,6 +9087,8 @@ pcre_uchar cworkspace[COMPILE_WORK_SIZE];
+ similar way to cworkspace, it can be expanded using malloc() if necessary. */
+
+ named_group named_groups[NAMED_GROUP_LIST_SIZE];
++cd->named_groups = named_groups;
++cd->named_group_list_size = NAMED_GROUP_LIST_SIZE;
+
+ /* Set this early so that early errors get offset 0. */
+
+@@ -9360,8 +9362,6 @@ cd->hwm = cworkspace;
+ cd->iscondassert = FALSE;
+ cd->start_workspace = cworkspace;
+ cd->workspace_size = COMPILE_WORK_SIZE;
+-cd->named_groups = named_groups;
+-cd->named_group_list_size = NAMED_GROUP_LIST_SIZE;
+ cd->start_pattern = (const pcre_uchar *)pattern;
+ cd->end_pattern = (const pcre_uchar *)(pattern + STRLEN_UC((const pcre_uchar *)pattern));
+ cd->req_varyopt = 0;
+@@ -9472,6 +9472,7 @@ if (cd->names_found > 0)
+ add_name(cd, ng->name, ng->length, ng->number);
+ if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
+ (PUBL(free))((void *)cd->named_groups);
++ cd->named_group_list_size = 0; /* So we don't free it twice */
+ }
+
+ /* Set up a starting, non-extracting bracket, then compile the expression. On
+@@ -9622,6 +9623,8 @@ if (errorcode != 0)
+ {
+ (PUBL(free))(re);
+ PCRE_EARLY_ERROR_RETURN:
++ if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
++ (PUBL(free))((void *)cd->named_groups);
+ *erroroffset = (int)(ptr - (const pcre_uchar *)pattern);
+ PCRE_EARLY_ERROR_RETURN2:
+ *errorptr = find_error_text(errorcode);
+diff --git a/src/third_party/pcre-8.42/pcre_exec.c b/src/third_party/pcre-8.42/pcre_exec.c
+index 3fd58cbe31c..79c5cb98bdb 100644
+--- a/src/third_party/pcre-8.42/pcre_exec.c
++++ b/src/third_party/pcre-8.42/pcre_exec.c
+@@ -758,7 +758,7 @@ for (;;)
+ md->mark = NULL; /* In case previously set by assertion */
+ RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
+ eptrb, RM55);
+- if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
++ if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT || rrc == MATCH_KETRPOS) &&
+ md->mark == NULL) md->mark = ecode + 2;
+
+ /* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an
+--
+2.30.2
+
diff --git a/src/third_party/pcre-8.42/pcre_compile.c b/src/third_party/pcre-8.42/pcre_compile.c
index 6dd88860638..6b61e10ccd1 100644
--- a/src/third_party/pcre-8.42/pcre_compile.c
+++ b/src/third_party/pcre-8.42/pcre_compile.c
@@ -9087,6 +9087,8 @@ pcre_uchar cworkspace[COMPILE_WORK_SIZE];
similar way to cworkspace, it can be expanded using malloc() if necessary. */
named_group named_groups[NAMED_GROUP_LIST_SIZE];
+cd->named_groups = named_groups;
+cd->named_group_list_size = NAMED_GROUP_LIST_SIZE;
/* Set this early so that early errors get offset 0. */
@@ -9360,8 +9362,6 @@ cd->hwm = cworkspace;
cd->iscondassert = FALSE;
cd->start_workspace = cworkspace;
cd->workspace_size = COMPILE_WORK_SIZE;
-cd->named_groups = named_groups;
-cd->named_group_list_size = NAMED_GROUP_LIST_SIZE;
cd->start_pattern = (const pcre_uchar *)pattern;
cd->end_pattern = (const pcre_uchar *)(pattern + STRLEN_UC((const pcre_uchar *)pattern));
cd->req_varyopt = 0;
@@ -9472,6 +9472,7 @@ if (cd->names_found > 0)
add_name(cd, ng->name, ng->length, ng->number);
if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
(PUBL(free))((void *)cd->named_groups);
+ cd->named_group_list_size = 0; /* So we don't free it twice */
}
/* Set up a starting, non-extracting bracket, then compile the expression. On
@@ -9622,6 +9623,8 @@ if (errorcode != 0)
{
(PUBL(free))(re);
PCRE_EARLY_ERROR_RETURN:
+ if (cd->named_group_list_size > NAMED_GROUP_LIST_SIZE)
+ (PUBL(free))((void *)cd->named_groups);
*erroroffset = (int)(ptr - (const pcre_uchar *)pattern);
PCRE_EARLY_ERROR_RETURN2:
*errorptr = find_error_text(errorcode);
diff --git a/src/third_party/pcre-8.42/pcre_exec.c b/src/third_party/pcre-8.42/pcre_exec.c
index 3fd58cbe31c..79c5cb98bdb 100644
--- a/src/third_party/pcre-8.42/pcre_exec.c
+++ b/src/third_party/pcre-8.42/pcre_exec.c
@@ -758,7 +758,7 @@ for (;;)
md->mark = NULL; /* In case previously set by assertion */
RMATCH(eptr, ecode + PRIV(OP_lengths)[*ecode] + ecode[1], offset_top, md,
eptrb, RM55);
- if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT) &&
+ if ((rrc == MATCH_MATCH || rrc == MATCH_ACCEPT || rrc == MATCH_KETRPOS) &&
md->mark == NULL) md->mark = ecode + 2;
/* A return of MATCH_SKIP_ARG means that matching failed at SKIP with an