changeset 7982:fbbb5ce52995

PCRE2 and PCRE binary compatibility. With this change, dynamic modules using nginx regex interface can be used regardless of the variant of the PCRE library nginx was compiled with. If a module is compiled with different PCRE library variant, in case of ngx_regex_exec() errors it will report wrong function name in error messages. This is believed to be tolerable, given that fixing this will require interface changes.
author Maxim Dounin <mdounin@mdounin.ru>
date Sat, 25 Dec 2021 01:07:16 +0300
parents 0b5f12d5c531
children d07456044b61
files src/core/ngx_regex.c src/core/ngx_regex.h
diffstat 2 files changed, 48 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -118,6 +118,7 @@ ngx_regex_compile(ngx_regex_compile_t *r
     char                   *p;
     u_char                  errstr[128];
     size_t                  erroff;
+    uint32_t                options;
     pcre2_code             *re;
     ngx_regex_elt_t        *elt;
     pcre2_general_context  *gctx;
@@ -152,11 +153,24 @@ ngx_regex_compile(ngx_regex_compile_t *r
         ngx_regex_malloc_done();
     }
 
+    options = 0;
+
+    if (rc->options & NGX_REGEX_CASELESS) {
+        options |= PCRE2_CASELESS;
+    }
+
+    if (rc->options & ~NGX_REGEX_CASELESS) {
+        rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                            "regex \"%V\" compilation failed: invalid options",
+                            &rc->pattern)
+                      - rc->err.data;
+        return NGX_ERROR;
+    }
+
     ngx_regex_malloc_init(rc->pool);
 
-    re = pcre2_compile(rc->pattern.data, rc->pattern.len,
-                       (uint32_t) rc->options, &errcode, &erroff,
-                       ngx_regex_compile_context);
+    re = pcre2_compile(rc->pattern.data, rc->pattern.len, options,
+                       &errcode, &erroff, ngx_regex_compile_context);
 
     /* ensure that there is no current pool */
     ngx_regex_malloc_done();
@@ -252,11 +266,26 @@ ngx_regex_compile(ngx_regex_compile_t *r
     char             *p;
     pcre             *re;
     const char       *errstr;
+    ngx_uint_t        options;
     ngx_regex_elt_t  *elt;
 
+    options = 0;
+
+    if (rc->options & NGX_REGEX_CASELESS) {
+        options |= PCRE_CASELESS;
+    }
+
+    if (rc->options & ~NGX_REGEX_CASELESS) {
+        rc->err.len = ngx_snprintf(rc->err.data, rc->err.len,
+                            "regex \"%V\" compilation failed: invalid options",
+                            &rc->pattern)
+                      - rc->err.data;
+        return NGX_ERROR;
+    }
+
     ngx_regex_malloc_init(rc->pool);
 
-    re = pcre_compile((const char *) rc->pattern.data, (int) rc->options,
+    re = pcre_compile((const char *) rc->pattern.data, (int) options,
                       &errstr, &erroff, NULL);
 
     /* ensure that there is no current pool */
@@ -413,6 +442,15 @@ failed:
     return rc;
 }
 
+#else
+
+ngx_int_t
+ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_uint_t size)
+{
+    return pcre_exec(re->code, re->extra, (const char *) s->data, s->len,
+                     0, 0, captures, size);
+}
+
 #endif
 
 
--- a/src/core/ngx_regex.h
+++ b/src/core/ngx_regex.h
@@ -19,7 +19,6 @@
 #include <pcre2.h>
 
 #define NGX_REGEX_NO_MATCHED   PCRE2_ERROR_NOMATCH   /* -1 */
-#define NGX_REGEX_CASELESS     PCRE2_CASELESS
 
 typedef pcre2_code  ngx_regex_t;
 
@@ -28,7 +27,6 @@ typedef pcre2_code  ngx_regex_t;
 #include <pcre.h>
 
 #define NGX_REGEX_NO_MATCHED   PCRE_ERROR_NOMATCH    /* -1 */
-#define NGX_REGEX_CASELESS     PCRE_CASELESS
 
 typedef struct {
     pcre        *code;
@@ -38,10 +36,13 @@ typedef struct {
 #endif
 
 
+#define NGX_REGEX_CASELESS     0x00000001
+
+
 typedef struct {
     ngx_str_t     pattern;
     ngx_pool_t   *pool;
-    ngx_int_t     options;
+    ngx_uint_t    options;
 
     ngx_regex_t  *regex;
     int           captures;
@@ -61,19 +62,13 @@ typedef struct {
 void ngx_regex_init(void);
 ngx_int_t ngx_regex_compile(ngx_regex_compile_t *rc);
 
-#if (NGX_PCRE2)
-
 ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures,
     ngx_uint_t size);
+
+#if (NGX_PCRE2)
 #define ngx_regex_exec_n       "pcre2_match()"
-
 #else
-
-#define ngx_regex_exec(re, s, captures, size)                                \
-    pcre_exec(re->code, re->extra, (const char *) (s)->data, (s)->len, 0, 0, \
-              captures, size)
 #define ngx_regex_exec_n       "pcre_exec()"
-
 #endif
 
 ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log);