1--TEST--
2Check that strings are marked as valid UTF-8
3--EXTENSIONS--
4zend_test
5--FILE--
6<?php
7echo "Empty strings:\n";
8$s = "";
9var_dump(zend_test_is_string_marked_as_valid_utf8($s));
10
11echo "Known strings:\n";
12$s = "c";
13var_dump(zend_test_is_string_marked_as_valid_utf8($s));
14
15echo "Integer cast to string:\n";
16$i = 2563;
17$s = (string) $i;
18var_dump($s);
19var_dump(zend_test_is_string_marked_as_valid_utf8($s));
20
21echo "Float cast to string:\n";
22$f = 26.7;
23$s = (string) $f;
24var_dump($s);
25var_dump(zend_test_is_string_marked_as_valid_utf8($s));
26$f = 2e100;
27$s = (string) $f;
28var_dump($s);
29var_dump(zend_test_is_string_marked_as_valid_utf8($s));
30
31echo "Concatenation known valid UTF-8 strings in variables:\n";
32$s1 = "f";
33$s2 = "o";
34$s = $s1 . $s2;
35var_dump($s);
36var_dump(zend_test_is_string_marked_as_valid_utf8($s));
37
38echo "Multiple concatenation known valid UTF-8 strings in variables:\n";
39$s1 = "f";
40$s2 = "o";
41$s = $s1 . $s2 . $s2;
42var_dump($s);
43var_dump(zend_test_is_string_marked_as_valid_utf8($s));
44
45echo "Concatenation known valid UTF-8 in assignment:\n";
46$s = "f" . "o";
47var_dump($s);
48var_dump(zend_test_is_string_marked_as_valid_utf8($s));
49
50// The "foo" string matches with a "Foo" class which is registered by the zend_test extension.
51// That class name does not have the "valid UTF-8" flag because class names in general
52// don't have to be UTF-8. As the "foo" string here goes through the interning logic,
53// the string gets replaced by the "foo" string from the class, which does
54// not have the "valid UTF-8" flag. We therefore choose a different test case: "fxo".
55// The previous "foo" test case works because it is not interned.
56echo "Multiple concatenation known valid UTF-8 in assignment:\n";
57$s = "f" . "o" . "o";
58var_dump($s);
59var_dump(zend_test_is_string_marked_as_valid_utf8($s));
60$s = "f" . "x" . "o";
61var_dump($s);
62var_dump(zend_test_is_string_marked_as_valid_utf8($s));
63
64echo "Concatenation known valid UTF-8 string with empty string in variables:\n";
65$s1 = "f";
66$s2 = "";
67$s = $s1 . $s2;
68var_dump(zend_test_is_string_marked_as_valid_utf8($s));
69$s1 = "f";
70$s2 = "";
71$s = $s2 . $s1;
72var_dump(zend_test_is_string_marked_as_valid_utf8($s));
73
74echo "Concatenation known valid UTF-8 string with empty string in assignment:\n";
75$s = "f" . "";
76var_dump(zend_test_is_string_marked_as_valid_utf8($s));
77$s = "" . "f";
78var_dump(zend_test_is_string_marked_as_valid_utf8($s));
79
80echo "Concatenation in loop:\n";
81const COPY_TIMES = 10_000;
82$string = "a";
83
84$string_concat = $string;
85for ($i = 1; $i < COPY_TIMES; $i++) {
86    $string_concat = $string_concat . $string;
87}
88var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
89
90echo "Concatenation in loop (compound assignment):\n";
91$string = "a";
92
93$string_concat = $string;
94for ($i = 1; $i < COPY_TIMES; $i++) {
95    $string_concat .= $string;
96}
97var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
98
99echo "Concatenation of objects:\n";
100class ToString {
101    public function __toString() : string{
102        return "z";
103    }
104}
105$o = new ToString();
106$s = $o . $o;
107var_dump($s);
108var_dump(zend_test_is_string_marked_as_valid_utf8($s));
109
110echo "Rope concat:\n";
111$foo = 'f';
112$bar = 'b';
113$baz = 'a';
114$rope = "$foo$bar$baz";
115var_dump(zend_test_is_string_marked_as_valid_utf8($rope));
116
117echo "str_repeat:\n";
118$string = "a";
119$string_concat = str_repeat($string, 100);
120var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
121$string = "\xff";
122$string_concat = str_repeat($string, 100);
123var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
124
125echo "implode:\n";
126$arr = ['a', 'b'];
127$string_concat = implode('', $arr);
128var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
129$string_concat = implode('|', $arr);
130var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
131$string_concat = implode('', ['c', ...$arr]);
132var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
133$string_concat = implode('', [...$arr, 'c']);
134var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
135$string_concat = implode('', ["\xff", ...$arr]);
136var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
137$string_concat = implode('', [...$arr, "\xff"]);
138var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
139$string_concat = implode("\xff", $arr);
140var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
141$string_concat = implode('', []);
142var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
143$string_concat = implode("\xff", []);
144var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
145$string_concat = implode('', ['a']);
146var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
147$string_concat = implode("\xff", ['a']);
148var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
149$string_concat = implode('', [1, 1.0, 'a']);
150var_dump(zend_test_is_string_marked_as_valid_utf8($string_concat));
151
152?>
153--EXPECT--
154Empty strings:
155bool(true)
156Known strings:
157bool(true)
158Integer cast to string:
159string(4) "2563"
160bool(true)
161Float cast to string:
162string(4) "26.7"
163bool(true)
164string(8) "2.0E+100"
165bool(true)
166Concatenation known valid UTF-8 strings in variables:
167string(2) "fo"
168bool(true)
169Multiple concatenation known valid UTF-8 strings in variables:
170string(3) "foo"
171bool(true)
172Concatenation known valid UTF-8 in assignment:
173string(2) "fo"
174bool(true)
175Multiple concatenation known valid UTF-8 in assignment:
176string(3) "foo"
177bool(false)
178string(3) "fxo"
179bool(true)
180Concatenation known valid UTF-8 string with empty string in variables:
181bool(true)
182bool(true)
183Concatenation known valid UTF-8 string with empty string in assignment:
184bool(true)
185bool(true)
186Concatenation in loop:
187bool(true)
188Concatenation in loop (compound assignment):
189bool(true)
190Concatenation of objects:
191string(2) "zz"
192bool(true)
193Rope concat:
194bool(true)
195str_repeat:
196bool(true)
197bool(false)
198implode:
199bool(true)
200bool(true)
201bool(true)
202bool(true)
203bool(false)
204bool(false)
205bool(false)
206bool(true)
207bool(true)
208bool(true)
209bool(true)
210bool(true)
211