summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--server/util_pcre.c85
1 files changed, 21 insertions, 64 deletions
diff --git a/server/util_pcre.c b/server/util_pcre.c
index 21f455ca75..488f389ffe 100644
--- a/server/util_pcre.c
+++ b/server/util_pcre.c
@@ -82,10 +82,10 @@ POSSIBILITY OF SUCH DAMAGE.
* sizeof(pcre2_general_context) + offsetof(pcre2_match_data, ovector)
*/
#define AP_PCRE_STACKBUF_SIZE \
- (128 + POSIX_MALLOC_THRESHOLD * sizeof(PCRE2_SIZE) * 2)
+ APR_ALIGN_DEFAULT(128 + POSIX_MALLOC_THRESHOLD * sizeof(PCRE2_SIZE) * 2)
#else
#define AP_PCRE_STACKBUF_SIZE \
- (POSIX_MALLOC_THRESHOLD * sizeof(int) * 3)
+ APR_ALIGN_DEFAULT(POSIX_MALLOC_THRESHOLD * sizeof(int) * 3)
#endif
/* Table of error strings corresponding to POSIX error codes; must be
@@ -276,9 +276,9 @@ AP_DECLARE(int) ap_regcomp(ap_regex_t * preg, const char *pattern, int cflags)
* is in POSIX_MALLOC_THRESHOLD macro that can be changed at configure time.
* PCRE2 takes an opaque match context and lets us provide the callbacks to
* manage the memory needed during the match, so we can still use a small stack
- * space that'll suffice for regexes up to POSIX_MALLOC_THRESHOLD captures (and
- * not too complex), above that either use some thread local subpool cache (if
- * AP_HAS_THREAD_LOCAL) or fall back to malloc()/free().
+ * space that will suffice for the match context struct and a single frame of
+ * POSIX_MALLOC_THRESHOLD captures, above that either use a thread local
+ * subpool cache (#if AP_HAS_THREAD_LOCAL) or fall back to malloc()/free().
*/
#if AP_HAS_THREAD_LOCAL && !defined(APREG_NO_THREAD_LOCAL)
@@ -294,14 +294,7 @@ typedef int* match_vector_pt;
#endif
#if APREG_USE_THREAD_LOCAL
-struct match_thread_state {
- char *heap;
- apr_size_t heap_size;
- apr_size_t heap_used;
- apr_pool_t *pool;
-};
-
-static AP_THREAD_LOCAL struct match_thread_state *thread_state;
+static AP_THREAD_LOCAL apr_pool_t *thread_pool;
#endif
struct match_data_state {
@@ -311,7 +304,7 @@ struct match_data_state {
#if APREG_USE_THREAD_LOCAL
apr_thread_t *thd;
- struct match_thread_state *ts;
+ apr_pool_t *pool;
#endif
#ifdef HAVE_PCRE2
@@ -325,59 +318,25 @@ struct match_data_state {
static void * private_malloc(size_t size, void *ctx)
{
struct match_data_state *state = ctx;
- apr_size_t avail;
- avail = sizeof(state->buf) - state->buf_used;
- if (avail >= size) {
+ if (size <= sizeof(state->buf) - state->buf_used) {
void *p = state->buf + state->buf_used;
- size = APR_ALIGN_DEFAULT(size);
- if (size > avail) {
- size = avail;
- }
- state->buf_used += size;
+ state->buf_used += APR_ALIGN_DEFAULT(size);
return p;
}
#if APREG_USE_THREAD_LOCAL
if (state->thd) {
- struct match_thread_state *ts = thread_state;
- void *p;
-
- if (!ts) {
- apr_pool_t *tp = apr_thread_pool_get(state->thd);
- ts = apr_pcalloc(tp, sizeof(*ts));
- apr_pool_create(&ts->pool, tp);
- thread_state = state->ts = ts;
- }
- else if (!state->ts) {
- ts->heap_used = 0;
- state->ts = ts;
- }
-
- avail = ts->heap_size - ts->heap_used;
- if (avail >= size) {
- size = APR_ALIGN_DEFAULT(size);
- if (size > avail) {
- size = avail;
+ apr_pool_t *pool = state->pool;
+ if (pool == NULL) {
+ pool = thread_pool;
+ if (pool == NULL) {
+ apr_pool_create(&pool, apr_thread_pool_get(state->thd));
+ thread_pool = pool;
}
- p = ts->heap + ts->heap_used;
+ state->pool = pool;
}
- else {
- ts->heap_size *= 2;
- size = APR_ALIGN_DEFAULT(size);
- if (ts->heap_size < size) {
- ts->heap_size = size;
- }
- if (ts->heap_size < AP_PCRE_STACKBUF_SIZE * 2) {
- ts->heap_size = AP_PCRE_STACKBUF_SIZE * 2;
- }
- ts->heap = apr_palloc(ts->pool, ts->heap_size);
- ts->heap_used = 0;
- p = ts->heap;
- }
-
- ts->heap_used += size;
- return p;
+ return apr_palloc(pool, size);
}
#endif
@@ -408,9 +367,10 @@ static APR_INLINE
int setup_state(struct match_data_state *state, apr_uint32_t ncaps)
{
state->buf_used = 0;
+
#if APREG_USE_THREAD_LOCAL
state->thd = ap_thread_current();
- state->ts = NULL;
+ state->pool = NULL;
#endif
#ifdef HAVE_PCRE2
@@ -454,14 +414,11 @@ void cleanup_state(struct match_data_state *state)
#endif
#if APREG_USE_THREAD_LOCAL
- if (state->ts) {
+ if (state->pool) {
/* Let the thread's pool allocator recycle or free according
* to its max_free setting.
*/
- struct match_thread_state *ts = state->ts;
- apr_pool_clear(ts->pool);
- ts->heap_size = 0;
- ts->heap = NULL;
+ apr_pool_clear(state->pool);
}
#endif
}