gh-67877: Fix memory leaks in terminated RE matching (GH-126840)

If SRE(match) function terminates abruptly, either because of a signal
or because memory allocation fails, allocated SRE_REPEAT blocks might
be never released.

Co-authored-by: <wjssz@users.noreply.github.com>
This commit is contained in:
Serhiy Storchaka 2024-11-18 11:53:45 +02:00 committed by GitHub
parent 3938fd60c0
commit 7538e7f569
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 230 additions and 14 deletions

View file

@ -2681,6 +2681,29 @@ class ReTests(unittest.TestCase):
self.assertIsNone(re.search(p, s))
self.assertIsNone(re.search('(?s:.)' + p, s))
def check_interrupt(self, pattern, string, maxcount):
class Interrupt(Exception):
pass
p = re.compile(pattern)
for n in range(maxcount):
try:
p._fail_after(n, Interrupt)
p.match(string)
return n
except Interrupt:
pass
finally:
p._fail_after(-1, None)
@unittest.skipUnless(hasattr(re.Pattern, '_fail_after'), 'requires debug build')
def test_memory_leaks(self):
self.check_interrupt(r'(.)*:', 'abc:', 100)
self.check_interrupt(r'([^:])*?:', 'abc:', 100)
self.check_interrupt(r'([^:])*+:', 'abc:', 100)
self.check_interrupt(r'(.){2,4}:', 'abc:', 100)
self.check_interrupt(r'([^:]){2,4}?:', 'abc:', 100)
self.check_interrupt(r'([^:]){2,4}+:', 'abc:', 100)
def get_debug_out(pat):
with captured_stdout() as out: