From 69e077d25a5ebe43a293a80f7483b3bc793386c8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 25 Mar 2023 18:35:11 +0100 Subject: [PATCH] Fix undefined behaviour in string uppercasing and lowercasing At least on 32-bit, the address computations overflow in running the test on CI with UBSAN enabled. Fix it by reordering the arithmetic. Since a part of the expression is already used in the code above the computation, this should not negatively affect performance. --- Zend/zend_operators.c | 4 ++-- ext/standard/string.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 93df8cea2ea9d..d61334471f01c 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2760,7 +2760,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo if (_mm_movemask_epi8(mingle)) { zend_string *res = zend_string_alloc(length, persistent); memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char *) ZSTR_VAL(str)); - unsigned char *q = p + (ZSTR_VAL(res) - ZSTR_VAL(str)); + unsigned char *q = p - (unsigned char*) ZSTR_VAL(str) + (unsigned char*) ZSTR_VAL(res); /* Lowercase the chunk we already compared. */ const __m128i delta = _mm_set1_epi8('a' - 'A'); @@ -2783,7 +2783,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo zend_string *res = zend_string_alloc(length, persistent); memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*) ZSTR_VAL(str)); - unsigned char *q = p + (ZSTR_VAL(res) - ZSTR_VAL(str)); + unsigned char *q = p - (unsigned char*) ZSTR_VAL(str) + (unsigned char*) ZSTR_VAL(res); while (p < end) { *q++ = zend_tolower_ascii(*p++); } diff --git a/ext/standard/string.c b/ext/standard/string.c index 368f0123870ce..284ad18f47f60 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1373,7 +1373,7 @@ PHPAPI zend_string *php_string_toupper(zend_string *s) if (c != (unsigned char*)ZSTR_VAL(s)) { memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s)); } - r = c + (ZSTR_VAL(res) - ZSTR_VAL(s)); + r = c - (unsigned char*) ZSTR_VAL(s) + (unsigned char*) ZSTR_VAL(res); while (c < e) { *r = toupper(*c); r++; @@ -1438,7 +1438,7 @@ PHPAPI zend_string *php_string_tolower(zend_string *s) if (c != (unsigned char*)ZSTR_VAL(s)) { memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s)); } - r = c + (ZSTR_VAL(res) - ZSTR_VAL(s)); + r = c - (unsigned char*) ZSTR_VAL(s) + (unsigned char*) ZSTR_VAL(res); while (c < e) { *r = tolower(*c); r++;