Skip to content

Commit d7c351e

Browse files
authored
Propagate UTF-8 flag during Rope operations (php#10915)
1 parent a7f91e3 commit d7c351e

File tree

5 files changed

+50
-14
lines changed

5 files changed

+50
-14
lines changed

Zend/zend_vm_def.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -3330,8 +3330,6 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM)
33303330
zend_string **rope;
33313331
zval *var, *ret;
33323332
uint32_t i;
3333-
size_t len = 0;
3334-
char *target;
33353333

33363334
rope = (zend_string**)EX_VAR(opline->op1.var);
33373335
if (OP2_TYPE == IS_CONST) {
@@ -3364,12 +3362,18 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM)
33643362
}
33653363
}
33663364
}
3365+
3366+
size_t len = 0;
3367+
uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES;
33673368
for (i = 0; i <= opline->extended_value; i++) {
3369+
flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]);
33683370
len += ZSTR_LEN(rope[i]);
33693371
}
33703372
ret = EX_VAR(opline->result.var);
33713373
ZVAL_STR(ret, zend_string_alloc(len, 0));
3372-
target = Z_STRVAL_P(ret);
3374+
GC_ADD_FLAGS(Z_STR_P(ret), flags);
3375+
3376+
char *target = Z_STRVAL_P(ret);
33733377
for (i = 0; i <= opline->extended_value; i++) {
33743378
memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i]));
33753379
target += ZSTR_LEN(rope[i]);

Zend/zend_vm_execute.h

+21-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/opcache/jit/zend_jit_helpers.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -3104,13 +3104,16 @@ static zend_string* ZEND_FASTCALL zend_jit_rope_end(zend_string **rope, uint32_t
31043104
zend_string *ret;
31053105
uint32_t i;
31063106
size_t len = 0;
3107-
char *target;
31083107

3108+
uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES;
31093109
for (i = 0; i <= count; i++) {
3110+
flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]);
31103111
len += ZSTR_LEN(rope[i]);
31113112
}
31123113
ret = zend_string_alloc(len, 0);
3113-
target = ZSTR_VAL(ret);
3114+
GC_ADD_FLAGS(ret, flags);
3115+
3116+
char *target = ZSTR_VAL(ret);
31143117
for (i = 0; i <= count; i++) {
31153118
memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i]));
31163119
target += ZSTR_LEN(rope[i]);

ext/zend_test/tests/strings_marked_as_utf8.phpt

+9
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ $s = $o . $o;
107107
var_dump($s);
108108
var_dump(zend_test_is_string_marked_as_valid_utf8($s));
109109

110+
echo "Rope concat:\n";
111+
$foo = 'f';
112+
$bar = 'b';
113+
$baz = 'a';
114+
$rope = "$foo$bar$baz";
115+
var_dump(zend_test_is_string_marked_as_valid_utf8($rope));
116+
110117
echo "str_repeat:\n";
111118
$string = "a";
112119
$string_concat = str_repeat($string, 100);
@@ -183,6 +190,8 @@ bool(true)
183190
Concatenation of objects:
184191
string(2) "zz"
185192
bool(true)
193+
Rope concat:
194+
bool(true)
186195
str_repeat:
187196
bool(true)
188197
bool(false)

ext/zend_test/tests/strings_not_marked_as_utf8.phpt

+8
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ $s = $o . $o;
102102
$s = $s . $non_utf8;
103103
var_dump(zend_test_is_string_marked_as_valid_utf8($s));
104104

105+
echo "Rope concat:\n";
106+
$foo = 'f';
107+
$bar = "\xc3";
108+
$baz = 'a';
109+
$rope = "$foo$bar$baz";
110+
var_dump(zend_test_is_string_marked_as_valid_utf8($rope));
105111
?>
106112
--EXPECT--
107113
Integer cast to string concatenated to invalid UTF-8:
@@ -129,3 +135,5 @@ Concatenation in loop (compound assignment):
129135
bool(false)
130136
Concatenation of objects:
131137
bool(false)
138+
Rope concat:
139+
bool(false)

0 commit comments

Comments
 (0)