summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2022-07-15 10:46:37 +0000
committerYann Ylavic <ylavic@apache.org>2022-07-15 10:46:37 +0000
commit97afea48fd328304d74fc174c742518175063ab7 (patch)
treeba36314205a3d0e13d12f153dc5786a267c6f15c /server
parentf589ecaa68cfe3be8694042035efc8343715e25c (diff)
downloadhttpd-97afea48fd328304d74fc174c742518175063ab7.tar.gz
util_pcre: Restore nmatch < ncaps behaviour with PCRE1 (only).
When the requested nmatch is below the number of captures for the regex (i.e. nmatch is zero if the user does not care about the captures), with PCRE1 we can pass a smaller ovector to pcre_exec() (or even NULL) which allows for somes optimizations (less or even no recursion) internally in pcre. This might avoid crashes due to stack usage/exhaustion with pathological patterns (see BZ 66119). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1902732 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server')
-rw-r--r--server/util_pcre.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/server/util_pcre.c b/server/util_pcre.c
index 53096ea69c..e3ee455837 100644
--- a/server/util_pcre.c
+++ b/server/util_pcre.c
@@ -484,6 +484,32 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
match_vector_pt ovector = NULL;
apr_uint32_t ncaps = (apr_uint32_t)preg->re_nsub + 1;
+#ifndef HAVE_PCRE2
+ /* This is fine if pcre_exec() gets a vector size smaller than the
+ * number of capturing groups (it will treat the remaining ones as
+ * non-capturing), but if the vector is too small to keep track of
+ * the potential backrefs within the pattern, it will temporarily
+ * malloc()ate the necessary space anyway. So let's provide a vector
+ * of at least PCRE_INFO_BACKREFMAX entries (likely zero, otherwise
+ * the vector is most likely cached already anyway).
+ * Note that if no captures are to be used by the caller, passing an
+ * nmatch of zero (thus forcing all groups to be non-capturing) may
+ * allow for some optimizations and/or less recursion (stack usage)
+ * with PCRE1, unless backrefs..
+ */
+ if (ncaps > nmatch) {
+ int backrefmax = 0;
+ pcre_fullinfo((const pcre *)preg->re_pcre, NULL,
+ PCRE_INFO_BACKREFMAX, &backrefmax);
+ if (backrefmax > 0 && (apr_uint32_t)backrefmax >= nmatch) {
+ ncaps = (apr_uint32_t)backrefmax + 1;
+ }
+ else {
+ ncaps = nmatch;
+ }
+ }
+#endif
+
if (!setup_state(&state, ncaps)) {
return AP_REG_ESPACE;
}