@@ -863,6 +863,7 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
863
863
{
864
864
zend_string * old_str ;
865
865
zend_uchar c ;
866
+ char * string_value ;
866
867
size_t string_len ;
867
868
zend_long offset ;
868
869
@@ -888,11 +889,11 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
888
889
}
889
890
890
891
string_len = ZSTR_LEN (tmp );
891
- c = ( zend_uchar ) ZSTR_VAL (tmp )[ 0 ] ;
892
+ string_value = ZSTR_VAL (tmp );
892
893
zend_string_release (tmp );
893
894
} else {
894
895
string_len = Z_STRLEN_P (value );
895
- c = ( zend_uchar ) Z_STRVAL_P (value )[ 0 ] ;
896
+ string_value = Z_STRVAL_P (value );
896
897
}
897
898
898
899
if (string_len == 0 ) {
@@ -904,32 +905,98 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
904
905
return ;
905
906
}
906
907
907
- if (offset < 0 ) { /* Handle negative offset */
908
- offset += (zend_long )Z_STRLEN_P (str );
908
+ /* If it's a byte char replace byte directly */
909
+ if (string_len == 1 ) {
910
+ c = (zend_uchar )string_value [0 ];
911
+
912
+ if (offset < 0 ) { /* Handle negative offset */
913
+ offset += (zend_long )
914
+ Z_STRLEN_P (str );
915
+ }
916
+
917
+ if ((size_t ) offset >= Z_STRLEN_P (str )) {
918
+ /* Extend string if needed */
919
+ zend_long old_len = Z_STRLEN_P (str );
920
+ Z_STR_P (str ) = zend_string_extend (Z_STR_P (str ), offset + 1 , 0 );
921
+ Z_TYPE_INFO_P (str ) = IS_STRING_EX ;
922
+ memset (Z_STRVAL_P (str ) + old_len , ' ' , offset - old_len );
923
+ Z_STRVAL_P (str )[offset + 1 ] = 0 ;
924
+ } else if (!Z_REFCOUNTED_P (str )) {
925
+ old_str = Z_STR_P (str );
926
+ Z_STR_P (str ) = zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 );
927
+ Z_TYPE_INFO_P (str ) = IS_STRING_EX ;
928
+ zend_string_release (old_str );
929
+ } else {
930
+ SEPARATE_STRING (str );
931
+ zend_string_forget_hash_val (Z_STR_P (str ));
932
+ }
933
+
934
+ Z_STRVAL_P (str )[offset ] = c ;
935
+
936
+ if (result ) {
937
+ /* Return the new character */
938
+ ZVAL_INTERNED_STR (result , ZSTR_CHAR (c ));
939
+ }
940
+ return ;
909
941
}
910
942
943
+
944
+
911
945
if ((size_t )offset >= Z_STRLEN_P (str )) {
912
- /* Extend string if needed */
946
+ /* Extend string */
913
947
zend_long old_len = Z_STRLEN_P (str );
914
- Z_STR_P (str ) = zend_string_extend (Z_STR_P (str ), offset + 1 , 0 );
915
- Z_TYPE_INFO_P (str ) = IS_STRING_EX ;
916
- memset (Z_STRVAL_P (str ) + old_len , ' ' , offset - old_len );
917
- Z_STRVAL_P (str )[offset + 1 ] = 0 ;
948
+ zend_string * tmp = zend_string_extend (Z_STR_P (str ), offset + string_len , 0 ); // Leak
949
+ memset (ZSTR_VAL (tmp ) + old_len , ' ' , offset - old_len );
950
+ memcpy (ZSTR_VAL (tmp ) + offset , string_value , string_len );
951
+ if (result ) {
952
+ ZVAL_STR (result , zend_string_init (ZSTR_VAL (tmp ), ZSTR_LEN (tmp ), 0 ));
953
+ }
954
+ zend_string_release_ex (tmp , 0 );
955
+ return ;
918
956
} else if (!Z_REFCOUNTED_P (str )) {
919
- old_str = Z_STR_P (str );
920
- Z_STR_P ( str ) = zend_string_init ( Z_STRVAL_P (str ), Z_STRLEN_P ( str ), 0 );
921
- Z_TYPE_INFO_P (str ) = IS_STRING_EX ;
922
- zend_string_release ( old_str );
957
+ ZVAL_NEW_STR ( str , zend_string_init ( Z_STRVAL_P ( str ), Z_STRLEN_P (str ), 0 ) );
958
+ } else if ( Z_REFCOUNT_P (str ) > 1 ) {
959
+ Z_DELREF_P (str );
960
+ ZVAL_NEW_STR ( str , zend_string_init ( Z_STRVAL_P ( str ), Z_STRLEN_P ( str ), 0 ) );
923
961
} else {
924
- SEPARATE_STRING (str );
925
962
zend_string_forget_hash_val (Z_STR_P (str ));
926
963
}
927
964
928
- Z_STRVAL_P (str )[offset ] = c ;
965
+ // Buffer offset
966
+ int k = 0 ;
967
+ // Source offset
968
+ int i = 0 ;
969
+ char * buffer = emalloc (Z_STRLEN_P (str ) + string_len );
970
+ char * source = Z_STRVAL_P (str );
971
+ // Append bytes from the source string to the buffer until the offset is reached
972
+ while (i < offset ) {
973
+ buffer [k ] = source [i ];
974
+ i ++ ;
975
+ k ++ ;
976
+ }
977
+ i ++ ; // Skip byte being replaced
978
+ // If not an empty string then append all the bytes from the value to the buffer
979
+ if (string_len > 0 ) {
980
+ int j = 0 ;
981
+ while (string_value [j ] != '\0' ) {
982
+ buffer [k ] = string_value [j ];
983
+ j ++ ;
984
+ k ++ ;
985
+ }
986
+ }
987
+ // Add remaining bytes from the source string.
988
+ while (source [i ] != '\0' ) {
989
+ buffer [k ] = source [i ];
990
+ i ++ ;
991
+ k ++ ;
992
+ }
993
+ // Append NUL byte to make a valid C string.
994
+ buffer [k ] = '\0' ;
995
+ ZVAL_NEW_STR (str , zend_string_init (buffer , Z_STRLEN_P (str ) + string_len - 1 , 0 ));
996
+ efree (buffer );
929
997
930
998
if (result ) {
931
- /* Return the new character */
932
- ZVAL_INTERNED_STR (result , ZSTR_CHAR (c ));
999
+ ZVAL_STR (result , zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
933
1000
}
934
1001
}
935
1002
0 commit comments