Mailing List Archive

svn commit: r1902732 - /httpd/httpd/trunk/server/util_pcre.c
Author: ylavic
Date: Fri Jul 15 10:46:37 2022
New Revision: 1902732

URL: http://svn.apache.org/viewvc?rev=1902732&view=rev
Log:
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).


Modified:
httpd/httpd/trunk/server/util_pcre.c

Modified: httpd/httpd/trunk/server/util_pcre.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/util_pcre.c?rev=1902732&r1=1902731&r2=1902732&view=diff
==============================================================================
--- httpd/httpd/trunk/server/util_pcre.c (original)
+++ httpd/httpd/trunk/server/util_pcre.c Fri Jul 15 10:46:37 2022
@@ -484,6 +484,32 @@ AP_DECLARE(int) ap_regexec_len(const ap_
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;
}