src/core/ngx_regex.c - nginx source code

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. typedef struct {
  8.     ngx_flag_t   pcre_jit;
  9.     ngx_list_t  *studies;
  10. } ngx_regex_conf_t;


  11. static ngx_inline void ngx_regex_malloc_init(ngx_pool_t *pool);
  12. static ngx_inline void ngx_regex_malloc_done(void);

  13. #if (NGX_PCRE2)
  14. static void * ngx_libc_cdecl ngx_regex_malloc(size_t size, void *data);
  15. static void ngx_libc_cdecl ngx_regex_free(void *p, void *data);
  16. #else
  17. static void * ngx_libc_cdecl ngx_regex_malloc(size_t size);
  18. static void ngx_libc_cdecl ngx_regex_free(void *p);
  19. #endif
  20. static void ngx_regex_cleanup(void *data);

  21. static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle);

  22. static void *ngx_regex_create_conf(ngx_cycle_t *cycle);
  23. static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf);

  24. static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data);
  25. static ngx_conf_post_t  ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit };


  26. static ngx_command_t  ngx_regex_commands[] = {

  27.     { ngx_string("pcre_jit"),
  28.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  29.       ngx_conf_set_flag_slot,
  30.       0,
  31.       offsetof(ngx_regex_conf_t, pcre_jit),
  32.       &ngx_regex_pcre_jit_post },

  33.       ngx_null_command
  34. };


  35. static ngx_core_module_t  ngx_regex_module_ctx = {
  36.     ngx_string("regex"),
  37.     ngx_regex_create_conf,
  38.     ngx_regex_init_conf
  39. };


  40. ngx_module_t  ngx_regex_module = {
  41.     NGX_MODULE_V1,
  42.     &ngx_regex_module_ctx,                 /* module context */
  43.     ngx_regex_commands,                    /* module directives */
  44.     NGX_CORE_MODULE,                       /* module type */
  45.     NULL,                                  /* init master */
  46.     ngx_regex_module_init,                 /* init module */
  47.     NULL,                                  /* init process */
  48.     NULL,                                  /* init thread */
  49.     NULL,                                  /* exit thread */
  50.     NULL,                                  /* exit process */
  51.     NULL,                                  /* exit master */
  52.     NGX_MODULE_V1_PADDING
  53. };


  54. static ngx_pool_t             *ngx_regex_pool;
  55. static ngx_list_t             *ngx_regex_studies;
  56. static ngx_uint_t              ngx_regex_direct_alloc;

  57. #if (NGX_PCRE2)
  58. static pcre2_compile_context  *ngx_regex_compile_context;
  59. static pcre2_match_data       *ngx_regex_match_data;
  60. static ngx_uint_t              ngx_regex_match_data_size;
  61. #endif


  62. void
  63. ngx_regex_init(void)
  64. {
  65. #if !(NGX_PCRE2)
  66.     pcre_malloc = ngx_regex_malloc;
  67.     pcre_free = ngx_regex_free;
  68. #endif
  69. }


  70. static ngx_inline void
  71. ngx_regex_malloc_init(ngx_pool_t *pool)
  72. {
  73.     ngx_regex_pool = pool;
  74.     ngx_regex_direct_alloc = (pool == NULL) ? 1 : 0;
  75. }


  76. static ngx_inline void
  77. ngx_regex_malloc_done(void)
  78. {
  79.     ngx_regex_pool = NULL;
  80.     ngx_regex_direct_alloc = 0;
  81. }


  82. #if (NGX_PCRE2)

  83. ngx_int_t
  84. ngx_regex_compile(ngx_regex_compile_t *rc)
  85. {
  86.     int                     n, errcode;
  87.     char                   *p;
  88.     u_char                  errstr[128];
  89.     size_t                  erroff;
  90.     uint32_t                options;
  91.     pcre2_code             *re;
  92.     ngx_regex_elt_t        *elt;
  93.     pcre2_general_context  *gctx;
  94.     pcre2_compile_context  *cctx;

  95.     if (ngx_regex_compile_context == NULL) {
  96.         /*
  97.          * Allocate a compile context if not yet allocated.  This uses
  98.          * direct allocations from heap, so the result can be cached
  99.          * even at runtime.
  100.          */

  101.         ngx_regex_malloc_init(NULL);

  102.         gctx = pcre2_general_context_create(ngx_regex_malloc, ngx_regex_free,
  103.                                             NULL);
  104.         if (gctx == NULL) {
  105.             ngx_regex_malloc_done();
  106.             goto nomem;
  107.         }

  108.         cctx = pcre2_compile_context_create(gctx);
  109.         if (cctx == NULL) {
  110.             pcre2_general_context_free(gctx);
  111.             ngx_regex_malloc_done();
  112.             goto nomem;
  113.         }

  114.         ngx_regex_compile_context = cctx;

  115.         pcre2_general_context_free(gctx);
  116.         ngx_regex_malloc_done();
  117.     }

  118.     options = 0;

  119.     if (rc->options & NGX_REGEX_CASELESS) {
  120.         options |= PCRE2_CASELESS;
  121.     }

  122.     if (rc->options & NGX_REGEX_MULTILINE) {
  123.         options |= PCRE2_MULTILINE;
  124.     }

  125.     if (rc->options & ~(NGX_REGEX_CASELESS|NGX_REGEX_MULTILINE)) {
  126.         rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  127.                             "regex \"%V\" compilation failed: invalid options",
  128.                             &rc->pattern)
  129.                       - rc->err.data;
  130.         return NGX_ERROR;
  131.     }

  132.     ngx_regex_malloc_init(rc->pool);

  133.     re = pcre2_compile(rc->pattern.data, rc->pattern.len, options,
  134.                        &errcode, &erroff, ngx_regex_compile_context);

  135.     /* ensure that there is no current pool */
  136.     ngx_regex_malloc_done();

  137.     if (re == NULL) {
  138.         pcre2_get_error_message(errcode, errstr, 128);

  139.         if ((size_t) erroff == rc->pattern.len) {
  140.             rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  141.                               "pcre2_compile() failed: %s in \"%V\"",
  142.                                errstr, &rc->pattern)
  143.                           - rc->err.data;

  144.         } else {
  145.             rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  146.                               "pcre2_compile() failed: %s in \"%V\" at \"%s\"",
  147.                                errstr, &rc->pattern, rc->pattern.data + erroff)
  148.                           - rc->err.data;
  149.         }

  150.         return NGX_ERROR;
  151.     }

  152.     rc->regex = re;

  153.     /* do not study at runtime */

  154.     if (ngx_regex_studies != NULL) {
  155.         elt = ngx_list_push(ngx_regex_studies);
  156.         if (elt == NULL) {
  157.             goto nomem;
  158.         }

  159.         elt->regex = rc->regex;
  160.         elt->name = rc->pattern.data;
  161.     }

  162.     n = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &rc->captures);
  163.     if (n < 0) {
  164.         p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_CAPTURECOUNT) failed: %d";
  165.         goto failed;
  166.     }

  167.     if (rc->captures == 0) {
  168.         return NGX_OK;
  169.     }

  170.     n = pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &rc->named_captures);
  171.     if (n < 0) {
  172.         p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMECOUNT) failed: %d";
  173.         goto failed;
  174.     }

  175.     if (rc->named_captures == 0) {
  176.         return NGX_OK;
  177.     }

  178.     n = pcre2_pattern_info(re, PCRE2_INFO_NAMEENTRYSIZE, &rc->name_size);
  179.     if (n < 0) {
  180.         p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMEENTRYSIZE) failed: %d";
  181.         goto failed;
  182.     }

  183.     n = pcre2_pattern_info(re, PCRE2_INFO_NAMETABLE, &rc->names);
  184.     if (n < 0) {
  185.         p = "pcre2_pattern_info(\"%V\", PCRE2_INFO_NAMETABLE) failed: %d";
  186.         goto failed;
  187.     }

  188.     return NGX_OK;

  189. failed:

  190.     rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
  191.                   - rc->err.data;
  192.     return NGX_ERROR;

  193. nomem:

  194.     rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  195.                                "regex \"%V\" compilation failed: no memory",
  196.                                &rc->pattern)
  197.                   - rc->err.data;
  198.     return NGX_ERROR;
  199. }

  200. #else

  201. ngx_int_t
  202. ngx_regex_compile(ngx_regex_compile_t *rc)
  203. {
  204.     int               n, erroff;
  205.     char             *p;
  206.     pcre             *re;
  207.     const char       *errstr;
  208.     ngx_uint_t        options;
  209.     ngx_regex_elt_t  *elt;

  210.     options = 0;

  211.     if (rc->options & NGX_REGEX_CASELESS) {
  212.         options |= PCRE_CASELESS;
  213.     }

  214.     if (rc->options & NGX_REGEX_MULTILINE) {
  215.         options |= PCRE_MULTILINE;
  216.     }

  217.     if (rc->options & ~(NGX_REGEX_CASELESS|NGX_REGEX_MULTILINE)) {
  218.         rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  219.                             "regex \"%V\" compilation failed: invalid options",
  220.                             &rc->pattern)
  221.                       - rc->err.data;
  222.         return NGX_ERROR;
  223.     }

  224.     ngx_regex_malloc_init(rc->pool);

  225.     re = pcre_compile((const char *) rc->pattern.data, (int) options,
  226.                       &errstr, &erroff, NULL);

  227.     /* ensure that there is no current pool */
  228.     ngx_regex_malloc_done();

  229.     if (re == NULL) {
  230.         if ((size_t) erroff == rc->pattern.len) {
  231.            rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  232.                               "pcre_compile() failed: %s in \"%V\"",
  233.                                errstr, &rc->pattern)
  234.                          - rc->err.data;

  235.         } else {
  236.            rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  237.                               "pcre_compile() failed: %s in \"%V\" at \"%s\"",
  238.                                errstr, &rc->pattern, rc->pattern.data + erroff)
  239.                          - rc->err.data;
  240.         }

  241.         return NGX_ERROR;
  242.     }

  243.     rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t));
  244.     if (rc->regex == NULL) {
  245.         goto nomem;
  246.     }

  247.     rc->regex->code = re;

  248.     /* do not study at runtime */

  249.     if (ngx_regex_studies != NULL) {
  250.         elt = ngx_list_push(ngx_regex_studies);
  251.         if (elt == NULL) {
  252.             goto nomem;
  253.         }

  254.         elt->regex = rc->regex;
  255.         elt->name = rc->pattern.data;
  256.     }

  257.     n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures);
  258.     if (n < 0) {
  259.         p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d";
  260.         goto failed;
  261.     }

  262.     if (rc->captures == 0) {
  263.         return NGX_OK;
  264.     }

  265.     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMECOUNT, &rc->named_captures);
  266.     if (n < 0) {
  267.         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMECOUNT) failed: %d";
  268.         goto failed;
  269.     }

  270.     if (rc->named_captures == 0) {
  271.         return NGX_OK;
  272.     }

  273.     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMEENTRYSIZE, &rc->name_size);
  274.     if (n < 0) {
  275.         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMEENTRYSIZE) failed: %d";
  276.         goto failed;
  277.     }

  278.     n = pcre_fullinfo(re, NULL, PCRE_INFO_NAMETABLE, &rc->names);
  279.     if (n < 0) {
  280.         p = "pcre_fullinfo(\"%V\", PCRE_INFO_NAMETABLE) failed: %d";
  281.         goto failed;
  282.     }

  283.     return NGX_OK;

  284. failed:

  285.     rc->err.len = ngx_snprintf(rc->err.data, rc->err.len, p, &rc->pattern, n)
  286.                   - rc->err.data;
  287.     return NGX_ERROR;

  288. nomem:

  289.     rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
  290.                                "regex \"%V\" compilation failed: no memory",
  291.                                &rc->pattern)
  292.                   - rc->err.data;
  293.     return NGX_ERROR;
  294. }

  295. #endif


  296. #if (NGX_PCRE2)

  297. ngx_int_t
  298. ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_uint_t size)
  299. {
  300.     size_t      *ov;
  301.     ngx_int_t    rc;
  302.     ngx_uint_t   n, i;

  303.     /*
  304.      * The pcre2_match() function might allocate memory for backtracking
  305.      * frames, typical allocations are from 40k and above.  So the allocator
  306.      * is configured to do direct allocations from heap during matching.
  307.      */

  308.     ngx_regex_malloc_init(NULL);

  309.     if (ngx_regex_match_data == NULL
  310.         || size > ngx_regex_match_data_size)
  311.     {
  312.         /*
  313.          * Allocate a match data if not yet allocated or smaller than
  314.          * needed.
  315.          */

  316.         if (ngx_regex_match_data) {
  317.             pcre2_match_data_free(ngx_regex_match_data);
  318.         }

  319.         ngx_regex_match_data_size = size;
  320.         ngx_regex_match_data = pcre2_match_data_create(size / 3, NULL);

  321.         if (ngx_regex_match_data == NULL) {
  322.             rc = PCRE2_ERROR_NOMEMORY;
  323.             goto failed;
  324.         }
  325.     }

  326.     rc = pcre2_match(re, s->data, s->len, 0, 0, ngx_regex_match_data, NULL);

  327.     if (rc < 0) {
  328.         goto failed;
  329.     }

  330.     n = pcre2_get_ovector_count(ngx_regex_match_data);
  331.     ov = pcre2_get_ovector_pointer(ngx_regex_match_data);

  332.     if (n > size / 3) {
  333.         n = size / 3;
  334.     }

  335.     for (i = 0; i < n; i++) {
  336.         captures[i * 2] = ov[i * 2];
  337.         captures[i * 2 + 1] = ov[i * 2 + 1];
  338.     }

  339. failed:

  340.     ngx_regex_malloc_done();

  341.     return rc;
  342. }

  343. #else

  344. ngx_int_t
  345. ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_uint_t size)
  346. {
  347.     return pcre_exec(re->code, re->extra, (const char *) s->data, s->len,
  348.                      0, 0, captures, size);
  349. }

  350. #endif


  351. ngx_int_t
  352. ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
  353. {
  354.     ngx_int_t         n;
  355.     ngx_uint_t        i;
  356.     ngx_regex_elt_t  *re;

  357.     re = a->elts;

  358.     for (i = 0; i < a->nelts; i++) {

  359.         n = ngx_regex_exec(re[i].regex, s, NULL, 0);

  360.         if (n == NGX_REGEX_NO_MATCHED) {
  361.             continue;
  362.         }

  363.         if (n < 0) {
  364.             ngx_log_error(NGX_LOG_ALERT, log, 0,
  365.                           ngx_regex_exec_n " failed: %i on \"%V\" using \"%s\"",
  366.                           n, s, re[i].name);
  367.             return NGX_ERROR;
  368.         }

  369.         /* match */

  370.         return NGX_OK;
  371.     }

  372.     return NGX_DECLINED;
  373. }


  374. #if (NGX_PCRE2)

  375. static void * ngx_libc_cdecl
  376. ngx_regex_malloc(size_t size, void *data)
  377. {
  378.     if (ngx_regex_pool) {
  379.         return ngx_palloc(ngx_regex_pool, size);
  380.     }

  381.     if (ngx_regex_direct_alloc) {
  382.         return ngx_alloc(size, ngx_cycle->log);
  383.     }

  384.     return NULL;
  385. }


  386. static void ngx_libc_cdecl
  387. ngx_regex_free(void *p, void *data)
  388. {
  389.     if (ngx_regex_direct_alloc) {
  390.         ngx_free(p);
  391.     }

  392.     return;
  393. }

  394. #else

  395. static void * ngx_libc_cdecl
  396. ngx_regex_malloc(size_t size)
  397. {
  398.     if (ngx_regex_pool) {
  399.         return ngx_palloc(ngx_regex_pool, size);
  400.     }

  401.     return NULL;
  402. }


  403. static void ngx_libc_cdecl
  404. ngx_regex_free(void *p)
  405. {
  406.     return;
  407. }

  408. #endif


  409. static void
  410. ngx_regex_cleanup(void *data)
  411. {
  412. #if (NGX_PCRE2 || NGX_HAVE_PCRE_JIT)
  413.     ngx_regex_conf_t *rcf = data;

  414.     ngx_uint_t        i;
  415.     ngx_list_part_t  *part;
  416.     ngx_regex_elt_t  *elts;

  417.     part = &rcf->studies->part;
  418.     elts = part->elts;

  419.     for (i = 0; /* void */ ; i++) {

  420.         if (i >= part->nelts) {
  421.             if (part->next == NULL) {
  422.                 break;
  423.             }

  424.             part = part->next;
  425.             elts = part->elts;
  426.             i = 0;
  427.         }

  428.         /*
  429.          * The PCRE JIT compiler uses mmap for its executable codes, so we
  430.          * have to explicitly call the pcre_free_study() function to free
  431.          * this memory.  In PCRE2, we call the pcre2_code_free() function
  432.          * for the same reason.
  433.          */

  434. #if (NGX_PCRE2)
  435.         pcre2_code_free(elts[i].regex);
  436. #else
  437.         if (elts[i].regex->extra != NULL) {
  438.             pcre_free_study(elts[i].regex->extra);
  439.         }
  440. #endif
  441.     }
  442. #endif

  443.     /*
  444.      * On configuration parsing errors ngx_regex_module_init() will not
  445.      * be called.  Make sure ngx_regex_studies is properly cleared anyway.
  446.      */

  447.     ngx_regex_studies = NULL;

  448. #if (NGX_PCRE2)

  449.     /*
  450.      * Free compile context and match data.  If needed at runtime by
  451.      * the new cycle, these will be re-allocated.
  452.      */

  453.     ngx_regex_malloc_init(NULL);

  454.     if (ngx_regex_compile_context) {
  455.         pcre2_compile_context_free(ngx_regex_compile_context);
  456.         ngx_regex_compile_context = NULL;
  457.     }

  458.     if (ngx_regex_match_data) {
  459.         pcre2_match_data_free(ngx_regex_match_data);
  460.         ngx_regex_match_data = NULL;
  461.         ngx_regex_match_data_size = 0;
  462.     }

  463.     ngx_regex_malloc_done();

  464. #endif
  465. }


  466. static ngx_int_t
  467. ngx_regex_module_init(ngx_cycle_t *cycle)
  468. {
  469.     int                opt;
  470. #if !(NGX_PCRE2)
  471.     const char        *errstr;
  472. #endif
  473.     ngx_uint_t         i;
  474.     ngx_list_part_t   *part;
  475.     ngx_regex_elt_t   *elts;
  476.     ngx_regex_conf_t  *rcf;

  477.     opt = 0;

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

  479. #if (NGX_PCRE2 || NGX_HAVE_PCRE_JIT)

  480.     if (rcf->pcre_jit) {
  481. #if (NGX_PCRE2)
  482.         opt = 1;
  483. #else
  484.         opt = PCRE_STUDY_JIT_COMPILE;
  485. #endif
  486.     }

  487. #endif

  488.     ngx_regex_malloc_init(cycle->pool);

  489.     part = &rcf->studies->part;
  490.     elts = part->elts;

  491.     for (i = 0; /* void */ ; i++) {

  492.         if (i >= part->nelts) {
  493.             if (part->next == NULL) {
  494.                 break;
  495.             }

  496.             part = part->next;
  497.             elts = part->elts;
  498.             i = 0;
  499.         }

  500. #if (NGX_PCRE2)

  501.         if (opt) {
  502.             int  n;

  503.             n = pcre2_jit_compile(elts[i].regex, PCRE2_JIT_COMPLETE);

  504.             if (n != 0) {
  505.                 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
  506.                               "pcre2_jit_compile() failed: %d in \"%s\", "
  507.                               "ignored",
  508.                               n, elts[i].name);
  509.             }
  510.         }

  511. #else

  512.         elts[i].regex->extra = pcre_study(elts[i].regex->code, opt, &errstr);

  513.         if (errstr != NULL) {
  514.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  515.                           "pcre_study() failed: %s in \"%s\"",
  516.                           errstr, elts[i].name);
  517.         }

  518. #if (NGX_HAVE_PCRE_JIT)
  519.         if (opt & PCRE_STUDY_JIT_COMPILE) {
  520.             int jit, n;

  521.             jit = 0;
  522.             n = pcre_fullinfo(elts[i].regex->code, elts[i].regex->extra,
  523.                               PCRE_INFO_JIT, &jit);

  524.             if (n != 0 || jit != 1) {
  525.                 ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
  526.                               "JIT compiler does not support pattern: \"%s\"",
  527.                               elts[i].name);
  528.             }
  529.         }
  530. #endif
  531. #endif
  532.     }

  533.     ngx_regex_malloc_done();

  534.     ngx_regex_studies = NULL;

  535.     return NGX_OK;
  536. }


  537. static void *
  538. ngx_regex_create_conf(ngx_cycle_t *cycle)
  539. {
  540.     ngx_regex_conf_t    *rcf;
  541.     ngx_pool_cleanup_t  *cln;

  542.     rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t));
  543.     if (rcf == NULL) {
  544.         return NULL;
  545.     }

  546.     rcf->pcre_jit = NGX_CONF_UNSET;

  547.     cln = ngx_pool_cleanup_add(cycle->pool, 0);
  548.     if (cln == NULL) {
  549.         return NULL;
  550.     }

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

  555.     cln->handler = ngx_regex_cleanup;
  556.     cln->data = rcf;

  557.     ngx_regex_studies = rcf->studies;

  558.     return rcf;
  559. }


  560. static char *
  561. ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf)
  562. {
  563.     ngx_regex_conf_t *rcf = conf;

  564.     ngx_conf_init_value(rcf->pcre_jit, 0);

  565.     return NGX_CONF_OK;
  566. }


  567. static char *
  568. ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data)
  569. {
  570.     ngx_flag_t  *fp = data;

  571.     if (*fp == 0) {
  572.         return NGX_CONF_OK;
  573.     }

  574. #if (NGX_PCRE2)
  575.     {
  576.     int       r;
  577.     uint32_t  jit;

  578.     jit = 0;
  579.     r = pcre2_config(PCRE2_CONFIG_JIT, &jit);

  580.     if (r != 0 || jit != 1) {
  581.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  582.                            "PCRE2 library does not support JIT");
  583.         *fp = 0;
  584.     }
  585.     }
  586. #elif (NGX_HAVE_PCRE_JIT)
  587.     {
  588.     int  jit, r;

  589.     jit = 0;
  590.     r = pcre_config(PCRE_CONFIG_JIT, &jit);

  591.     if (r != 0 || jit != 1) {
  592.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  593.                            "PCRE library does not support JIT");
  594.         *fp = 0;
  595.     }
  596.     }
  597. #else
  598.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  599.                        "nginx was built without PCRE JIT support");
  600.     *fp = 0;
  601. #endif

  602.     return NGX_CONF_OK;
  603. }