]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
ap_regex: PCRE needs buffers sized against the number of captures only.
authorYann Ylavic <ylavic@apache.org>
Thu, 20 Jan 2022 12:16:58 +0000 (12:16 +0000)
committerYann Ylavic <ylavic@apache.org>
Thu, 20 Jan 2022 12:16:58 +0000 (12:16 +0000)
No more (useless), no less (or PCRE will allocate a new buffer by itself to
satisfy the needs), so we should base our buffer size solely on the number
of captures in the regex (determined at compile time from the pattern).

The nmatch provided by the user is used to fill in pmatch only (up to that),
but "our" buffers are sized exactly as needed to avoid oversized allocations
or PCRE allocating by itself.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1897244 13f79535-47bb-0310-9956-ffa450edef68

server/util_pcre.c

index 1dcd950792938136c05851e39bb9fd6475a73d52..9bfa4791d8a3e7f361d8227120a5916785787edd 100644 (file)
@@ -396,13 +396,12 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
     int rc;
     int options = 0;
     match_vector_pt ovector = NULL;
-    apr_size_t nlim = ((apr_size_t)preg->re_nsub + 1) > nmatch
-                    ? ((apr_size_t)preg->re_nsub + 1) : nmatch;
+    apr_size_t ncaps = (apr_size_t)preg->re_nsub + 1;
 #if defined(HAVE_PCRE2) || defined(APR_HAS_THREAD_LOCAL)
-    match_data_pt data = get_match_data(nlim, &ovector, NULL);
+    match_data_pt data = get_match_data(ncaps, &ovector, NULL);
 #else
     int small_vector[POSIX_MALLOC_THRESHOLD * 3];
-    match_data_pt data = get_match_data(nlim, &ovector, small_vector);
+    match_data_pt data = get_match_data(ncaps, &ovector, small_vector);
 #endif
 
     if (!data) {
@@ -424,25 +423,26 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
                      0, options, data, NULL);
 #else
     rc = pcre_exec((const pcre *)preg->re_pcre, NULL, buff, (int)len,
-                   0, options, ovector, nlim * 3);
+                   0, options, ovector, ncaps * 3);
 #endif
 
     if (rc >= 0) {
-        apr_size_t n, i;
+        apr_size_t n = rc, i;
         if (rc == 0)
-            rc = nlim; /* All captured slots were filled in */
-        n = (apr_size_t)rc < nmatch ? (apr_size_t)rc : nmatch;
+            rc = ncaps; /* All captured slots were filled in */
+        else if (n > nmatch)
+            n = nmatch;
         for (i = 0; i < n; i++) {
             pmatch[i].rm_so = ovector[i * 2];
             pmatch[i].rm_eo = ovector[i * 2 + 1];
         }
         for (; i < nmatch; i++)
             pmatch[i].rm_so = pmatch[i].rm_eo = -1;
-        put_match_data(data, nlim);
+        put_match_data(data, ncaps);
         return 0;
     }
     else {
-        put_match_data(data, nlim);
+        put_match_data(data, ncaps);
 #ifdef HAVE_PCRE2
         if (rc <= PCRE2_ERROR_UTF8_ERR1 && rc >= PCRE2_ERROR_UTF8_ERR21)
             return AP_REG_INVARG;