Skip to content

Commit a635ab8

Browse files
committed
bugfix: use of the ngx.re API might lead to errors like "pcre_compile() failed: failed to get memory" due to incorrect pcre_malloc and pcre_free handling. thanks Vittly for reporting this in github issue #72.
1 parent 745b47f commit a635ab8

8 files changed

+162
-88
lines changed

src/ngx_http_lua_headerfilterby.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ ngx_http_lua_header_filter_by_chunk(lua_State *L, ngx_http_request_t *r)
101101
{
102102
ngx_int_t rc;
103103
u_char *err_msg;
104+
#if (NGX_PCRE)
105+
ngx_pool_t *old_pool;
106+
#endif
104107

105108
/* set Lua VM panic handler */
106109
lua_atpanic(L, ngx_http_lua_atpanic);
@@ -110,15 +113,15 @@ ngx_http_lua_header_filter_by_chunk(lua_State *L, ngx_http_request_t *r)
110113

111114
#if (NGX_PCRE)
112115
/* XXX: work-around to nginx regex subsystem */
113-
ngx_http_lua_pcre_malloc_init(r->pool);
116+
old_pool = ngx_http_lua_pcre_malloc_init(r->pool);
114117
#endif
115118

116119
/* protected call user code */
117120
rc = lua_pcall(L, 0, 1, 0);
118121

119122
#if (NGX_PCRE)
120123
/* XXX: work-around to nginx regex subsystem */
121-
ngx_http_lua_pcre_malloc_done();
124+
ngx_http_lua_pcre_malloc_done(old_pool);
122125
#endif
123126

124127
if (rc != 0) {

src/ngx_http_lua_pcrefix.c

+52-20
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
#include "ddebug.h"
55

66
#include "ngx_http_lua_pcrefix.h"
7+
#include "stdio.h"
78

89
#if (NGX_PCRE)
910

10-
ngx_pool_t *ngx_http_lua_pcre_pool;
11+
static ngx_pool_t *ngx_http_lua_pcre_pool = NULL;
1112

1213
static void *(*old_pcre_malloc)(size_t);
1314
static void (*old_pcre_free)(void *ptr);
@@ -17,48 +18,79 @@ static void (*old_pcre_free)(void *ptr);
1718
* to use PCRE functions. As PCRE still has memory-leaking problems,
1819
* and nginx overwrote pcre_malloc/free hooks with its own static
1920
* functions, so nobody else can reuse nginx regex subsystem... */
20-
void *
21+
static void *
2122
ngx_http_lua_pcre_malloc(size_t size)
2223
{
23-
if (ngx_http_lua_pcre_pool) {
24-
return ngx_palloc(ngx_http_lua_pcre_pool, size);
25-
}
24+
dd("lua pcre pool is %p", ngx_http_lua_pcre_pool);
2625

27-
dd("returning NULL");
26+
if (ngx_http_lua_pcre_pool) {
27+
return ngx_palloc(ngx_http_lua_pcre_pool, size);
28+
}
2829

29-
return NULL;
30+
fprintf(stderr, "error: lua pcre malloc failed due to empty pcre pool");
31+
32+
return NULL;
3033
}
3134

3235

3336
static void
3437
ngx_http_lua_pcre_free(void *ptr)
3538
{
36-
if (ngx_http_lua_pcre_pool) {
37-
ngx_pfree(ngx_http_lua_pcre_pool, ptr);
38-
}
39+
dd("lua pcre pool is %p", ngx_http_lua_pcre_pool);
40+
41+
if (ngx_http_lua_pcre_pool) {
42+
ngx_pfree(ngx_http_lua_pcre_pool, ptr);
43+
return;
44+
}
45+
46+
fprintf(stderr, "error: lua pcre free failed due to empty pcre pool");
3947
}
4048

4149

42-
void
50+
ngx_pool_t *
4351
ngx_http_lua_pcre_malloc_init(ngx_pool_t *pool)
4452
{
45-
ngx_http_lua_pcre_pool = pool;
53+
ngx_pool_t *old_pool;
54+
55+
if (pcre_malloc != ngx_http_lua_pcre_malloc) {
56+
57+
dd("overriding nginx pcre malloc and free");
58+
59+
ngx_http_lua_pcre_pool = pool;
4660

47-
old_pcre_malloc = pcre_malloc;
48-
old_pcre_free = pcre_free;
61+
old_pcre_malloc = pcre_malloc;
62+
old_pcre_free = pcre_free;
4963

50-
pcre_malloc = ngx_http_lua_pcre_malloc;
51-
pcre_free = ngx_http_lua_pcre_free;
64+
pcre_malloc = ngx_http_lua_pcre_malloc;
65+
pcre_free = ngx_http_lua_pcre_free;
66+
67+
return NULL;
68+
}
69+
70+
dd("lua pcre pool was %p", ngx_http_lua_pcre_pool);
71+
72+
old_pool = ngx_http_lua_pcre_pool;
73+
ngx_http_lua_pcre_pool = pool;
74+
75+
dd("lua pcre pool is %p", ngx_http_lua_pcre_pool);
76+
77+
return old_pool;
5278
}
5379

5480

5581
void
56-
ngx_http_lua_pcre_malloc_done()
82+
ngx_http_lua_pcre_malloc_done(ngx_pool_t *old_pool)
5783
{
58-
ngx_http_lua_pcre_pool = NULL;
84+
dd("lua pcre pool was %p", ngx_http_lua_pcre_pool);
85+
86+
ngx_http_lua_pcre_pool = old_pool;
87+
88+
dd("lua pcre pool is %p", ngx_http_lua_pcre_pool);
5989

60-
pcre_malloc = old_pcre_malloc;
61-
pcre_free = old_pcre_free;
90+
if (old_pool == NULL) {
91+
pcre_malloc = old_pcre_malloc;
92+
pcre_free = old_pcre_free;
93+
}
6294
}
6395

6496
#endif /* NGX_PCRE */

src/ngx_http_lua_pcrefix.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@
66

77

88
#if (NGX_PCRE)
9-
extern ngx_pool_t *ngx_http_lua_pcre_pool;
10-
11-
void ngx_http_lua_pcre_malloc_init(ngx_pool_t *pool);
12-
void ngx_http_lua_pcre_malloc_done();
13-
void *ngx_http_lua_pcre_malloc(size_t size);
9+
ngx_pool_t *ngx_http_lua_pcre_malloc_init(ngx_pool_t *pool);
10+
void ngx_http_lua_pcre_malloc_done(ngx_pool_t *old_pool);
1411
#endif
1512

1613

0 commit comments

Comments
 (0)