https://github.com/python/cpython/commit/2304b684eef82358bef59c4249c47310a4409265 commit: 2304b684eef82358bef59c4249c47310a4409265 branch: 3.15 author: Miss Islington (bot) <[email protected]> committer: gpshead <[email protected]> date: 2026-11-01T23:21:33Z summary:
[3.15] gh-160316: Make `re.Pattern.match()` return `None` when `pos > endpos` (GH-160317) (#161043) Pattern.match(), prefixmatch(), 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]> 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 062d812c822ab5f..00a4f325bc322c7 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2224,6 +2224,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..0e52137bde01ed5 --- /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.prefixmatch`, +:meth:`re.Pattern.fullmatch` and the ``match()`` and ``prefixmatch()`` methods +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 d372d6a03ab4ee4..1eee31b3ee48235 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -747,6 +747,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]
