https://github.com/python/cpython/commit/af2851ae54e337489d496c0090ac5d6fbb24fa2c commit: af2851ae54e337489d496c0090ac5d6fbb24fa2c branch: 3.14 author: Miss Islington (bot) <[email protected]> committer: gpshead <[email protected]> date: 2026-11-02T11:37:09Z summary:
[3.14] gh-160316: Make `re.Pattern.match()` return `None` when `pos > endpos` (GH-160317) (#161044) Pattern.match(), fullmatch() and the scanner match() ran the engine with the start position past the end position, which could return an empty match or read past the end of the string. ANT-2026-NMTUWIC8 (cherry picked from commit 6b58f9a6a12a3c514a755e5e86dc9b9f36bacb9d) Co-authored-by: Gregory P. Smith <[email protected]> * 3.14-ize the news entry Co-authored-by: Hugo van Kemenade <[email protected]> files: A Misc/NEWS.d/next/Library/2026-10-22-08-17-51.gh-issue-160316.sRe9pQ.rst M Lib/test/test_re.py M Modules/_sre/sre.c diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 021a8a3fe29cd6f..13d48339c932ca7 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2194,6 +2194,25 @@ def test_keyword_parameters(self): pat.scanner(string='abracadabra', pos=3, endpos=10).search().span(), (7, 9)) + def test_pos_greater_than_endpos(self): + # If endpos is less than pos, no match will be found. + for pattern in ['', r'$', r'^$', r'\b$', r'(?:x|$)']: + for string in ['abc\n', b'abc\n', bytearray(b'abc\n')]: + with self.subTest(pattern=pattern, string=string): + if isinstance(string, str): + p = re.compile(pattern, re.MULTILINE) + else: + p = re.compile(pattern.encode(), re.MULTILINE) + for pos, endpos in [(3, 0), (4, 0), (4, 3), (2, 1)]: + self.assertIsNone(p.match(string, pos, endpos)) + self.assertIsNone(p.fullmatch(string, pos, endpos)) + self.assertIsNone(p.search(string, pos, endpos)) + self.assertIsNone( + p.scanner(string, pos, endpos).match()) + self.assertIsNone( + p.scanner(string, pos, endpos).search()) + self.assertEqual(p.findall(string, pos, endpos), []) + def test_bug_20998(self): # Issue #20998: Fullmatch of repeated single character pattern # with ignore case. diff --git a/Misc/NEWS.d/next/Library/2026-10-22-08-17-51.gh-issue-160316.sRe9pQ.rst b/Misc/NEWS.d/next/Library/2026-10-22-08-17-51.gh-issue-160316.sRe9pQ.rst new file mode 100644 index 000000000000000..c7f7865dc715b4b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-10-22-08-17-51.gh-issue-160316.sRe9pQ.rst @@ -0,0 +1,5 @@ +Fix :meth:`re.Pattern.match`, +:meth:`re.Pattern.fullmatch` and the ``match()`` method +of scanner objects returning an empty match, or reading past the end of the +string, when *pos* is greater than *endpos*. They now return ``None``, as +documented. diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index ace6b17ee2d93cf..2e1bbe7b0746c26 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -746,6 +746,10 @@ pattern_dealloc(PyObject *self) LOCAL(Py_ssize_t) sre_match(SRE_STATE* state, SRE_CODE* pattern) { + /* No match if pos > endpos. */ + if (state->ptr > state->end) { + return 0; + } if (state->charsize == 1) return sre_ucs1_match(state, pattern, 1); if (state->charsize == 2) _______________________________________________ Python-checkins mailing list -- [email protected] To unsubscribe send an email to [email protected] https://mail.python.org/mailman3//lists/python-checkins.python.org Member address: [email protected]
