Skip to content

Commit 31b9410

Browse files
Issue python#25709: Fixed problem with in-place string concatenation and utf-8 cache.
1 parent fab75d9 commit 31b9410

File tree

3 files changed

+27
-0
lines changed

3 files changed

+27
-0
lines changed

Lib/test/test_unicode.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,6 +2303,23 @@ def test_resize(self):
23032303
self.assertNotEqual(abc, abcdef)
23042304
self.assertEqual(abcdef.decode('unicode_internal'), text)
23052305

2306+
@support.cpython_only
2307+
def test_pep393_utf8_caching_bug(self):
2308+
# Issue #25709: Problem with string concatenation and utf-8 cache
2309+
from _testcapi import getargs_s_hash
2310+
for k in 0x24, 0xa4, 0x20ac, 0x1f40d:
2311+
s = ''
2312+
for i in range(5):
2313+
# Due to CPython specific optimization the 's' string can be
2314+
# resized in-place.
2315+
s += chr(k)
2316+
# Parsing with the "s#" format code calls indirectly
2317+
# PyUnicode_AsUTF8AndSize() which creates the UTF-8
2318+
# encoded string cached in the Unicode object.
2319+
self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1))
2320+
# Check that the second call returns the same result
2321+
self.assertEqual(getargs_s_hash(s), chr(k).encode() * (i + 1))
2322+
23062323

23072324
class StringModuleTest(unittest.TestCase):
23082325
def test_formatter_parser(self):

Misc/NEWS

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@ What's New in Python 3.3.7?
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #25709: Fixed problem with in-place string concatenation and utf-8 cache.
14+
1315
- Issue #24407: Fix crash when dict is mutated while being updated.
1416

17+
- Issue #24097: Fixed crash in object.__reduce__() if slot name is freed inside
18+
__getattr__.
19+
1520
- Issue #24096: Make warnings.warn_explicit more robust against mutation of the
1621
warnings.filters list.
1722

Objects/unicodeobject.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,11 @@ resize_compact(PyObject *unicode, Py_ssize_t length)
679679
}
680680
new_size = (struct_size + (length + 1) * char_size);
681681

682+
if (_PyUnicode_HAS_UTF8_MEMORY(unicode)) {
683+
PyObject_DEL(_PyUnicode_UTF8(unicode));
684+
_PyUnicode_UTF8(unicode) = NULL;
685+
_PyUnicode_UTF8_LENGTH(unicode) = 0;
686+
}
682687
_Py_DEC_REFTOTAL;
683688
_Py_ForgetReference(unicode);
684689

0 commit comments

Comments
 (0)