diff options
author | Yann Ylavic <ylavic@apache.org> | 2022-01-20 18:01:40 +0100 |
---|---|---|
committer | Yann Ylavic <ylavic@apache.org> | 2022-01-20 18:01:40 +0100 |
commit | 9cda8538a6655621ed7d9112bc1af488dd1d8205 (patch) | |
tree | f4a5f52ba3fb88a9bf196533287f1bb63c9ba09a /server/util_pcre.c | |
parent | *) test: (diff) | |
download | apache2-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.c | 118 |
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; |