Skip to content

Commit 5c80513

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 c67d3db commit 5c80513

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
@@ -2194,6 +2194,25 @@ def test_keyword_parameters(self):
21942194
pat.scanner(string='abracadabra', pos=3, endpos=10).search().span(),
21952195
(7, 9))
21962196

2197+
def test_pos_greater_than_endpos(self):
2198+
# If endpos is less than pos, no match will be found.
2199+
for pattern in ['', r'$', r'^$', r'\b$', r'(?:x|$)']:
2200+
for string in ['abc\n', b'abc\n', bytearray(b'abc\n')]:
2201+
with self.subTest(pattern=pattern, string=string):
2202+
if isinstance(string, str):
2203+
p = re.compile(pattern, re.MULTILINE)
2204+
else:
2205+
p = re.compile(pattern.encode(), re.MULTILINE)
2206+
for pos, endpos in [(3, 0), (4, 0), (4, 3), (2, 1)]:
2207+
self.assertIsNone(p.match(string, pos, endpos))
2208+
self.assertIsNone(p.fullmatch(string, pos, endpos))
2209+
self.assertIsNone(p.search(string, pos, endpos))
2210+
self.assertIsNone(
2211+
p.scanner(string, pos, endpos).match())
2212+
self.assertIsNone(
2213+
p.scanner(string, pos, endpos).search())
2214+
self.assertEqual(p.findall(string, pos, endpos), [])
2215+
21972216
def test_bug_20998(self):
21982217
# Issue #20998: Fullmatch of repeated single character pattern
21992218
# 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
@@ -746,6 +746,10 @@ pattern_dealloc(PyObject *self)
746746
LOCAL(Py_ssize_t)
747747
sre_match(SRE_STATE* state, SRE_CODE* pattern)
748748
{
749+
/* No match if pos > endpos. */
750+
if (state->ptr > state->end) {
751+
return 0;
752+
}
749753
if (state->charsize == 1)
750754
return sre_ucs1_match(state, pattern, 1);
751755
if (state->charsize == 2)

0 commit comments

Comments
 (0)