Skip to content

Commit 348e22c

Browse files
[3.14] gh-127971: fix off-by-one read beyond the end of a string during search (GH-132574) (#136628)
gh-127971: fix off-by-one read beyond the end of a string during search (GH-132574) (cherry picked from commit 85ec3b3) Co-authored-by: Duane Griffin <duaneg@dghda.com>
1 parent ed1e0cd commit 348e22c

File tree

3 files changed

+14
-4
lines changed

3 files changed

+14
-4
lines changed

Lib/test/string_tests.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,15 @@ def test_replace(self):
767767
self.checkraises(TypeError, 'hello', 'replace', 42, 'h')
768768
self.checkraises(TypeError, 'hello', 'replace', 'h', 42)
769769

770+
def test_replacement_on_buffer_boundary(self):
771+
# gh-127971: Check we don't read past the end of the buffer when a
772+
# potential match misses on the last character.
773+
any_3_nonblank_codepoints = '!!!'
774+
seven_codepoints = any_3_nonblank_codepoints + ' ' + any_3_nonblank_codepoints
775+
a = (' ' * 243) + seven_codepoints + (' ' * 7)
776+
b = ' ' * 6 + chr(256)
777+
a.replace(seven_codepoints, b)
778+
770779
def test_replace_uses_two_way_maxcount(self):
771780
# Test that maxcount works in _two_way_count in fastsearch.h
772781
A, B = "A"*1000, "B"*1000
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix off-by-one read beyond the end of a string in string search.

Objects/stringlib/fastsearch.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ STRINGLIB(default_find)(const STRINGLIB_CHAR* s, Py_ssize_t n,
595595
continue;
596596
}
597597
/* miss: check if next character is part of pattern */
598-
if (!STRINGLIB_BLOOM(mask, ss[i+1])) {
598+
if (i + 1 <= w && !STRINGLIB_BLOOM(mask, ss[i+1])) {
599599
i = i + m;
600600
}
601601
else {
@@ -604,7 +604,7 @@ STRINGLIB(default_find)(const STRINGLIB_CHAR* s, Py_ssize_t n,
604604
}
605605
else {
606606
/* skip: check if next character is part of pattern */
607-
if (!STRINGLIB_BLOOM(mask, ss[i+1])) {
607+
if (i + 1 <= w && !STRINGLIB_BLOOM(mask, ss[i+1])) {
608608
i = i + m;
609609
}
610610
}
@@ -668,7 +668,7 @@ STRINGLIB(adaptive_find)(const STRINGLIB_CHAR* s, Py_ssize_t n,
668668
}
669669
}
670670
/* miss: check if next character is part of pattern */
671-
if (!STRINGLIB_BLOOM(mask, ss[i+1])) {
671+
if (i + 1 <= w && !STRINGLIB_BLOOM(mask, ss[i+1])) {
672672
i = i + m;
673673
}
674674
else {
@@ -677,7 +677,7 @@ STRINGLIB(adaptive_find)(const STRINGLIB_CHAR* s, Py_ssize_t n,
677677
}
678678
else {
679679
/* skip: check if next character is part of pattern */
680-
if (!STRINGLIB_BLOOM(mask, ss[i+1])) {
680+
if (i + 1 <= w && !STRINGLIB_BLOOM(mask, ss[i+1])) {
681681
i = i + m;
682682
}
683683
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy