summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2020-03-31 23:47:55 +0200
committerStefan Behnel <stefan_ml@behnel.de>2020-03-31 23:48:39 +0200
commit4fd901849ff30399289ebf6613c81d8075a79cc4 (patch)
tree22442ef635815d6f79c919dd5118892665b4be15
parent65f69510e95e5e1205e188c2ebb418d8ba336076 (diff)
downloadcython-4fd901849ff30399289ebf6613c81d8075a79cc4.tar.gz
Avoid relying on signed integer overflow in f-string joining helper function.
-rw-r--r--Cython/Utility/StringTools.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c
index ed56c7006..9b20c4a2b 100644
--- a/Cython/Utility/StringTools.c
+++ b/Cython/Utility/StringTools.c
@@ -860,7 +860,7 @@ static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_co
CYTHON_UNUSED Py_UCS4 max_char) {
#if CYTHON_USE_UNICODE_INTERNALS && CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
PyObject *result_uval;
- int result_ukind;
+ int result_ukind, kind_shift;
Py_ssize_t i, char_pos;
void *result_udata;
#if CYTHON_PEP393_ENABLED
@@ -868,14 +868,17 @@ static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_co
result_uval = PyUnicode_New(result_ulength, max_char);
if (unlikely(!result_uval)) return NULL;
result_ukind = (max_char <= 255) ? PyUnicode_1BYTE_KIND : (max_char <= 65535) ? PyUnicode_2BYTE_KIND : PyUnicode_4BYTE_KIND;
+ kind_shift = (result_ukind == PyUnicode_4BYTE_KIND) ? 2 : result_ukind - 1;
result_udata = PyUnicode_DATA(result_uval);
#else
// Py 2.x/3.2 (pre PEP-393)
result_uval = PyUnicode_FromUnicode(NULL, result_ulength);
if (unlikely(!result_uval)) return NULL;
result_ukind = sizeof(Py_UNICODE);
+ kind_shift = (result_ukind == 4) ? 2 : result_ukind - 1;
result_udata = PyUnicode_AS_UNICODE(result_uval);
#endif
+ assert(kind_shift == 2 || kind_shift == 1 || kind_shift == 0);
char_pos = 0;
for (i=0; i < value_count; i++) {
@@ -888,12 +891,12 @@ static PyObject* __Pyx_PyUnicode_Join(PyObject* value_tuple, Py_ssize_t value_co
ulength = __Pyx_PyUnicode_GET_LENGTH(uval);
if (unlikely(!ulength))
continue;
- if (unlikely(char_pos + ulength < 0))
+ if (unlikely((PY_SSIZE_T_MAX >> kind_shift) - ulength < char_pos))
goto overflow;
ukind = __Pyx_PyUnicode_KIND(uval);
udata = __Pyx_PyUnicode_DATA(uval);
if (!CYTHON_PEP393_ENABLED || ukind == result_ukind) {
- memcpy((char *)result_udata + char_pos * result_ukind, udata, (size_t) (ulength * result_ukind));
+ memcpy((char *)result_udata + (char_pos << kind_shift), udata, (size_t) (ulength << kind_shift));
} else {
#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030300F0 || defined(_PyUnicode_FastCopyCharacters)
_PyUnicode_FastCopyCharacters(result_uval, char_pos, uval, 0, ulength);