Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian....@packages.debian.org
Usertags: pu

Hi,

I've backported the upstream security fixes for CVE-2022-1586 and
CVE-2022-1587 to bullseye, and would like them to go in the next
stable update, please. I consulted the security team, and we think
this is the right approach for this issue, as the bugs are regarding
handling of regexes fed to the library rather than handling of
untrusted input (which would warrant a DSA).

The security team opened #1011954 for this issue.

I have built this package in a bullseye chroot and run the upstream
test suite in that chroot.

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in stable
  [X] the issue is verified as fixed in unstable

I'll do a source upload shortly.

Thanks,

Matthew

-- System Information:
Debian Release: 9.13
  APT prefers oldoldstable
  APT policy: (500, 'oldoldstable')
Architecture: amd64 (x86_64)

Kernel: Linux 4.9.0-19-amd64 (SMP w/8 CPU cores)
Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_GB:en (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: sysvinit (via /sbin/init)
diff -u pcre2-10.36/debian/changelog pcre2-10.36/debian/changelog
--- pcre2-10.36/debian/changelog
+++ pcre2-10.36/debian/changelog
@@ -1,3 +1,10 @@
+pcre2 (10.36-2+deb11u1) unstable; urgency=medium
+
+  * Backport upstream fixes for CVE-2022-1586 CVE-2022-1587
+    (Closes: #1011954)
+
+ -- Matthew Vernon <matt...@debian.org>  Sun, 21 Aug 2022 12:15:50 +0100
+
 pcre2 (10.36-2) unstable; urgency=medium
 
   * Upload to unstable
only in patch2:
unchanged:
--- pcre2-10.36.orig/ChangeLog
+++ pcre2-10.36/ChangeLog
@@ -1,8 +1,8 @@
 Change Log for PCRE2
 --------------------
 
-Version 10.36-RC1 04-December-2020
-----------------------------------
+Version 10.36 04-December-2020
+------------------------------
 
 1. Add CET_CFLAGS so that when Intel CET is enabled, pass -mshstk to
 compiler. This fixes https://bugs.exim.org/show_bug.cgi?id=2578. Patch for
only in patch2:
unchanged:
--- pcre2-10.36.orig/src/pcre2_jit_compile.c
+++ pcre2-10.36/src/pcre2_jit_compile.c
@@ -413,6 +413,9 @@
   /* Locals used by fast fail optimization. */
   sljit_s32 early_fail_start_ptr;
   sljit_s32 early_fail_end_ptr;
+  /* Variables used by recursive call generator. */
+  sljit_s32 recurse_bitset_size;
+  uint8_t *recurse_bitset;
 
   /* Flipped and lower case tables. */
   const sljit_u8 *fcc;
@@ -2316,19 +2319,39 @@
 
 #undef RECURSE_TMP_REG_COUNT
 
+static BOOL recurse_check_bit(compiler_common *common, sljit_sw bit_index)
+{
+uint8_t *byte;
+uint8_t mask;
+
+SLJIT_ASSERT((bit_index & (sizeof(sljit_sw) - 1)) == 0);
+
+bit_index >>= SLJIT_WORD_SHIFT;
+
+mask = 1 << (bit_index & 0x7);
+byte = common->recurse_bitset + (bit_index >> 3);
+
+if (*byte & mask)
+  return FALSE;
+
+*byte |= mask;
+return TRUE;
+}
+
 static int get_recurse_data_length(compiler_common *common, PCRE2_SPTR cc, 
PCRE2_SPTR ccend,
   BOOL *needs_control_head, BOOL *has_quit, BOOL *has_accept)
 {
 int length = 1;
-int size;
+int size, offset;
 PCRE2_SPTR alternative;
 BOOL quit_found = FALSE;
 BOOL accept_found = FALSE;
 BOOL setsom_found = FALSE;
 BOOL setmark_found = FALSE;
-BOOL capture_last_found = FALSE;
 BOOL control_head_found = FALSE;
 
+memset(common->recurse_bitset, 0, common->recurse_bitset_size);
+
 #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
 SLJIT_ASSERT(common->control_head_ptr != 0);
 control_head_found = TRUE;
@@ -2351,15 +2374,17 @@
       setsom_found = TRUE;
     if (common->mark_ptr != 0)
       setmark_found = TRUE;
-    if (common->capture_last_ptr != 0)
-      capture_last_found = TRUE;
+    if (common->capture_last_ptr != 0 && recurse_check_bit(common, 
common->capture_last_ptr))
+      length++;
     cc += 1 + LINK_SIZE;
     break;
 
     case OP_KET:
-    if (PRIVATE_DATA(cc) != 0)
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0)
       {
-      length++;
+      if (recurse_check_bit(common, offset))
+        length++;
       SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
       cc += PRIVATE_DATA(cc + 1);
       }
@@ -2378,39 +2403,55 @@
     case OP_SBRA:
     case OP_SBRAPOS:
     case OP_SCOND:
-    length++;
     SLJIT_ASSERT(PRIVATE_DATA(cc) != 0);
+    if (recurse_check_bit(common, PRIVATE_DATA(cc)))
+      length++;
     cc += 1 + LINK_SIZE;
     break;
 
     case OP_CBRA:
     case OP_SCBRA:
-    length += 2;
-    if (common->capture_last_ptr != 0)
-      capture_last_found = TRUE;
-    if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+    offset = GET2(cc, 1 + LINK_SIZE);
+    if (recurse_check_bit(common, OVECTOR(offset << 1)))
+      {
+      SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));
+      length += 2;
+      }
+    if (common->optimized_cbracket[offset] == 0 && recurse_check_bit(common, 
OVECTOR_PRIV(offset)))
+      length++;
+    if (common->capture_last_ptr != 0 && recurse_check_bit(common, 
common->capture_last_ptr))
       length++;
     cc += 1 + LINK_SIZE + IMM2_SIZE;
     break;
 
     case OP_CBRAPOS:
     case OP_SCBRAPOS:
-    length += 2 + 2;
-    if (common->capture_last_ptr != 0)
-      capture_last_found = TRUE;
+    offset = GET2(cc, 1 + LINK_SIZE);
+    if (recurse_check_bit(common, OVECTOR(offset << 1)))
+      {
+      SLJIT_ASSERT(recurse_check_bit(common, OVECTOR((offset << 1) + 1)));
+      length += 2;
+      }
+    if (recurse_check_bit(common, OVECTOR_PRIV(offset)))
+      length++;
+    if (recurse_check_bit(common, PRIVATE_DATA(cc)))
+      length++;
+    if (common->capture_last_ptr != 0 && recurse_check_bit(common, 
common->capture_last_ptr))
+      length++;
     cc += 1 + LINK_SIZE + IMM2_SIZE;
     break;
 
     case OP_COND:
     /* Might be a hidden SCOND. */
     alternative = cc + GET(cc, 1);
-    if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
+    if ((*alternative == OP_KETRMAX || *alternative == OP_KETRMIN) && 
recurse_check_bit(common, PRIVATE_DATA(cc)))
       length++;
     cc += 1 + LINK_SIZE;
     break;
 
     CASE_ITERATOR_PRIVATE_DATA_1
-    if (PRIVATE_DATA(cc) != 0)
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0 && recurse_check_bit(common, offset))
       length++;
     cc += 2;
 #ifdef SUPPORT_UNICODE
@@ -2419,8 +2460,12 @@
     break;
 
     CASE_ITERATOR_PRIVATE_DATA_2A
-    if (PRIVATE_DATA(cc) != 0)
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0 && recurse_check_bit(common, offset))
+      {
+      SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
       length += 2;
+      }
     cc += 2;
 #ifdef SUPPORT_UNICODE
     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
@@ -2428,8 +2473,12 @@
     break;
 
     CASE_ITERATOR_PRIVATE_DATA_2B
-    if (PRIVATE_DATA(cc) != 0)
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0 && recurse_check_bit(common, offset))
+      {
+      SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
       length += 2;
+      }
     cc += 2 + IMM2_SIZE;
 #ifdef SUPPORT_UNICODE
     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
@@ -2437,20 +2486,29 @@
     break;
 
     CASE_ITERATOR_TYPE_PRIVATE_DATA_1
-    if (PRIVATE_DATA(cc) != 0)
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0 && recurse_check_bit(common, offset))
       length++;
     cc += 1;
     break;
 
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
-    if (PRIVATE_DATA(cc) != 0)
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0 && recurse_check_bit(common, offset))
+      {
+      SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
       length += 2;
+      }
     cc += 1;
     break;
 
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
-    if (PRIVATE_DATA(cc) != 0)
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0 && recurse_check_bit(common, offset))
+      {
+      SLJIT_ASSERT(recurse_check_bit(common, offset + sizeof(sljit_sw)));
       length += 2;
+      }
     cc += 1 + IMM2_SIZE;
     break;
 
@@ -2462,7 +2520,9 @@
 #else
     size = 1 + 32 / (int)sizeof(PCRE2_UCHAR);
 #endif
-    if (PRIVATE_DATA(cc) != 0)
+
+    offset = PRIVATE_DATA(cc);
+    if (offset != 0 && recurse_check_bit(common, offset))
       length += get_class_iterator_size(cc + size);
     cc += size;
     break;
@@ -2497,8 +2557,7 @@
     case OP_THEN:
     SLJIT_ASSERT(common->control_head_ptr != 0);
     quit_found = TRUE;
-    if (!control_head_found)
-      control_head_found = TRUE;
+    control_head_found = TRUE;
     cc++;
     break;
 
@@ -2518,8 +2577,6 @@
 
 if (control_head_found)
   length++;
-if (capture_last_found)
-  length++;
 if (quit_found)
   {
   if (setsom_found)
@@ -2552,14 +2609,12 @@
 sljit_sw kept_shared_srcw[2];
 int private_count, shared_count, kept_shared_count;
 int from_sp, base_reg, offset, i;
-BOOL setsom_found = FALSE;
-BOOL setmark_found = FALSE;
-BOOL capture_last_found = FALSE;
-BOOL control_head_found = FALSE;
+
+memset(common->recurse_bitset, 0, common->recurse_bitset_size);
 
 #if defined DEBUG_FORCE_CONTROL_HEAD && DEBUG_FORCE_CONTROL_HEAD
 SLJIT_ASSERT(common->control_head_ptr != 0);
-control_head_found = TRUE;
+recurse_check_bit(common, common->control_head_ptr);
 #endif
 
 switch (type)
@@ -2647,11 +2702,10 @@
     {
     case OP_SET_SOM:
     SLJIT_ASSERT(common->has_set_som);
-    if (has_quit && !setsom_found)
+    if (has_quit && recurse_check_bit(common, OVECTOR(0)))
       {
       kept_shared_srcw[0] = OVECTOR(0);
       kept_shared_count = 1;
-      setsom_found = TRUE;
       }
     cc += 1;
     break;
@@ -2659,33 +2713,31 @@
     case OP_RECURSE:
     if (has_quit)
       {
-      if (common->has_set_som && !setsom_found)
+      if (common->has_set_som && recurse_check_bit(common, OVECTOR(0)))
         {
         kept_shared_srcw[0] = OVECTOR(0);
         kept_shared_count = 1;
-        setsom_found = TRUE;
         }
-      if (common->mark_ptr != 0 && !setmark_found)
+      if (common->mark_ptr != 0 && recurse_check_bit(common, common->mark_ptr))
         {
         kept_shared_srcw[kept_shared_count] = common->mark_ptr;
         kept_shared_count++;
-        setmark_found = TRUE;
         }
       }
-    if (common->capture_last_ptr != 0 && !capture_last_found)
+    if (common->capture_last_ptr != 0 && recurse_check_bit(common, 
common->capture_last_ptr))
       {
       shared_srcw[0] = common->capture_last_ptr;
       shared_count = 1;
-      capture_last_found = TRUE;
       }
     cc += 1 + LINK_SIZE;
     break;
 
     case OP_KET:
-    if (PRIVATE_DATA(cc) != 0)
+    private_srcw[0] = PRIVATE_DATA(cc);
+    if (private_srcw[0] != 0)
       {
-      private_count = 1;
-      private_srcw[0] = PRIVATE_DATA(cc);
+      if (recurse_check_bit(common, private_srcw[0]))
+        private_count = 1;
       SLJIT_ASSERT(PRIVATE_DATA(cc + 1) != 0);
       cc += PRIVATE_DATA(cc + 1);
       }
@@ -2704,50 +2756,66 @@
     case OP_SBRA:
     case OP_SBRAPOS:
     case OP_SCOND:
-    private_count = 1;
     private_srcw[0] = PRIVATE_DATA(cc);
+    if (recurse_check_bit(common, private_srcw[0]))
+      private_count = 1;
     cc += 1 + LINK_SIZE;
     break;
 
     case OP_CBRA:
     case OP_SCBRA:
-    offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
-    shared_srcw[0] = OVECTOR(offset);
-    shared_srcw[1] = OVECTOR(offset + 1);
-    shared_count = 2;
+    offset = GET2(cc, 1 + LINK_SIZE);
+    shared_srcw[0] = OVECTOR(offset << 1);
+    if (recurse_check_bit(common, shared_srcw[0]))
+      {
+      shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);
+      SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));
+      shared_count = 2;
+      }
 
-    if (common->capture_last_ptr != 0 && !capture_last_found)
+    if (common->capture_last_ptr != 0 && recurse_check_bit(common, 
common->capture_last_ptr))
       {
-      shared_srcw[2] = common->capture_last_ptr;
-      shared_count = 3;
-      capture_last_found = TRUE;
+      shared_srcw[shared_count] = common->capture_last_ptr;
+      shared_count++;
       }
 
-    if (common->optimized_cbracket[GET2(cc, 1 + LINK_SIZE)] == 0)
+    if (common->optimized_cbracket[offset] == 0)
       {
-      private_count = 1;
-      private_srcw[0] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+      private_srcw[0] = OVECTOR_PRIV(offset);
+      if (recurse_check_bit(common, private_srcw[0]))
+        private_count = 1;
       }
+
     cc += 1 + LINK_SIZE + IMM2_SIZE;
     break;
 
     case OP_CBRAPOS:
     case OP_SCBRAPOS:
-    offset = (GET2(cc, 1 + LINK_SIZE)) << 1;
-    shared_srcw[0] = OVECTOR(offset);
-    shared_srcw[1] = OVECTOR(offset + 1);
-    shared_count = 2;
+    offset = GET2(cc, 1 + LINK_SIZE);
+    shared_srcw[0] = OVECTOR(offset << 1);
+    if (recurse_check_bit(common, shared_srcw[0]))
+      {
+      shared_srcw[1] = shared_srcw[0] + sizeof(sljit_sw);
+      SLJIT_ASSERT(recurse_check_bit(common, shared_srcw[1]));
+      shared_count = 2;
+      }
 
-    if (common->capture_last_ptr != 0 && !capture_last_found)
+    if (common->capture_last_ptr != 0 && recurse_check_bit(common, 
common->capture_last_ptr))
       {
-      shared_srcw[2] = common->capture_last_ptr;
-      shared_count = 3;
-      capture_last_found = TRUE;
+      shared_srcw[shared_count] = common->capture_last_ptr;
+      shared_count++;
       }
 
-    private_count = 2;
     private_srcw[0] = PRIVATE_DATA(cc);
-    private_srcw[1] = OVECTOR_PRIV(GET2(cc, 1 + LINK_SIZE));
+    if (recurse_check_bit(common, private_srcw[0]))
+      private_count = 1;
+
+    offset = OVECTOR_PRIV(offset);
+    if (recurse_check_bit(common, offset))
+      {
+      private_srcw[private_count] = offset;
+      private_count++;
+      }
     cc += 1 + LINK_SIZE + IMM2_SIZE;
     break;
 
@@ -2756,18 +2824,17 @@
     alternative = cc + GET(cc, 1);
     if (*alternative == OP_KETRMAX || *alternative == OP_KETRMIN)
       {
-      private_count = 1;
       private_srcw[0] = PRIVATE_DATA(cc);
+      if (recurse_check_bit(common, private_srcw[0]))
+        private_count = 1;
       }
     cc += 1 + LINK_SIZE;
     break;
 
     CASE_ITERATOR_PRIVATE_DATA_1
-    if (PRIVATE_DATA(cc))
-      {
+    private_srcw[0] = PRIVATE_DATA(cc);
+    if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
       private_count = 1;
-      private_srcw[0] = PRIVATE_DATA(cc);
-      }
     cc += 2;
 #ifdef SUPPORT_UNICODE
     if (common->utf && HAS_EXTRALEN(cc[-1])) cc += GET_EXTRALEN(cc[-1]);
@@ -2775,11 +2842,12 @@
     break;
 
     CASE_ITERATOR_PRIVATE_DATA_2A
-    if (PRIVATE_DATA(cc))
+    private_srcw[0] = PRIVATE_DATA(cc);
+    if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
       {
       private_count = 2;
-      private_srcw[0] = PRIVATE_DATA(cc);
-      private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+      private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+      SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
       }
     cc += 2;
 #ifdef SUPPORT_UNICODE
@@ -2788,11 +2856,12 @@
     break;
 
     CASE_ITERATOR_PRIVATE_DATA_2B
-    if (PRIVATE_DATA(cc))
+    private_srcw[0] = PRIVATE_DATA(cc);
+    if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
       {
       private_count = 2;
-      private_srcw[0] = PRIVATE_DATA(cc);
-      private_srcw[1] = PRIVATE_DATA(cc) + sizeof(sljit_sw);
+      private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+      SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
       }
     cc += 2 + IMM2_SIZE;
 #ifdef SUPPORT_UNICODE
@@ -2801,30 +2870,30 @@
     break;
 
     CASE_ITERATOR_TYPE_PRIVATE_DATA_1
-    if (PRIVATE_DATA(cc))
-      {
+    private_srcw[0] = PRIVATE_DATA(cc);
+    if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
       private_count = 1;
-      private_srcw[0] = PRIVATE_DATA(cc);
-      }
     cc += 1;
     break;
 
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2A
-    if (PRIVATE_DATA(cc))
+    private_srcw[0] = PRIVATE_DATA(cc);
+    if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
       {
       private_count = 2;
-      private_srcw[0] = PRIVATE_DATA(cc);
       private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+      SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
       }
     cc += 1;
     break;
 
     CASE_ITERATOR_TYPE_PRIVATE_DATA_2B
-    if (PRIVATE_DATA(cc))
+    private_srcw[0] = PRIVATE_DATA(cc);
+    if (private_srcw[0] != 0 && recurse_check_bit(common, private_srcw[0]))
       {
       private_count = 2;
-      private_srcw[0] = PRIVATE_DATA(cc);
       private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+      SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
       }
     cc += 1 + IMM2_SIZE;
     break;
@@ -2841,14 +2910,17 @@
       switch(get_class_iterator_size(cc + i))
         {
         case 1:
-        private_count = 1;
         private_srcw[0] = PRIVATE_DATA(cc);
         break;
 
         case 2:
-        private_count = 2;
         private_srcw[0] = PRIVATE_DATA(cc);
-        private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+        if (recurse_check_bit(common, private_srcw[0]))
+          {
+          private_count = 2;
+          private_srcw[1] = private_srcw[0] + sizeof(sljit_sw);
+          SLJIT_ASSERT(recurse_check_bit(common, private_srcw[1]));
+          }
         break;
 
         default:
@@ -2863,28 +2935,25 @@
     case OP_PRUNE_ARG:
     case OP_THEN_ARG:
     SLJIT_ASSERT(common->mark_ptr != 0);
-    if (has_quit && !setmark_found)
+    if (has_quit && recurse_check_bit(common, common->mark_ptr))
       {
       kept_shared_srcw[0] = common->mark_ptr;
       kept_shared_count = 1;
-      setmark_found = TRUE;
       }
-    if (common->control_head_ptr != 0 && !control_head_found)
+    if (common->control_head_ptr != 0 && recurse_check_bit(common, 
common->control_head_ptr))
       {
       private_srcw[0] = common->control_head_ptr;
       private_count = 1;
-      control_head_found = TRUE;
       }
     cc += 1 + 2 + cc[1];
     break;
 
     case OP_THEN:
     SLJIT_ASSERT(common->control_head_ptr != 0);
-    if (!control_head_found)
+    if (recurse_check_bit(common, common->control_head_ptr))
       {
       private_srcw[0] = common->control_head_ptr;
       private_count = 1;
-      control_head_found = TRUE;
       }
     cc++;
     break;
@@ -2892,7 +2961,7 @@
     default:
     cc = next_opcode(common, cc);
     SLJIT_ASSERT(cc != NULL);
-    break;
+    continue;
     }
 
   if (type != recurse_copy_shared_to_global && type != 
recurse_copy_kept_shared_to_global)
@@ -7473,7 +7542,7 @@
     {
     SLJIT_ASSERT(*cc == XCL_PROP || *cc == XCL_NOTPROP);
     cc++;
-    if (*cc == PT_CLIST)
+    if (*cc == PT_CLIST && cc[-1] == XCL_PROP)
       {
       other_cases = PRIV(ucd_caseless_sets) + cc[1];
       while (*other_cases != NOTACHAR)
@@ -13652,7 +13721,7 @@
 common->cbra_ptr = OVECTOR_START + (re->top_bracket + 1) * 2 * 
sizeof(sljit_sw);
 
 total_length = ccend - common->start;
-common->private_data_ptrs = (sljit_s32 *)SLJIT_MALLOC(total_length * 
(sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);
+common->private_data_ptrs = (sljit_s32*)SLJIT_MALLOC(total_length * 
(sizeof(sljit_s32) + (common->has_then ? 1 : 0)), allocator_data);
 if (!common->private_data_ptrs)
   {
   SLJIT_FREE(common->optimized_cbracket, allocator_data);
@@ -13690,7 +13759,8 @@
   }
 common->compiler = compiler;
 
-/* Main pcre_jit_exec entry. */
+/* Main pcre2_jit_exec entry. */
+SLJIT_ASSERT((private_data_size & (sizeof(sljit_sw) - 1)) == 0);
 sljit_emit_enter(compiler, 0, SLJIT_ARG1(SW), 5, 5, 0, 0, private_data_size);
 
 /* Register init. */
@@ -13913,20 +13983,40 @@
 common->currententry = common->entries;
 common->local_quit_available = TRUE;
 quit_label = common->quit_label;
-while (common->currententry != NULL)
+if (common->currententry != NULL)
   {
-  /* Might add new entries. */
-  compile_recurse(common);
-  if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+  /* A free bit for each private data. */
+  common->recurse_bitset_size = ((private_data_size / (int)sizeof(sljit_sw)) + 
7) >> 3;
+  SLJIT_ASSERT(common->recurse_bitset_size > 0);
+  common->recurse_bitset = 
(sljit_u8*)SLJIT_MALLOC(common->recurse_bitset_size, allocator_data);;
+
+  if (common->recurse_bitset != NULL)
+    {
+    do
+      {
+      /* Might add new entries. */
+      compile_recurse(common);
+      if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
+        break;
+      flush_stubs(common);
+      common->currententry = common->currententry->next;
+      }
+    while (common->currententry != NULL);
+
+    SLJIT_FREE(common->recurse_bitset, allocator_data);
+    }
+
+  if (common->currententry != NULL)
     {
+    /* The common->recurse_bitset has been freed. */
+    SLJIT_ASSERT(sljit_get_compiler_error(compiler) || common->recurse_bitset 
== NULL);
+
     sljit_free_compiler(compiler);
     SLJIT_FREE(common->optimized_cbracket, allocator_data);
     SLJIT_FREE(common->private_data_ptrs, allocator_data);
     PRIV(jit_free_rodata)(common->read_only_data_head, allocator_data);
     return PCRE2_ERROR_NOMEMORY;
     }
-  flush_stubs(common);
-  common->currententry = common->currententry->next;
   }
 common->local_quit_available = FALSE;
 common->quit_label = quit_label;
only in patch2:
unchanged:
--- pcre2-10.36.orig/src/pcre2_jit_test.c
+++ pcre2-10.36/src/pcre2_jit_test.c
@@ -410,6 +410,9 @@
        { MUP, A, 0, 0 | F_PROPERTY, 
"[\\P{L&}]{2}[^\xc2\x85-\xc2\x89\\p{Ll}\\p{Lu}]{2}", 
"\xc3\xa9\xe6\x92\xad.a\xe6\x92\xad|\xc2\x8a#" },
        { PCRE2_UCP, 0, 0, 0 | F_PROPERTY, "[a-b\\s]{2,5}[^a]", "AB  baaa" },
        { MUP, 0, 0, 0 | F_NOMATCH, "[^\\p{Hangul}\\p{Z}]", " " },
+       { MUP, 0, 0, 0, "[\\p{Lu}\\P{Latin}]+", "c\xEA\xA4\xAE,A,b" },
+       { MUP, 0, 0, 0, "[\\x{a92e}\\p{Lu}\\P{Latin}]+", "c\xEA\xA4\xAE,A,b" },
+       { CMUP, 0, 0, 0, "[^S]\\B", "\xe2\x80\x8a" },
 
        /* Possible empty brackets. */
        { MU, A, 0, 0, "(?:|ab||bc|a)+d", "abcxabcabd" },
@@ -745,6 +748,7 @@
        { MU, A, 0, 0, "((?(R)a|(?1)){1,3}?)M", "aaaM" },
        { MU, A, 0, 0, "((.)(?:.|\\2(?1))){0}#(?1)#", "#aabbccdde# 
#aabbccddee#" },
        { MU, A, 0, 0, "((.)(?:\\2|\\2{4}b)){0}#(?:(?1))+#", "#aaaab# #aaaaab#" 
},
+       { MU, A, 0, 0 | F_NOMATCH, "(?1)$((.|\\2xx){1,2})", "abc" },
 
        /* 16 bit specific tests. */
        { CM, A, 0, 0 | F_FORCECONV, "\xc3\xa1", "\xc3\x81\xc3\xa1" },

Reply via email to