Skip to content

Commit 212452d

Browse files
committed
Add test case for adaptive_find and comments better explaining the reasons for
and limitations of the tests.
1 parent 1d0210a commit 212452d

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

Lib/test/string_tests.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,13 +767,40 @@ def test_replace(self):
767767
self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
768768
self.checkraises(TypeError, 'hello', 'replace', 'h', 42)
769769

770-
# gh-127971
770+
def test_replacement_on_buffer_boundary(self):
771+
772+
# gh-127971: Check we don't read past the end of the buffer when a
773+
# potential match misses on the last character. Note this will likely
774+
# not cause a failure unless ASAN is enabled, and even that may be
775+
# dependent on implementation details subject to change.
771776
any_3_nonblank_codepoints = '!!!'
772777
seven_codepoints = any_3_nonblank_codepoints + ' ' + any_3_nonblank_codepoints
773778
a = (' ' * 243) + seven_codepoints + (' ' * 7)
774779
b = ' ' * 6 + chr(256)
775780
a.replace(seven_codepoints, b)
776781

782+
def test_adaptive_find_on_buffer_boundary(self):
783+
784+
# gh-127971: This exercises the adaptive search algorithm to trigger a
785+
# corner-case where it might examine the character *after* the last
786+
# position that could be the start of the pattern.
787+
#
788+
# Unfortunately there is nothing to *test* to confirm whether the
789+
# character is read or not, nor in fact does it matter for correctness
790+
# with the implementation at time of writing: the adaptive algorithm is
791+
# only triggered if the input is over a certain size and with a pattern
792+
# with more than one character, so with the current implementation even
793+
# though the final character read is not necessary or significant, it
794+
# won't cause a fault.
795+
#
796+
# This test at least intentionally exercises this path, and might
797+
# possibly catch a regression if the implementation changes and breaks
798+
# those assumptions.
799+
prefix = ' ' * (1024 * 4)
800+
haystack = prefix + 'x'
801+
needle = prefix + 'y'
802+
self.assertEqual(haystack.find(needle), -1)
803+
777804
def test_replace_uses_two_way_maxcount(self):
778805
# Test that maxcount works in _two_way_count in fastsearch.h
779806
A, B = "A"*1000, "B"*1000

0 commit comments

Comments
 (0)