mirror of
https://github.com/apache/httpd.git
synced 2025-08-01 16:41:19 +00:00
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
This commit is contained in:
@ -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)
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
#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;
|
||||
|
Reference in New Issue
Block a user