Skip to content

Commit af2851a

Browse files
[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 6b58f9a) Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com> * 3.14-ize the news entry Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
1 parent a620d45 commit af2851a

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`,
2+
:meth:`re.Pattern.fullmatch` and the ``match()`` method
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)