changeset 2581:3c89db25314d

Fixed regexp compilation of patterns with escaped '[' characters. This fixes #934 issue on Github.
author Dmitry Volyntsev <xeioex@nginx.com>
date Mon, 30 Jun 2025 18:30:03 -0700
parents ecf2499ed755
children 93d79230539b
files external/njs_regex.c src/test/njs_unit_test.c
diffstat 2 files changed, 69 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/external/njs_regex.c	Tue Jul 01 23:01:57 2025 -0700
+++ b/external/njs_regex.c	Mon Jun 30 18:30:03 2025 -0700
@@ -114,6 +114,11 @@
 
     for (p = start; p < end; p++) {
         switch (*p) {
+        case '\\':
+            p += 1;
+
+            break;
+
         case '[':
             if (p + 1 < end && p[1] == ']') {
                 p += 1;
@@ -122,6 +127,11 @@
             } else if (p + 2 < end && p[1] == '^' && p[2] == ']') {
                 p += 2;
                 anychars += 1;
+
+            } else {
+                while (p < end && *p != ']') {
+                    p += 1;
+                }
             }
 
             break;
@@ -146,6 +156,15 @@
     for (p = start; p < end; p++) {
 
         switch (*p) {
+        case '\\':
+            *dst++ = *p;
+            if (p + 1 < end) {
+                p += 1;
+                *dst++ = *p;
+            }
+
+            continue;
+
         case '[':
             if (p + 1 < end && p[1] == ']') {
                 p += 1;
@@ -156,6 +175,14 @@
                 p += 2;
                 dst = njs_cpymem(dst, "[\\s\\S]", 6);
                 continue;
+
+            } else {
+                *dst++ = *p;
+                while (p < end && *p != ']') {
+                    *dst++ = *p++;
+                }
+
+                continue;
             }
         }
 
--- a/src/test/njs_unit_test.c	Tue Jul 01 23:01:57 2025 -0700
+++ b/src/test/njs_unit_test.c	Mon Jun 30 18:30:03 2025 -0700
@@ -11969,6 +11969,48 @@
     { njs_str("/[]a/.test('a')"),
       njs_str("false") },
 
+    { njs_str("/[#[]/.test('[')"),
+      njs_str("true") },
+
+    { njs_str("/[\\s[]/.test('[')"),
+      njs_str("true") },
+
+    { njs_str("/[#[^]/.test('[')"),
+      njs_str("true") },
+
+    { njs_str("/[#\\[]/.test('[')"),
+      njs_str("true") },
+
+    { njs_str("/[\\[^]/.test('[')"),
+      njs_str("true") },
+
+    { njs_str("/[^]abc]/.test('#abc]')"),
+      njs_str("true") },
+
+    { njs_str("/[[^]abc]/.test('[abc]')"),
+      njs_str("true") },
+
+    { njs_str("/[[^]abc]/.test('^abc]')"),
+      njs_str("true") },
+
+    { njs_str("/[]/.test('[]')"),
+      njs_str("false") },
+
+    { njs_str("/[[]/.test('[')"),
+      njs_str("true") },
+
+    { njs_str("/\\[]/.test('[]')"),
+      njs_str("true") },
+
+    { njs_str("/[]abc]/.test('abc]')"),
+      njs_str("false") },
+
+    { njs_str("/abc]/.test('abc]')"),
+      njs_str("true") },
+
+    { njs_str("/\\\\\\[]/.test('\\\\[]')"),
+      njs_str("true") },
+
 #ifdef NJS_HAVE_PCRE2
     { njs_str("/[]*a/.test('a')"),
       njs_str("true") },