@@ -1569,7 +1569,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(c
1569
1569
1570
1570
static zend_never_inline void zend_assign_to_string_offset (zval * str , zval * dim , zval * value OPLINE_DC EXECUTE_DATA_DC )
1571
1571
{
1572
- zend_uchar c ;
1572
+ char * string_value ;
1573
1573
size_t string_len ;
1574
1574
zend_long offset ;
1575
1575
@@ -1593,33 +1593,56 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
1593
1593
return ;
1594
1594
}
1595
1595
1596
+ string_value = ZSTR_VAL (tmp );
1596
1597
string_len = ZSTR_LEN (tmp );
1597
- c = (zend_uchar )ZSTR_VAL (tmp )[0 ];
1598
1598
zend_string_release_ex (tmp , 0 );
1599
1599
} else {
1600
+ string_value = Z_STRVAL_P (value );
1600
1601
string_len = Z_STRLEN_P (value );
1601
- c = (zend_uchar )Z_STRVAL_P (value )[0 ];
1602
1602
}
1603
1603
1604
- if (string_len == 0 ) {
1605
- /* Error on empty input string */
1606
- zend_error (E_WARNING , "Cannot assign an empty string to a string offset" );
1604
+ if (offset < 0 ) { /* Handle negative offset */
1605
+ offset += (zend_long )Z_STRLEN_P (str );
1606
+ }
1607
+
1608
+ /* If it's a byte char replace byte directly */
1609
+ if (string_len == 1 ) {
1610
+ zend_uchar c = (zend_uchar ) string_value [0 ];
1611
+
1612
+ if ((size_t )offset >= Z_STRLEN_P (str )) {
1613
+ /* Extend string if needed */
1614
+ zend_long old_len = Z_STRLEN_P (str );
1615
+ ZVAL_NEW_STR (str , zend_string_extend (Z_STR_P (str ), offset + 1 , 0 ));
1616
+ memset (Z_STRVAL_P (str ) + old_len , ' ' , offset - old_len );
1617
+ Z_STRVAL_P (str )[offset + 1 ] = 0 ;
1618
+ } else if (!Z_REFCOUNTED_P (str )) {
1619
+ ZVAL_NEW_STR (str , zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
1620
+ } else if (Z_REFCOUNT_P (str ) > 1 ) {
1621
+ Z_DELREF_P (str );
1622
+ ZVAL_NEW_STR (str , zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
1623
+ } else {
1624
+ zend_string_forget_hash_val (Z_STR_P (str ));
1625
+ }
1626
+
1627
+ Z_STRVAL_P (str )[offset ] = c ;
1628
+
1607
1629
if (UNEXPECTED (RETURN_VALUE_USED (opline ))) {
1608
- ZVAL_NULL (EX_VAR (opline -> result .var ));
1630
+ /* Return the new character */
1631
+ ZVAL_INTERNED_STR (EX_VAR (opline -> result .var ), ZSTR_CHAR (c ));
1609
1632
}
1610
1633
return ;
1611
1634
}
1612
1635
1613
- if (offset < 0 ) { /* Handle negative offset */
1614
- offset += (zend_long )Z_STRLEN_P (str );
1615
- }
1616
-
1617
1636
if ((size_t )offset >= Z_STRLEN_P (str )) {
1618
- /* Extend string if needed */
1637
+ /* Extend string */
1619
1638
zend_long old_len = Z_STRLEN_P (str );
1620
- ZVAL_NEW_STR (str , zend_string_extend (Z_STR_P (str ), offset + 1 , 0 ));
1639
+ ZVAL_NEW_STR (str , zend_string_extend (Z_STR_P (str ), offset + string_len , 0 ));
1621
1640
memset (Z_STRVAL_P (str ) + old_len , ' ' , offset - old_len );
1622
- Z_STRVAL_P (str )[offset + 1 ] = 0 ;
1641
+ memcpy (Z_STRVAL_P (str ) + offset , string_value , string_len );
1642
+ if (UNEXPECTED (RETURN_VALUE_USED (opline ))) {
1643
+ ZVAL_INTERNED_STR (EX_VAR (opline -> result .var ), zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
1644
+ }
1645
+ return ;
1623
1646
} else if (!Z_REFCOUNTED_P (str )) {
1624
1647
ZVAL_NEW_STR (str , zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
1625
1648
} else if (Z_REFCOUNT_P (str ) > 1 ) {
@@ -1629,12 +1652,42 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
1629
1652
zend_string_forget_hash_val (Z_STR_P (str ));
1630
1653
}
1631
1654
1632
- Z_STRVAL_P (str )[offset ] = c ;
1633
-
1655
+ // Buffer offset
1656
+ int k = 0 ;
1657
+ // Source offset
1658
+ int i = 0 ;
1659
+ char * buffer = emalloc (Z_STRLEN_P (str ) + string_len - 1 ); // -1 as we replace a byte
1660
+ char * source = Z_STRVAL_P (str );
1661
+ // Append bytes from the source string to the buffer until the offset is reached
1662
+ while (i < offset ) {
1663
+ buffer [k ] = source [i ];
1664
+ i ++ ;
1665
+ k ++ ;
1666
+ }
1667
+ i ++ ; // Skip byte being replaced
1668
+ // If not an empty string then append all the bytes from the value to the buffer
1669
+ if (string_len > 0 ) {
1670
+ int j = 0 ;
1671
+ while (string_value [j ] != '\0' ) {
1672
+ buffer [k ] = string_value [j ];
1673
+ j ++ ;
1674
+ k ++ ;
1675
+ }
1676
+ }
1677
+ // Add remaining bytes from the source string.
1678
+ while (source [i ] != '\0' ) {
1679
+ buffer [k ] = source [i ];
1680
+ i ++ ;
1681
+ k ++ ;
1682
+ }
1683
+ // Append NUL byte to make a valid C string.
1684
+ buffer [k ] = '\0' ;
1685
+ ZVAL_NEW_STR (str , zend_string_init (buffer , Z_STRLEN_P (str ) + string_len - 1 , 0 ));
1634
1686
if (UNEXPECTED (RETURN_VALUE_USED (opline ))) {
1635
- /* Return the new character */
1636
- ZVAL_INTERNED_STR (EX_VAR (opline -> result .var ), ZSTR_CHAR (c ));
1687
+ ZVAL_INTERNED_STR (EX_VAR (opline -> result .var ), zend_string_init (Z_STRVAL_P (str ), Z_STRLEN_P (str ), 0 ));
1637
1688
}
1689
+
1690
+ efree (buffer );
1638
1691
}
1639
1692
1640
1693
static zend_property_info * zend_get_prop_not_accepting_double (zend_reference * ref )
0 commit comments