summaryrefslogtreecommitdiffstats
path: root/server/util_pcre.c
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2022-01-20 18:01:40 +0100
committerYann Ylavic <ylavic@apache.org>2022-01-20 18:01:40 +0100
commit9cda8538a6655621ed7d9112bc1af488dd1d8205 (patch)
treef4a5f52ba3fb88a9bf196533287f1bb63c9ba09a /server/util_pcre.c
parent *) test: (diff)
downloadapache2-9cda8538a6655621ed7d9112bc1af488dd1d8205.tar.xz
apache2-9cda8538a6655621ed7d9112bc1af488dd1d8205.zip
ap_regex: Follow up to r1897240: runtime fallback to alloc/free.
Even though APR_HAS_THREAD_LOCAL is compiled in, ap_regexec() might still be called by non a apr_thread_t thread, let's fall back to alloc/free in this case too. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1897260 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'server/util_pcre.c')
-rw-r--r--server/util_pcre.c118
1 files changed, 69 insertions, 49 deletions
diff --git a/server/util_pcre.c b/server/util_pcre.c
index 2a3deefead..ece8801d4b 100644
--- a/server/util_pcre.c
+++ b/server/util_pcre.c
@@ -281,11 +281,57 @@ typedef int* match_data_pt;
typedef int* match_vector_pt;
#endif
+static APR_INLINE
+match_data_pt alloc_match_data(apr_size_t size,
+ match_vector_pt *ovector,
+ match_vector_pt small_vector)
+{
+ match_data_pt data;
+
+#ifdef HAVE_PCRE2
+ data = pcre2_match_data_create(size, NULL);
+ if (data) {
+ *ovector = pcre2_get_ovector_pointer(data);
+ }
+#else
+ if (size > POSIX_MALLOC_THRESHOLD) {
+ data = malloc(size * sizeof(int) * 3);
+ }
+ else {
+ data = small_vector;
+ }
+ *ovector = data;
+#endif
+
+ return data;
+}
+
+static APR_INLINE
+void free_match_data(match_data_pt data, apr_size_t size)
+{
+#ifdef HAVE_PCRE2
+ pcre2_match_data_free(data);
+#else
+ if (size > POSIX_MALLOC_THRESHOLD) {
+ free(data);
+ }
+#endif
+}
+
+static APR_INLINE
+void put_match_data(match_data_pt data, apr_size_t size, int to_free)
+{
+ if (to_free) {
+ free_match_data(data, size);
+ }
+}
+
#ifdef APR_HAS_THREAD_LOCAL
static match_data_pt get_match_data(apr_size_t size,
match_vector_pt *ovector,
- match_vector_pt small_vector)
+ match_vector_pt small_vector,
+ int *to_free)
{
apr_thread_t *current;
struct {
@@ -293,9 +339,15 @@ static match_data_pt get_match_data(apr_size_t size,
apr_size_t size;
} *tls = NULL;
- /* APR_HAS_THREAD_LOCAL garantees this works */
- current = apr_thread_current();
- ap_assert(current != NULL);
+ /* Even though APR_HAS_THREAD_LOCAL is compiled in we may still be
+ * called by non a apr_thread_t thread, let's fall back to alloc/free
+ * in this case.
+ */
+ current = ap_thread_current();
+ if (!current) {
+ *to_free = 1;
+ return alloc_match_data(size, ovector, small_vector);
+ }
apr_thread_data_get((void **)&tls, "apreg", current);
if (!tls || tls->size < size) {
@@ -335,49 +387,15 @@ static match_data_pt get_match_data(apr_size_t size,
return tls->data;
}
-/* Nothing to put back with thread local */
-static APR_INLINE void put_match_data(match_data_pt data,
- apr_size_t size)
-{ }
-
#else /* !APR_HAS_THREAD_LOCAL */
-/* Always allocate/free without thread local */
-
-static match_data_pt get_match_data(apr_size_t size,
- match_vector_pt *ovector,
- match_vector_pt small_vector)
-{
- match_data_pt data;
-
-#ifdef HAVE_PCRE2
- data = pcre2_match_data_create(size, NULL);
- if (data) {
- *ovector = pcre2_get_ovector_pointer(data);
- }
-#else
- if (size > POSIX_MALLOC_THRESHOLD) {
- data = malloc(size * sizeof(int) * 3);
- }
- else {
- data = small_vector;
- }
- *ovector = data;
-#endif
-
- return data;
-}
-
-static APR_INLINE void put_match_data(match_data_pt data,
- apr_size_t size)
+static APR_INLINE match_data_pt get_match_data(apr_size_t size,
+ match_vector_pt *ovector,
+ match_vector_pt small_vector,
+ int *to_free)
{
-#ifdef HAVE_PCRE2
- pcre2_match_data_free(data);
-#else
- if (size > POSIX_MALLOC_THRESHOLD) {
- free(data);
- }
-#endif
+ *to_free = 1;
+ return alloc_match_data(size, ovector, small_vector);
}
#endif /* !APR_HAS_THREAD_LOCAL */
@@ -395,14 +413,16 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
ap_regmatch_t *pmatch, int eflags)
{
int rc;
- int options = 0;
+ int options = 0, to_free = 0;
match_vector_pt ovector = NULL;
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(ncaps, &ovector, NULL);
+ match_data_pt data = get_match_data(ncaps, &ovector, NULL,
+ &to_free);
#else
int small_vector[POSIX_MALLOC_THRESHOLD * 3];
- match_data_pt data = get_match_data(ncaps, &ovector, small_vector);
+ match_data_pt data = get_match_data(ncaps, &ovector, small_vector,
+ &to_free);
#endif
if (!data) {
@@ -437,11 +457,11 @@ AP_DECLARE(int) ap_regexec_len(const ap_regex_t *preg, const char *buff,
}
for (; i < nmatch; i++)
pmatch[i].rm_so = pmatch[i].rm_eo = -1;
- put_match_data(data, ncaps);
+ put_match_data(data, ncaps, to_free);
return 0;
}
else {
- put_match_data(data, ncaps);
+ put_match_data(data, ncaps, to_free);
#ifdef HAVE_PCRE2
if (rc <= PCRE2_ERROR_UTF8_ERR1 && rc >= PCRE2_ERROR_UTF8_ERR21)
return AP_REG_INVARG;