]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-101955: Fix SystemError in possesive quantifier with alternative and group...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 18 Nov 2024 12:03:19 +0000 (13:03 +0100)
committerGitHub <noreply@github.com>
Mon, 18 Nov 2024 12:03:19 +0000 (12:03 +0000)
(cherry picked from commit f9c5573dedcb2f2e9ae152672ce157987cdea612)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/test/test_re.py
Misc/NEWS.d/next/Library/2023-10-26-16-36-22.gh-issue-101955.Ixu3IF.rst [new file with mode: 0644]
Modules/_sre/sre_lib.h

index 130e1e1d01dec5401f8c53938d7126107aac1234..fbab49534183de5ca80c06bd026a85947c4fb5e1 100644 (file)
@@ -2601,6 +2601,12 @@ class ReTests(unittest.TestCase):
         self.assertEqual(re.match("(?>(?:ab?c){1,3})", "aca").span(), (0, 2))
         self.assertEqual(re.match("(?:ab?c){1,3}+", "aca").span(), (0, 2))
 
+    def test_bug_gh101955(self):
+        # Possessive quantifier with nested alternative with capture groups
+        self.assertEqual(re.match('((x)|y|z)*+', 'xyz').groups(), ('z', 'x'))
+        self.assertEqual(re.match('((x)|y|z){3}+', 'xyz').groups(), ('z', 'x'))
+        self.assertEqual(re.match('((x)|y|z){3,}+', 'xyz').groups(), ('z', 'x'))
+
     @unittest.skipIf(multiprocessing is None, 'test requires multiprocessing')
     def test_regression_gh94675(self):
         pattern = re.compile(r'(?<=[({}])(((//[^\n]*)?[\n])([\000-\040])*)*'
diff --git a/Misc/NEWS.d/next/Library/2023-10-26-16-36-22.gh-issue-101955.Ixu3IF.rst b/Misc/NEWS.d/next/Library/2023-10-26-16-36-22.gh-issue-101955.Ixu3IF.rst
new file mode 100644 (file)
index 0000000..8943101
--- /dev/null
@@ -0,0 +1,2 @@
+Fix SystemError when match regular expression pattern containing some
+combination of possessive quantifier, alternative and capture group.
index d82ba7aa3c8b83a533bbcbee37110c18f31b754a..9e9a0ec92683f08848b0eea554249a583fa6650e 100644 (file)
@@ -1269,6 +1269,17 @@ dispatch:
                pointer */
             state->ptr = ptr;
 
+            /* Set state->repeat to non-NULL */
+            ctx->u.rep = repeat_pool_malloc(state);
+            if (!ctx->u.rep) {
+                RETURN_ERROR(SRE_ERROR_MEMORY);
+            }
+            ctx->u.rep->count = -1;
+            ctx->u.rep->pattern = NULL;
+            ctx->u.rep->prev = state->repeat;
+            ctx->u.rep->last_ptr = NULL;
+            state->repeat = ctx->u.rep;
+
             /* Initialize Count to 0 */
             ctx->count = 0;
 
@@ -1283,6 +1294,9 @@ dispatch:
                 }
                 else {
                     state->ptr = ptr;
+                    /* Restore state->repeat */
+                    state->repeat = ctx->u.rep->prev;
+                    repeat_pool_free(state, ctx->u.rep);
                     RETURN_FAILURE;
                 }
             }
@@ -1355,6 +1369,10 @@ dispatch:
                 }
             }
 
+            /* Restore state->repeat */
+            state->repeat = ctx->u.rep->prev;
+            repeat_pool_free(state, ctx->u.rep);
+
             /* Evaluate Tail */
             /* Jump to end of pattern indicated by skip, and then skip
                the SUCCESS op code that follows it. */