Skip to content

Commit 7ed0a4d

Browse files
committed
Revert "New implementation (without leaks)"
Due to some null bytes disapering and I have no idea why. This reverts commit 236c583.
1 parent 236c583 commit 7ed0a4d

File tree

2 files changed

+57
-75
lines changed

2 files changed

+57
-75
lines changed

Zend/zend_execute.c

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,7 +1571,6 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
15711571
{
15721572
char *string_value;
15731573
size_t string_len;
1574-
zend_long old_len = Z_STRLEN_P(str);
15751574
zend_long offset;
15761575

15771576
offset = zend_check_string_offset(dim, BP_VAR_W EXECUTE_DATA_CC);
@@ -1612,6 +1611,7 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
16121611

16131612
if ((size_t)offset >= Z_STRLEN_P(str)) {
16141613
/* Extend string if needed */
1614+
zend_long old_len = Z_STRLEN_P(str);
16151615
ZVAL_NEW_STR(str, zend_string_extend(Z_STR_P(str), offset + 1, 0));
16161616
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
16171617
Z_STRVAL_P(str)[offset+1] = 0;
@@ -1633,42 +1633,61 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
16331633
return;
16341634
}
16351635

1636-
/* -1 for the byte we are replacing */
1637-
zend_long new_len = old_len + string_len - 1;
16381636
if ((size_t)offset >= Z_STRLEN_P(str)) {
16391637
/* Extend string */
1638+
zend_long old_len = Z_STRLEN_P(str);
16401639
ZVAL_NEW_STR(str, zend_string_extend(Z_STR_P(str), offset + string_len, 0));
16411640
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
16421641
memcpy(Z_STRVAL_P(str) + offset, string_value, string_len);
16431642
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1644-
ZVAL_STR(EX_VAR(opline->result.var), zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
1643+
ZVAL_INTERNED_STR(EX_VAR(opline->result.var), zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
16451644
}
16461645
return;
1647-
}
1648-
1649-
zend_string *tmp = zend_string_init(Z_STRVAL_P(str), new_len, 0);
1650-
if (string_len > 0) {
1651-
memcpy(ZSTR_VAL(tmp) + offset, string_value, string_len);
1652-
}
1653-
/* Copy after the replacement string, from the position of the initial string after the offset,
1654-
* for the remainder of the initial string (old length - offset) */
1655-
memcpy(ZSTR_VAL(tmp) + offset + string_len, Z_STRVAL_P(str) + offset + 1, old_len - offset);
1656-
1657-
if (!Z_REFCOUNTED_P(str)) {
1658-
ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), new_len, 0));
1646+
} else if (!Z_REFCOUNTED_P(str)) {
1647+
ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
16591648
} else if (Z_REFCOUNT_P(str) > 1) {
16601649
Z_DELREF_P(str);
1661-
ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), new_len, 0));
1650+
ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
16621651
} else {
16631652
zend_string_forget_hash_val(Z_STR_P(str));
16641653
}
1665-
1666-
memcpy(Z_STRVAL_P(str), ZSTR_VAL(tmp), new_len);
1667-
zend_string_release_ex(tmp, 0);
16681654

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));
16691686
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1670-
ZVAL_STR(EX_VAR(opline->result.var), zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
1687+
ZVAL_INTERNED_STR(EX_VAR(opline->result.var), zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
16711688
}
1689+
1690+
efree(buffer);
16721691
}
16731692

16741693
static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *ref)

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,6 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
862862
static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value, zval *result)
863863
{
864864
zend_string *old_str;
865-
zend_long old_len = Z_STRLEN_P(str);
866865
zend_uchar c;
867866
size_t string_len;
868867
zend_long offset;
@@ -896,63 +895,27 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
896895
c = (zend_uchar)Z_STRVAL_P(value)[0];
897896
}
898897

899-
if (offset < 0) { /* Handle negative offset */
900-
offset += (zend_long)Z_STRLEN_P(str);
901-
}
902-
903-
/* If it's a byte char replace byte directly */
904-
if (string_len == 1) {
905-
if ((size_t) offset >= Z_STRLEN_P(str)) {
906-
/* Extend string if needed */
907-
Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
908-
Z_TYPE_INFO_P(str) = IS_STRING_EX;
909-
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
910-
Z_STRVAL_P(str)[offset + 1] = 0;
911-
} else if (!Z_REFCOUNTED_P(str)) {
912-
old_str = Z_STR_P(str);
913-
Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
914-
Z_TYPE_INFO_P(str) = IS_STRING_EX;
915-
zend_string_release(old_str);
916-
} else {
917-
SEPARATE_STRING(str);
918-
zend_string_forget_hash_val(Z_STR_P(str));
919-
}
920-
921-
Z_STRVAL_P(str)[offset] = c;
922-
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");
923901
if (result) {
924-
/* Return the new character */
925-
ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
902+
ZVAL_NULL(result);
926903
}
927904
return;
928905
}
929906

930-
/* -1 for the byte we are replacing */
931-
zend_long new_len = old_len + string_len - 1;
932-
if ((size_t)offset >= Z_STRLEN_P(str)) {
933-
old_str = Z_STR_P(str);
934-
/* Extend string */
935-
ZVAL_NEW_STR(str, zend_string_extend(Z_STR_P(str), offset + string_len, 0));
936-
memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
937-
memcpy(Z_STRVAL_P(str) + offset, ZSTR_VAL(old_str), string_len);
938-
939-
zend_string_release(old_str);
940-
if (result) {
941-
ZVAL_STR(result, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
942-
}
943-
return;
907+
if (offset < 0) { /* Handle negative offset */
908+
offset += (zend_long)Z_STRLEN_P(str);
944909
}
945910

946-
old_str = Z_STR_P(str);
947-
zend_string *tmp = zend_string_init(Z_STRVAL_P(str), new_len, 0);
948-
if (string_len > 0) {
949-
memcpy(ZSTR_VAL(tmp) + offset, ZSTR_VAL(old_str), string_len);
950-
}
951-
/* Copy after the replacement string, from the position of the initial string after the offset,
952-
* for the remainder of the initial string (old length - offset) */
953-
memcpy(ZSTR_VAL(tmp) + offset + string_len, Z_STRVAL_P(str) + offset + 1, old_len - offset);
954-
955-
if (!Z_REFCOUNTED_P(str)) {
911+
if ((size_t)offset >= Z_STRLEN_P(str)) {
912+
/* Extend string if needed */
913+
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;
918+
} else if (!Z_REFCOUNTED_P(str)) {
956919
old_str = Z_STR_P(str);
957920
Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
958921
Z_TYPE_INFO_P(str) = IS_STRING_EX;
@@ -962,11 +925,11 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
962925
zend_string_forget_hash_val(Z_STR_P(str));
963926
}
964927

965-
memcpy(Z_STRVAL_P(str), ZSTR_VAL(tmp), new_len);
966-
zend_string_release_ex(tmp, 0);
928+
Z_STRVAL_P(str)[offset] = c;
967929

968930
if (result) {
969-
ZVAL_STR(result, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
931+
/* Return the new character */
932+
ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
970933
}
971934
}
972935

0 commit comments

Comments
 (0)