diff options
author | Yann Ylavic <ylavic@apache.org> | 2022-07-15 12:46:37 +0200 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2022-07-15 12:46:37 +0200 |
commit | 97afea48fd328304d74fc174c742518175063ab7 (patch) | |
tree | ba36314205a3d0e13d12f153dc5786a267c6f15c /server | |
parent | util_pcre: Add a thread local subpool cache for when stack does not suffice. (diff) | |
download | apache2-97afea48fd328304d74fc174c742518175063ab7.tar.xz apache2-97afea48fd328304d74fc174c742518175063ab7.zip |
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.c | 26 |
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; } |