Skip to content

Commit 93e0f6b

Browse files
committed
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. Closes GH-10936.
1 parent f6989df commit 93e0f6b

File tree

2 files changed

+4
-4
lines changed

2 files changed

+4
-4
lines changed

Zend/zend_operators.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2760,7 +2760,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo
27602760
if (_mm_movemask_epi8(mingle)) {
27612761
zend_string *res = zend_string_alloc(length, persistent);
27622762
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char *) ZSTR_VAL(str));
2763-
unsigned char *q = p + (ZSTR_VAL(res) - ZSTR_VAL(str));
2763+
unsigned char *q = (unsigned char*) ZSTR_VAL(res) + (p - (unsigned char*) ZSTR_VAL(str));
27642764

27652765
/* Lowercase the chunk we already compared. */
27662766
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
27832783
zend_string *res = zend_string_alloc(length, persistent);
27842784
memcpy(ZSTR_VAL(res), ZSTR_VAL(str), p - (unsigned char*) ZSTR_VAL(str));
27852785

2786-
unsigned char *q = p + (ZSTR_VAL(res) - ZSTR_VAL(str));
2786+
unsigned char *q = (unsigned char*) ZSTR_VAL(res) + (p - (unsigned char*) ZSTR_VAL(str));
27872787
while (p < end) {
27882788
*q++ = zend_tolower_ascii(*p++);
27892789
}

ext/standard/string.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ PHPAPI zend_string *php_string_toupper(zend_string *s)
13731373
if (c != (unsigned char*)ZSTR_VAL(s)) {
13741374
memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
13751375
}
1376-
r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
1376+
r = (unsigned char*) ZSTR_VAL(res) + (c - (unsigned char*) ZSTR_VAL(s));
13771377
while (c < e) {
13781378
*r = toupper(*c);
13791379
r++;
@@ -1438,7 +1438,7 @@ PHPAPI zend_string *php_string_tolower(zend_string *s)
14381438
if (c != (unsigned char*)ZSTR_VAL(s)) {
14391439
memcpy(ZSTR_VAL(res), ZSTR_VAL(s), c - (unsigned char*)ZSTR_VAL(s));
14401440
}
1441-
r = c + (ZSTR_VAL(res) - ZSTR_VAL(s));
1441+
r = (unsigned char*) ZSTR_VAL(res) + (c - (unsigned char*) ZSTR_VAL(s));
14421442
while (c < e) {
14431443
*r = tolower(*c);
14441444
r++;

0 commit comments

Comments
 (0)