https://github.com/python/cpython/commit/79249038315b7bb8288a37415ca94e63753ec852
commit: 79249038315b7bb8288a37415ca94e63753ec852
branch: 3.14
author: Miss Islington (bot) <[email protected]>
committer: sobolevn <[email protected]>
date: 2026-06-29T16:49:17Z
summary:

[3.14] gh-152228: Fix an assertion failure in `str.replace` under a limited 
memory case (GH-152229) (#152616)

gh-152228: Fix an assertion failure in `str.replace` under a limited memory 
case (GH-152229)
(cherry picked from commit c5043dce1c6743682d93c71e937b95e7d27e0b35)

Co-authored-by: sobolevn <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-06-25-21-34-15.gh-issue-152228.a6K14K.rst
M Lib/test/test_str.py
M Objects/unicodeobject.c

diff --git a/Lib/test/test_str.py b/Lib/test/test_str.py
index 2584fbf72d3fa6..444841ddd470aa 100644
--- a/Lib/test/test_str.py
+++ b/Lib/test/test_str.py
@@ -600,6 +600,21 @@ def test_replace_id(self):
         text = 'abc def'
         self.assertIs(text.replace(pattern, pattern), text)
 
+    @support.nomemtest
+    def test_replace_oom(self):
+        # https://github.com/python/cpython/issues/152228
+        s1 = "轘" * 4
+        s2 = "&"
+        s3 = "&amp;"
+        assertion = self.assertRaises(MemoryError)
+        _testcapi.set_nomemory(0, 0)
+        try:
+            # No allocations made in the test itself:
+            with assertion:
+                s1.replace(s2, s3)  # this line used to crash before
+        finally:
+            _testcapi.remove_mem_hooks()
+
     def test_repeat_id_preserving(self):
         a = '123abc1@'
         b = '456zyx-+'
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-25-21-34-15.gh-issue-152228.a6K14K.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-25-21-34-15.gh-issue-152228.a6K14K.rst
new file mode 100644
index 00000000000000..8af7ae0d173913
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-25-21-34-15.gh-issue-152228.a6K14K.rst
@@ -0,0 +1,2 @@
+Fix an assertion failure when python is built in a debug mode
+that happened in :meth:`str.replace` under a limited memory situation.
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 0a7f3dfe5f66f4..e249473cd79e3b 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -11046,9 +11046,9 @@ replace(PyObject *self, PyObject *str1,
     }
 
   done:
-    assert(srelease == (sbuf != PyUnicode_DATA(self)));
-    assert(release1 == (buf1 != PyUnicode_DATA(str1)));
-    assert(release2 == (buf2 != PyUnicode_DATA(str2)));
+    assert(srelease == (sbuf != NULL && sbuf != PyUnicode_DATA(self)));
+    assert(release1 == (buf1 != NULL && buf1 != PyUnicode_DATA(str1)));
+    assert(release2 == (buf2 != NULL && buf2 != PyUnicode_DATA(str2)));
     if (srelease)
         PyMem_Free((void *)sbuf);
     if (release1)
@@ -11060,9 +11060,9 @@ replace(PyObject *self, PyObject *str1,
 
   nothing:
     /* nothing to replace; return original string (when possible) */
-    assert(srelease == (sbuf != PyUnicode_DATA(self)));
-    assert(release1 == (buf1 != PyUnicode_DATA(str1)));
-    assert(release2 == (buf2 != PyUnicode_DATA(str2)));
+    assert(srelease == (sbuf != NULL && sbuf != PyUnicode_DATA(self)));
+    assert(release1 == (buf1 != NULL && buf1 != PyUnicode_DATA(str1)));
+    assert(release2 == (buf2 != NULL && buf2 != PyUnicode_DATA(str2)));
     if (srelease)
         PyMem_Free((void *)sbuf);
     if (release1)
@@ -11072,9 +11072,9 @@ replace(PyObject *self, PyObject *str1,
     return unicode_result_unchanged(self);
 
   error:
-    assert(srelease == (sbuf != PyUnicode_DATA(self)));
-    assert(release1 == (buf1 != PyUnicode_DATA(str1)));
-    assert(release2 == (buf2 != PyUnicode_DATA(str2)));
+    assert(srelease == (sbuf != NULL && sbuf != PyUnicode_DATA(self)));
+    assert(release1 == (buf1 != NULL && buf1 != PyUnicode_DATA(str1)));
+    assert(release2 == (buf2 != NULL && buf2 != PyUnicode_DATA(str2)));
     if (srelease)
         PyMem_Free((void *)sbuf);
     if (release1)

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to