Skip to content

Commit 2304b68

Browse files
[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 6b58f9a) Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
1 parent 6d7c362 commit 2304b68

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

‎Lib/test/test_re.py‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,6 +2224,25 @@ def test_keyword_parameters(self):
22242224
pat.scanner(string='abracadabra', pos=3, endpos=10).search().span(),
22252225
(7, 9))
22262226

2227+
def test_pos_greater_than_endpos(self):
2228+
# If endpos is less than pos, no match will be found.
2229+
for pattern in ['', r'$', r'^$', r'\b$', r'(?:x|$)']:
2230+
for string in ['abc\n', b'abc\n', bytearray(b'abc\n')]:
2231+
with self.subTest(pattern=pattern, string=string):
2232+
if isinstance(string, str):
2233+
p = re.compile(pattern, re.MULTILINE)
2234+
else:
2235+
p = re.compile(pattern.encode(), re.MULTILINE)
2236+
for pos, endpos in [(3, 0), (4, 0), (4, 3), (2, 1)]:
2237+
self.assertIsNone(p.match(string, pos, endpos))
2238+
self.assertIsNone(p.fullmatch(string, pos, endpos))
2239+
self.assertIsNone(p.search(string, pos, endpos))
2240+
self.assertIsNone(
2241+
p.scanner(string, pos, endpos).match())
2242+
self.assertIsNone(
2243+
p.scanner(string, pos, endpos).search())
2244+
self.assertEqual(p.findall(string, pos, endpos), [])
2245+
22272246
def test_bug_20998(self):
22282247
# Issue #20998: Fullmatch of repeated single character pattern
22292248
# with ignore case.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix :meth:`re.Pattern.match`, :meth:`re.Pattern.prefixmatch`,
2+
:meth:`re.Pattern.fullmatch` and the ``match()`` and ``prefixmatch()`` methods
3+
of scanner objects returning an empty match, or reading past the end of the
4+
string, when *pos* is greater than *endpos*. They now return ``None``, as
5+
documented.

‎Modules/_sre/sre.c‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,10 @@ pattern_dealloc(PyObject *self)
747747
LOCAL(Py_ssize_t)
748748
sre_match(SRE_STATE* state, SRE_CODE* pattern)
749749
{
750+
/* No match if pos > endpos. */
751+
if (state->ptr > state->end) {
752+
return 0;
753+
}
750754
if (state->charsize == 1)
751755
return sre_ucs1_match(state, pattern, 1);
752756
if (state->charsize == 2)

0 commit comments

Comments
 (0)