Skip to content

Commit 1c9a8aa

Browse files
committed
Possible fix for JIT
1 parent 34c137c commit 1c9a8aa

File tree

1 file changed

+72
-22
lines changed

1 file changed

+72
-22
lines changed

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -861,8 +861,8 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
861861

862862
static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value, zval *result)
863863
{
864-
zend_string *old_str;
865-
zend_uchar c;
864+
zend_string *old_str
865+
char *string_value;
866866
size_t string_len;
867867
zend_long offset;
868868

@@ -879,42 +879,62 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
879879
if (Z_TYPE_P(value) != IS_STRING) {
880880
/* Convert to string, just the time to pick the 1st byte */
881881
zend_string *tmp = zval_try_get_string_func(value);
882-
883882
if (UNEXPECTED(!tmp)) {
884883
if (result) {
885884
ZVAL_UNDEF(result);
886885
}
887886
return;
888887
}
889888

889+
string_value = ZSTR_VAL(tmp);
890890
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);
893892
} else {
893+
string_value = Z_STRVAL_P(value);
894894
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;
905895
}
906896

907897
if (offset < 0) { /* Handle negative offset */
908898
offset += (zend_long)Z_STRLEN_P(str);
909899
}
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+
}
910927

911928
if ((size_t)offset >= Z_STRLEN_P(str)) {
912929
/* Extend string if needed */
913930
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));
916932
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;
918938
} else if (!Z_REFCOUNTED_P(str)) {
919939
old_str = Z_STR_P(str);
920940
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,
925945
zend_string_forget_hash_val(Z_STR_P(str));
926946
}
927947

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));
930979
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));
933981
}
982+
983+
efree(buffer);
934984
}
935985

936986
static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim, zval *value, zval *result)

0 commit comments

Comments
 (0)