From cad35409cbfd192159cb7f15535362e15f624a58 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 17 Jul 2024 09:02:03 +0200 Subject: [PATCH] gh-121849: Fix PyUnicodeWriter_WriteSubstring() crash if len=0 Do nothing if start=end. --- Lib/test/test_capi/test_unicode.py | 6 +++++- Objects/unicodeobject.c | 23 ++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_capi/test_unicode.py b/Lib/test/test_capi/test_unicode.py index 9ef476a02de47d..e6f85427214958 100644 --- a/Lib/test/test_capi/test_unicode.py +++ b/Lib/test/test_capi/test_unicode.py @@ -1736,7 +1736,7 @@ def test_basic(self): writer.write_char('=') # test PyUnicodeWriter_WriteSubstring() - writer.write_substring("[long]", 1, 5); + writer.write_substring("[long]", 1, 5) # test PyUnicodeWriter_WriteStr() writer.write_str(" value ") @@ -1862,6 +1862,10 @@ def test_ucs4(self): with self.assertRaises(ValueError): writer.write_ucs4("text", -1) + def test_substring_empty(self): + writer = self.create_writer(0) + writer.write_substring("abc", 1, 1) + self.assertEqual(writer.finish(), '') @unittest.skipIf(ctypes is None, 'need ctypes') diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index 408d74fb3afef9..6196a8e766a15b 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13637,27 +13637,28 @@ int _PyUnicodeWriter_WriteSubstring(_PyUnicodeWriter *writer, PyObject *str, Py_ssize_t start, Py_ssize_t end) { - Py_UCS4 maxchar; - Py_ssize_t len; - assert(0 <= start); assert(end <= PyUnicode_GET_LENGTH(str)); assert(start <= end); - if (end == 0) - return 0; - if (start == 0 && end == PyUnicode_GET_LENGTH(str)) return _PyUnicodeWriter_WriteStr(writer, str); - if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) + Py_ssize_t len = end - start; + if (len == 0) { + return 0; + } + + Py_UCS4 maxchar; + if (PyUnicode_MAX_CHAR_VALUE(str) > writer->maxchar) { maxchar = _PyUnicode_FindMaxChar(str, start, end); - else + } + else { maxchar = writer->maxchar; - len = end - start; - - if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) + } + if (_PyUnicodeWriter_Prepare(writer, len, maxchar) < 0) { return -1; + } _PyUnicode_FastCopyCharacters(writer->buffer, writer->pos, str, start, len);