~ubuntu-branches/ubuntu/trusty/nginx/trusty-proposed

« back to all changes in this revision

Viewing changes to src/core/ngx_regex.c

  • Committer: Package Import Robot
  • Author(s): Kartik Mistry
  • Date: 2013-04-25 12:51:45 UTC
  • mfrom: (1.3.28)
  • mto: (1.3.29) (15.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 64.
  • Revision ID: package-import@ubuntu.com-20130425125145-ugl0wor6bq0u5eae
Tags: upstream-1.4.0
ImportĀ upstreamĀ versionĀ 1.4.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
3
 * Copyright (C) Igor Sysoev
 
4
 * Copyright (C) Nginx, Inc.
4
5
 */
5
6
 
6
7
 
8
9
#include <ngx_core.h>
9
10
 
10
11
 
 
12
typedef struct {
 
13
    ngx_flag_t  pcre_jit;
 
14
} ngx_regex_conf_t;
 
15
 
 
16
 
11
17
static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
12
18
static void ngx_libc_cdecl ngx_regex_free(void *p);
 
19
#if (NGX_HAVE_PCRE_JIT)
 
20
static void ngx_pcre_free_studies(void *data);
 
21
#endif
 
22
 
 
23
static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);
 
24
 
 
25
static void *ngx_regex_create_conf(ngx_cycle_t *cycle);
 
26
static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf);
 
27
 
 
28
static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data);
 
29
static ngx_conf_post_t  ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };
 
30
 
 
31
 
 
32
static ngx_command_t  ngx_regex_commands[] = {
 
33
 
 
34
    { ngx_string("pcre_jit"),
 
35
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
 
36
      ngx_conf_set_flag_slot,
 
37
      0,
 
38
      offsetof(ngx_regex_conf_t, pcre_jit),
 
39
      &ngx_regex_pcre_jit_post },
 
40
 
 
41
      ngx_null_command
 
42
};
 
43
 
 
44
 
 
45
static ngx_core_module_t  ngx_regex_module_ctx = {
 
46
    ngx_string("regex"),
 
47
    ngx_regex_create_conf,
 
48
    ngx_regex_init_conf
 
49
};
 
50
 
 
51
 
 
52
ngx_module_t  ngx_regex_module = {
 
53
    NGX_MODULE_V1,
 
54
    &ngx_regex_module_ctx,                 /* module context */
 
55
    ngx_regex_commands,                    /* module directives */
 
56
    NGX_CORE_MODULE,                       /* module type */
 
57
    NULL,                                  /* init master */
 
58
    ngx_regex_module_init,                 /* init module */
 
59
    NULL,                                  /* init process */
 
60
    NULL,                                  /* init thread */
 
61
    NULL,                                  /* exit thread */
 
62
    NULL,                                  /* exit process */
 
63
    NULL,                                  /* exit master */
 
64
    NGX_MODULE_V1_PADDING
 
65
};
13
66
 
14
67
 
15
68
static ngx_pool_t  *ngx_pcre_pool;
 
69
static ngx_list_t  *ngx_pcre_studies;
16
70
 
17
71
 
18
72
void
23
77
}
24
78
 
25
79
 
26
 
ngx_regex_t *
27
 
ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, ngx_pool_t *pool,
28
 
    ngx_str_t *err)
 
80
static ngx_inline void
 
81
ngx_regex_malloc_init(ngx_pool_t *pool)
29
82
{
30
 
    int              erroff;
31
 
    const char      *errstr;
32
 
    ngx_regex_t     *re;
33
83
#if (NGX_THREADS)
34
84
    ngx_core_tls_t  *tls;
35
85
 
36
 
#if (NGX_SUPPRESS_WARN)
37
 
    tls = NULL;
38
 
#endif
39
 
 
40
86
    if (ngx_threaded) {
41
87
        tls = ngx_thread_get_tls(ngx_core_tls_key);
42
88
        tls->pool = pool;
43
 
    } else {
44
 
        ngx_pcre_pool = pool;
 
89
        return;
45
90
    }
46
91
 
47
 
#else
 
92
#endif
48
93
 
49
94
    ngx_pcre_pool = pool;
 
95
}
 
96
 
 
97
 
 
98
static ngx_inline void
 
99
ngx_regex_malloc_done(void)
 
100
{
 
101
#if (NGX_THREADS)
 
102
    ngx_core_tls_t  *tls;
 
103
 
 
104
    if (ngx_threaded) {
 
105
        tls = ngx_thread_get_tls(ngx_core_tls_key);
 
106
        tls->pool = NULL;
 
107
        return;
 
108
    }
50
109
 
51
110
#endif
52
111
 
53
 
    re = pcre_compile((const char *) pattern->data, (int) options,
 
112
    ngx_pcre_pool = NULL;
 
113
}
 
114
 
 
115
 
 
116
ngx_int_t
 
117
ngx_regex_compile(ngx_regex_compile_t *rc)
 
118
{
 
119
    int               n, erroff;
 
120
    char             *p;
 
121
    pcre             *re;
 
122
    const char       *errstr;
 
123
    ngx_regex_elt_t  *elt;
 
124
 
 
125
    ngx_regex_malloc_init(rc->pool);
 
126
 
 
127
    re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
54
128
                      &errstr, &erroff, NULL);
55
129
 
 
130
    /* ensure that there is no current pool */
 
131
    ngx_regex_malloc_done();
 
132
 
56
133
    if (re == NULL) {
57
 
       if ((size_t) erroff == pattern->len) {
58
 
           ngx_snprintf(err->data, err->len - 1,
59
 
                        "pcre_compile() failed: %s in \"%s\"%Z",
60
 
                        errstr, pattern->data);
 
134
        if ((size_t) erroff == rc->pattern.len) {
 
135
           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
 
136
                              "pcre_compile() failed: %s in \"%V\"",
 
137
                               errstr, &rc->pattern)
 
138
                      - rc->err.data;
 
139
 
61
140
        } else {
62
 
           ngx_snprintf(err->data, err->len - 1,
63
 
                        "pcre_compile() failed: %s in \"%s\" at \"%s\"%Z",
64
 
                        errstr, pattern->data, pattern->data + erroff);
65
 
        }
66
 
    }
67
 
 
68
 
    /* ensure that there is no current pool */
69
 
 
70
 
#if (NGX_THREADS)
71
 
    if (ngx_threaded) {
72
 
        tls->pool = NULL;
73
 
    } else {
74
 
        ngx_pcre_pool = NULL;
75
 
    }
76
 
#else
77
 
    ngx_pcre_pool = NULL;
78
 
#endif
79
 
 
80
 
    return re;
81
 
}
82
 
 
83
 
 
84
 
ngx_int_t
85
 
ngx_regex_capture_count(ngx_regex_t *re)
86
 
{
87
 
    int  rc, n;
88
 
 
89
 
    n = 0;
90
 
 
91
 
    rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &n);
92
 
 
93
 
    if (rc < 0) {
94
 
        return (ngx_int_t) rc;
95
 
    }
96
 
 
97
 
    return (ngx_int_t) n;
98
 
}
99
 
 
100
 
 
101
 
ngx_int_t
102
 
ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_int_t size)
103
 
{
104
 
    int  rc;
105
 
 
106
 
    rc = pcre_exec(re, NULL, (const char *) s->data, s->len, 0, 0,
107
 
                   captures, size);
108
 
 
109
 
    if (rc == -1) {
110
 
        return NGX_REGEX_NO_MATCHED;
111
 
    }
112
 
 
113
 
    return rc;
 
141
           rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
 
142
                              "pcre_compile() failed: %s in \"%V\" at \"%s\"",
 
143
                               errstr, &rc->pattern, rc->pattern.data + erroff)
 
144
                      - rc->err.data;
 
145
        }
 
146
 
 
147
        return NGX_ERROR;
 
148
    }
 
149
 
 
150
    rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t));
 
151
    if (rc->regex == NULL) {
 
152
        return NGX_ERROR;
 
153
    }
 
154
 
 
155
    rc->regex->code = re;
 
156
 
 
157
    /* do not study at runtime */
 
158
 
 
159
    if (ngx_pcre_studies != NULL) {
 
160
        elt = ngx_list_push(ngx_pcre_studies);
 
161
        if (elt == NULL) {
 
162
            return NGX_ERROR;
 
163
        }
 
164
 
 
165
        elt->regex = rc->regex;
 
166
        elt->name = rc->pattern.data;
 
167
    }
 
168
 
 
169
    n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
 
170
    if (n < 0) {
 
171
        p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
 
172
        goto failed;
 
173
    }
 
174
 
 
175
    if (rc->captures == 0) {
 
176
        return NGX_OK;
 
177
    }
 
178
 
 
179
    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
 
180
    if (n < 0) {
 
181
        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
 
182
        goto failed;
 
183
    }
 
184
 
 
185
    if (rc->named_captures == 0) {
 
186
        return NGX_OK;
 
187
    }
 
188
 
 
189
    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
 
190
    if (n < 0) {
 
191
        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
 
192
        goto failed;
 
193
    }
 
194
 
 
195
    n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
 
196
    if (n < 0) {
 
197
        p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
 
198
        goto failed;
 
199
    }
 
200
 
 
201
    return NGX_OK;
 
202
 
 
203
failed:
 
204
 
 
205
    rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
 
206
                  - rc->err.data;
 
207
    return NGX_OK;
114
208
}
115
209
 
116
210
 
133
227
 
134
228
        if (n < 0) {
135
229
            ngx_log_error(NGX_LOG_ALERT, log, 0,
136
 
                          ngx_regex_exec_n " failed: %d on \"%V\" using \"%s\"",
 
230
                          ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
137
231
                          n, s, re[i].name);
138
232
            return NGX_ERROR;
139
233
        }
157
251
    if (ngx_threaded) {
158
252
        tls = ngx_thread_get_tls(ngx_core_tls_key);
159
253
        pool = tls->pool;
 
254
 
160
255
    } else {
161
256
        pool = ngx_pcre_pool;
162
257
    }
 
258
 
163
259
#else
 
260
 
164
261
    pool = ngx_pcre_pool;
 
262
 
165
263
#endif
166
264
 
167
265
    if (pool) {
177
275
{
178
276
    return;
179
277
}
 
278
 
 
279
 
 
280
#if (NGX_HAVE_PCRE_JIT)
 
281
 
 
282
static void
 
283
ngx_pcre_free_studies(void *data)
 
284
{
 
285
    ngx_list_t *studies = data;
 
286
 
 
287
    ngx_uint_t        i;
 
288
    ngx_list_part_t  *part;
 
289
    ngx_regex_elt_t  *elts;
 
290
 
 
291
    part = &studies->part;
 
292
    elts = part->elts;
 
293
 
 
294
    for (i = 0 ; /* void */ ; i++) {
 
295
 
 
296
        if (i >= part->nelts) {
 
297
            if (part->next == NULL) {
 
298
                break;
 
299
            }
 
300
 
 
301
            part = part->next;
 
302
            elts = part->elts;
 
303
            i = 0;
 
304
        }
 
305
 
 
306
        if (elts[i].regex->extra != NULL) {
 
307
            pcre_free_study(elts[i].regex->extra);
 
308
        }
 
309
    }
 
310
}
 
311
 
 
312
#endif
 
313
 
 
314
 
 
315
static ngx_int_t
 
316
ngx_regex_module_init(ngx_cycle_t *cycle)
 
317
{
 
318
    int               opt;
 
319
    const char       *errstr;
 
320
    ngx_uint_t        i;
 
321
    ngx_list_part_t  *part;
 
322
    ngx_regex_elt_t  *elts;
 
323
 
 
324
    opt = 0;
 
325
 
 
326
#if (NGX_HAVE_PCRE_JIT)
 
327
    {
 
328
    ngx_regex_conf_t    *rcf;
 
329
    ngx_pool_cleanup_t  *cln;
 
330
 
 
331
    rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module);
 
332
 
 
333
    if (rcf->pcre_jit) {
 
334
        opt = PCRE_STUDY_JIT_COMPILE;
 
335
 
 
336
        /*
 
337
         * The PCRE JIT compiler uses mmap for its executable codes, so we
 
338
         * have to explicitly call the pcre_free_study() function to free
 
339
         * this memory.
 
340
         */
 
341
 
 
342
        cln = ngx_pool_cleanup_add(cycle->pool, 0);
 
343
        if (cln == NULL) {
 
344
            return NGX_ERROR;
 
345
        }
 
346
 
 
347
        cln->handler = ngx_pcre_free_studies;
 
348
        cln->data = ngx_pcre_studies;
 
349
    }
 
350
    }
 
351
#endif
 
352
 
 
353
    ngx_regex_malloc_init(cycle->pool);
 
354
 
 
355
    part = &ngx_pcre_studies->part;
 
356
    elts = part->elts;
 
357
 
 
358
    for (i = 0 ; /* void */ ; i++) {
 
359
 
 
360
        if (i >= part->nelts) {
 
361
            if (part->next == NULL) {
 
362
                break;
 
363
            }
 
364
 
 
365
            part = part->next;
 
366
            elts = part->elts;
 
367
            i = 0;
 
368
        }
 
369
 
 
370
        elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr);
 
371
 
 
372
        if (errstr != NULL) {
 
373
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
 
374
                          "pcre_study() failed: %s in \"%s\"",
 
375
                          errstr, elts[i].name);
 
376
        }
 
377
 
 
378
#if (NGX_HAVE_PCRE_JIT)
 
379
        if (opt & PCRE_STUDY_JIT_COMPILE) {
 
380
            int jit, n;
 
381
 
 
382
            jit = 0;
 
383
            n = pcre_fullinfo(elts[i].regex->code, elts[i].regex->extra,
 
384
                              PCRE_INFO_JIT, &jit);
 
385
 
 
386
            if (n != 0 || jit != 1) {
 
387
                ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
 
388
                              "JIT compiler does not support pattern: \"%s\"",
 
389
                              elts[i].name);
 
390
            }
 
391
        }
 
392
#endif
 
393
    }
 
394
 
 
395
    ngx_regex_malloc_done();
 
396
 
 
397
    ngx_pcre_studies = NULL;
 
398
 
 
399
    return NGX_OK;
 
400
}
 
401
 
 
402
 
 
403
static void *
 
404
ngx_regex_create_conf(ngx_cycle_t *cycle)
 
405
{
 
406
    ngx_regex_conf_t  *rcf;
 
407
 
 
408
    rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
 
409
    if (rcf == NULL) {
 
410
        return NULL;
 
411
    }
 
412
 
 
413
    rcf->pcre_jit = NGX_CONF_UNSET;
 
414
 
 
415
    ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t));
 
416
    if (ngx_pcre_studies == NULL) {
 
417
        return NULL;
 
418
    }
 
419
 
 
420
    return rcf;
 
421
}
 
422
 
 
423
 
 
424
static char *
 
425
ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf)
 
426
{
 
427
    ngx_regex_conf_t *rcf = conf;
 
428
 
 
429
    ngx_conf_init_value(rcf->pcre_jit, 0);
 
430
 
 
431
    return NGX_CONF_OK;
 
432
}
 
433
 
 
434
 
 
435
static char *
 
436
ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
 
437
{
 
438
    ngx_flag_t  *fp = data;
 
439
 
 
440
    if (*fp == 0) {
 
441
        return NGX_CONF_OK;
 
442
    }
 
443
 
 
444
#if (NGX_HAVE_PCRE_JIT)
 
445
    {
 
446
    int  jit, r;
 
447
 
 
448
    jit = 0;
 
449
    r = pcre_config(PCRE_CONFIG_JIT, &jit);
 
450
 
 
451
    if (r != 0 || jit != 1) {
 
452
        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
 
453
                           "PCRE library does not support JIT");
 
454
        *fp = 0;
 
455
    }
 
456
    }
 
457
#else
 
458
    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
 
459
                       "nginx was built without PCRE JIT support");
 
460
    *fp = 0;
 
461
#endif
 
462
 
 
463
    return NGX_CONF_OK;
 
464
}