diff options
author | Ryan Egesdahl <ryan.egesdahl@mongodb.com> | 2021-09-29 20:55:40 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-09-29 21:20:23 +0000 |
commit | 46ba1b4ec34ddb0bdecaa8261f770bbf1c860216 (patch) | |
tree | 1992753f2aca2dd94a8c0c4dfaafe1fbfd3ac92e | |
parent | 2361822068027ab179bf0bbab15c5559612130a6 (diff) | |
download | mongo-46ba1b4ec34ddb0bdecaa8261f770bbf1c860216.tar.gz |
SERVER-60299 Backport PCRE bugfix for Bugzilla #2613
-rw-r--r-- | jstests/core/regex_error.js | 11 | ||||
-rw-r--r-- | src/third_party/pcre-8.42/patches/0003-SERVER-60299-fix-compile-error-memory-leak.patch | 76 | ||||
-rw-r--r-- | src/third_party/pcre-8.42/pcre_compile.c | 7 | ||||
-rw-r--r-- | src/third_party/pcre-8.42/pcre_exec.c | 2 |
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 |