From f9c5573dedcb2f2e9ae152672ce157987cdea612 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Mon, 18 Nov 2024 13:43:44 +0200 Subject: [PATCH] gh-101955: Fix SystemError in possesive quantifier with alternative and group (GH-111362) Co-authored-by: --- Lib/test/test_re.py | 6 ++++++ ...3-10-26-16-36-22.gh-issue-101955.Ixu3IF.rst | 2 ++ Modules/_sre/sre_lib.h | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2023-10-26-16-36-22.gh-issue-101955.Ixu3IF.rst diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 1612fc7663e..0d3599be87f 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2640,6 +2640,12 @@ def test_bug_gh100061(self): 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 index 00000000000..89431010f78 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-10-26-16-36-22.gh-issue-101955.Ixu3IF.rst @@ -0,0 +1,2 @@ +Fix SystemError when match regular expression pattern containing some +combination of possessive quantifier, alternative and capture group. diff --git a/Modules/_sre/sre_lib.h b/Modules/_sre/sre_lib.h index 0c93f512110..af4bfc56083 100644 --- a/Modules/_sre/sre_lib.h +++ b/Modules/_sre/sre_lib.h @@ -1306,6 +1306,17 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) 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; @@ -1320,6 +1331,9 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) } else { state->ptr = ptr; + /* Restore state->repeat */ + state->repeat = ctx->u.rep->prev; + repeat_pool_free(state, ctx->u.rep); RETURN_FAILURE; } } @@ -1392,6 +1406,10 @@ SRE(match)(SRE_STATE* state, const SRE_CODE* pattern, int toplevel) } } + /* 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. */