@@ -861,8 +861,8 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
861
861
862
862
static zend_never_inline void zend_assign_to_string_offset (zval * str , zval * dim , zval * value , zval * result )
863
863
{
864
- zend_string * old_str ;
865
- zend_uchar c ;
864
+ zend_string * old_str
865
+ char * string_value ;
866
866
size_t string_len ;
867
867
zend_long offset ;
868
868
@@ -879,42 +879,62 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
879
879
if (Z_TYPE_P (value ) != IS_STRING ) {
880
880
/* Convert to string, just the time to pick the 1st byte */
881
881
zend_string * tmp = zval_try_get_string_func (value );
882
-
883
882
if (UNEXPECTED (!tmp )) {
884
883
if (result ) {
885
884
ZVAL_UNDEF (result );
886
885
}
887
886
return ;
888
887
}
889
888
889
+ string_value = ZSTR_VAL (tmp );
890
890
string_len = ZSTR_LEN (tmp );
891
- c = (zend_uchar )ZSTR_VAL (tmp )[0 ];
892
- zend_string_release (tmp );
891
+ zend_string_release_ex (tmp , 0 );
893
892
} else {
893
+ string_value = Z_STRVAL_P (value );
894
894
string_len = Z_STRLEN_P (value );
895
- c = (zend_uchar )Z_STRVAL_P (value )[0 ];
896
- }
897
-
898
- if (string_len == 0 ) {
899
- /* Error on empty input string */
900
- zend_error (E_WARNING , "Cannot assign an empty string to a string offset" );
901
- if (result ) {
902
- ZVAL_NULL (result );
903
- }
904
- return ;
905
895
}
906
896
907
897
if (offset < 0 ) { /* Handle negative offset */
908
898
offset += (zend_long )Z_STRLEN_P (str );
909
899
}
900
+ /* If it's a byte char replace byte directly */
901
+ if (string_len == 1 ) {
902
+ zend_uchar c = (zend_uchar ) string_value [0 ];
903
+
904
+ if ((size_t )offset >= Z_STRLEN_P (str )) {
905
+ /* Extend string if needed */
906
+ zend_long old_len = Z_STRLEN_P (str );
907
+ ZVAL_NEW_STR (str , zend_string_extend (Z_STR_P (str ), offset + 1 , 0 ));
908
+ memset (Z_STRVAL_P (str ) + old_len , ' ' , offset - old_len );
909
+ Z_STRVAL_P (str )[offset + 1 ] = 0 ;
910
+ } else if (!Z_REFCOUNTED_P (str )) {
911
+ old_str = Z_STR_P (str );
912
+ Z_STR_P (str ) = zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 );
913
+ Z_TYPE_INFO_P (str ) = IS_STRING_EX ;
914
+ zend_string_release (old_str );
915
+ } else {
916
+ SEPARATE_STRING (str );
917
+ zend_string_forget_hash_val (Z_STR_P (str ));
918
+ }
919
+
920
+ Z_STRVAL_P (str )[offset ] = c ;
921
+
922
+ if (result ) {
923
+ /* Return the new character */
924
+ ZVAL_INTERNED_STR (result , ZSTR_CHAR (c ));
925
+ }
926
+ }
910
927
911
928
if ((size_t )offset >= Z_STRLEN_P (str )) {
912
929
/* Extend string if needed */
913
930
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 ;
931
+ ZVAL_NEW_STR (str , zend_string_extend (Z_STR_P (str ), offset + string_len , 0 ));
916
932
memset (Z_STRVAL_P (str ) + old_len , ' ' , offset - old_len );
917
- Z_STRVAL_P (str )[offset + 1 ] = 0 ;
933
+ ZVAL_NEW_STR (str , zend_string_init (strcat (Z_STRVAL_P (str ), string_value ), offset + string_len , 0 ));
934
+ if (result ) {
935
+ ZVAL_INTERNED_STR (result , zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
936
+ }
937
+ return ;
918
938
} else if (!Z_REFCOUNTED_P (str )) {
919
939
old_str = Z_STR_P (str );
920
940
Z_STR_P (str ) = zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 );
@@ -925,12 +945,42 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
925
945
zend_string_forget_hash_val (Z_STR_P (str ));
926
946
}
927
947
928
- Z_STRVAL_P (str )[offset ] = c ;
929
-
948
+ // Buffer offset
949
+ int k = 0 ;
950
+ // Source offset
951
+ int i = 0 ;
952
+ char * buffer = emalloc (Z_STRLEN_P (str ) + string_len - 1 ); // -1 as we replace a byte
953
+ char * source = Z_STRVAL_P (str );
954
+ // Append bytes from the source string to the buffer until the offset is reached
955
+ while (i < offset ) {
956
+ buffer [k ] = source [i ];
957
+ i ++ ;
958
+ k ++ ;
959
+ }
960
+ i ++ ; // Skip byte being replaced
961
+ // If not an empty string then append all the bytes from the value to the buffer
962
+ if (string_len > 0 ) {
963
+ int j = 0 ;
964
+ while (string_value [j ] != '\0' ) {
965
+ buffer [k ] = string_value [j ];
966
+ j ++ ;
967
+ k ++ ;
968
+ }
969
+ }
970
+ // Add remaining bytes from the source string.
971
+ while (source [i ] != '\0' ) {
972
+ buffer [k ] = source [i ];
973
+ i ++ ;
974
+ k ++ ;
975
+ }
976
+ // Append NUL byte to make a valid C string.
977
+ buffer [k ] = '\0' ;
978
+ ZVAL_NEW_STR (str , zend_string_init (buffer , Z_STRLEN_P (str ) + string_len - 1 , 0 ));
930
979
if (result ) {
931
- /* Return the new character */
932
- ZVAL_INTERNED_STR (result , ZSTR_CHAR (c ));
980
+ ZVAL_INTERNED_STR (result , zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
933
981
}
982
+
983
+ efree (buffer );
934
984
}
935
985
936
986
static void ZEND_FASTCALL zend_jit_assign_dim_helper (zval * object_ptr , zval * dim , zval * value , zval * result )
0 commit comments