Skip to content

Commit 3effeec

Browse files
gpsheadmiss-islington
authored andcommitted
gh-160316: Make re.Pattern.match() return None when pos > endpos (GH-160317)
gh-160316: Make re.Pattern.match() return None when pos > endpos 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 7440c35 commit 3effeec

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)