@@ -2877,6 +2877,18 @@ ZEND_API char* ZEND_FASTCALL zend_str_toupper_dup_ex(const char *source, size_t
28772877}
28782878/* }}} */
28792879
2880+ static zend_string * ZEND_FASTCALL zend_string_alloc_or_partial_dup (zend_string * str , bool persistent , const unsigned char * p )
2881+ {
2882+ if (persistent || !zend_may_modify_string_in_place (str )) {
2883+ zend_string * res = zend_string_alloc (ZSTR_LEN (str ), persistent );
2884+ memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2885+ return res ;
2886+ } else {
2887+ zend_string_forget_hash_val (str );
2888+ return str ;
2889+ }
2890+ }
2891+
28802892ZEND_API zend_string * ZEND_FASTCALL zend_string_tolower_ex (zend_string * str , bool persistent ) /* {{{ */
28812893{
28822894 size_t length = ZSTR_LEN (str );
@@ -2888,8 +2900,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo
28882900 while (p + BLOCKCONV_STRIDE <= end ) {
28892901 BLOCKCONV_LOAD (p );
28902902 if (BLOCKCONV_FOUND ()) {
2891- zend_string * res = zend_string_alloc (length , persistent );
2892- memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2903+ zend_string * res = zend_string_alloc_or_partial_dup (str , persistent , p );
28932904 unsigned char * q = (unsigned char * ) ZSTR_VAL (res ) + (p - (unsigned char * ) ZSTR_VAL (str ));
28942905
28952906 /* Lowercase the chunk we already compared. */
@@ -2909,8 +2920,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_tolower_ex(zend_string *str, boo
29092920
29102921 while (p < end ) {
29112922 if (* p != zend_tolower_ascii (* p )) {
2912- zend_string * res = zend_string_alloc (length , persistent );
2913- memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2923+ zend_string * res = zend_string_alloc_or_partial_dup (str , persistent , p );
29142924
29152925 unsigned char * q = (unsigned char * ) ZSTR_VAL (res ) + (p - (unsigned char * ) ZSTR_VAL (str ));
29162926 while (p < end ) {
@@ -2937,8 +2947,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, boo
29372947 while (p + BLOCKCONV_STRIDE <= end ) {
29382948 BLOCKCONV_LOAD (p );
29392949 if (BLOCKCONV_FOUND ()) {
2940- zend_string * res = zend_string_alloc (length , persistent );
2941- memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2950+ zend_string * res = zend_string_alloc_or_partial_dup (str , persistent , p );
29422951 unsigned char * q = (unsigned char * ) ZSTR_VAL (res ) + (p - (unsigned char * ) ZSTR_VAL (str ));
29432952
29442953 /* Uppercase the chunk we already compared. */
@@ -2958,8 +2967,7 @@ ZEND_API zend_string* ZEND_FASTCALL zend_string_toupper_ex(zend_string *str, boo
29582967
29592968 while (p < end ) {
29602969 if (* p != zend_toupper_ascii (* p )) {
2961- zend_string * res = zend_string_alloc (length , persistent );
2962- memcpy (ZSTR_VAL (res ), ZSTR_VAL (str ), p - (unsigned char * ) ZSTR_VAL (str ));
2970+ zend_string * res = zend_string_alloc_or_partial_dup (str , persistent , p );
29632971
29642972 unsigned char * q = (unsigned char * ) ZSTR_VAL (res ) + (p - (unsigned char * ) ZSTR_VAL (str ));
29652973 while (p < end ) {
0 commit comments