Skip to content

Commit

Permalink
Core: fixed ngx_pcre_studies cleanup.
Browse files Browse the repository at this point in the history
If a configuration parsing fails for some reason, ngx_regex_module_init()
is not called, and ngx_pcre_studies remained set despite the fact that
the pool it was allocated from is already freed.  This might result in
a segmentation fault during runtime regular expression compilation, such
as in SSI, for example, in the single process mode, or if a worker process
died and was respawned from a master process in such an inconsistent state.

Fix is to clear ngx_pcre_studies from the pool cleanup handler (which is
anyway used to free JIT-compiled patterns).
  • Loading branch information
mdounin committed Dec 24, 2021
1 parent 363505e commit 09268f5
Showing 1 changed file with 43 additions and 40 deletions.
83 changes: 43 additions & 40 deletions src/core/ngx_regex.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@


typedef struct {
ngx_flag_t pcre_jit;
ngx_flag_t pcre_jit;
ngx_list_t *studies;
} ngx_regex_conf_t;


static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
static void ngx_libc_cdecl ngx_regex_free(void *p);
#if (NGX_HAVE_PCRE_JIT)
static void ngx_pcre_free_studies(void *data);
#endif
static void ngx_regex_cleanup(void *data);

static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);

Expand Down Expand Up @@ -248,18 +247,17 @@ ngx_regex_free(void *p)
}


#if (NGX_HAVE_PCRE_JIT)

static void
ngx_pcre_free_studies(void *data)
ngx_regex_cleanup(void *data)
{
ngx_list_t *studies = data;
#if (NGX_HAVE_PCRE_JIT)
ngx_regex_conf_t *rcf = data;

ngx_uint_t i;
ngx_list_part_t *part;
ngx_regex_elt_t *elts;

part = &studies->part;
part = &rcf->studies->part;
elts = part->elts;

for (i = 0; /* void */ ; i++) {
Expand All @@ -274,56 +272,50 @@ ngx_pcre_free_studies(void *data)
i = 0;
}

/*
* The PCRE JIT compiler uses mmap for its executable codes, so we
* have to explicitly call the pcre_free_study() function to free
* this memory.
*/

if (elts[i].regex->extra != NULL) {
pcre_free_study(elts[i].regex->extra);
}
}
}

#endif

/*
* On configuration parsing errors ngx_regex_module_init() will not
* be called. Make sure ngx_pcre_studies is properly cleared anyway.
*/

ngx_pcre_studies = NULL;
}


static ngx_int_t
ngx_regex_module_init(ngx_cycle_t *cycle)
{
int opt;
const char *errstr;
ngx_uint_t i;
ngx_list_part_t *part;
ngx_regex_elt_t *elts;
int opt;
const char *errstr;
ngx_uint_t i;
ngx_list_part_t *part;
ngx_regex_elt_t *elts;
ngx_regex_conf_t *rcf;

opt = 0;

#if (NGX_HAVE_PCRE_JIT)
{
ngx_regex_conf_t *rcf;
ngx_pool_cleanup_t *cln;

rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);

#if (NGX_HAVE_PCRE_JIT)
if (rcf->pcre_jit) {
opt = PCRE_STUDY_JIT_COMPILE;

/*
* The PCRE JIT compiler uses mmap for its executable codes, so we
* have to explicitly call the pcre_free_study() function to free
* this memory.
*/

cln = ngx_pool_cleanup_add(cycle->pool, 0);
if (cln == NULL) {
return NGX_ERROR;
}

cln->handler = ngx_pcre_free_studies;
cln->data = ngx_pcre_studies;
}
}
#endif

ngx_regex_malloc_init(cycle->pool);

part = &ngx_pcre_studies->part;
part = &rcf->studies->part;
elts = part->elts;

for (i = 0; /* void */ ; i++) {
Expand Down Expand Up @@ -374,7 +366,8 @@ ngx_regex_module_init(ngx_cycle_t *cycle)
static void *
ngx_regex_create_conf(ngx_cycle_t *cycle)
{
ngx_regex_conf_t *rcf;
ngx_regex_conf_t *rcf;
ngx_pool_cleanup_t *cln;

rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
if (rcf == NULL) {
Expand All @@ -383,11 +376,21 @@ ngx_regex_create_conf(ngx_cycle_t *cycle)

rcf->pcre_jit = NGX_CONF_UNSET;

ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
if (ngx_pcre_studies == NULL) {
cln = ngx_pool_cleanup_add(cycle->pool, 0);
if (cln == NULL) {
return NULL;
}

cln->handler = ngx_regex_cleanup;
cln->data = rcf;

rcf->studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
if (rcf->studies == NULL) {
return NULL;
}

ngx_pcre_studies = rcf->studies;

return rcf;
}

Expand Down

0 comments on commit 09268f5

Please sign in to comment.