1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Dmitry Stogov <dmitry@php.net> |
18 +----------------------------------------------------------------------+
19 */
20
21 /* If you change this file, please regenerate the zend_vm_execute.h and
22 * zend_vm_opcodes.h files by running:
23 * php zend_vm_gen.php
24 */
25
ZEND_VM_HELPER(zend_add_helper,ANY,ANY,zval * op_1,zval * op_2)26 ZEND_VM_HELPER(zend_add_helper, ANY, ANY, zval *op_1, zval *op_2)
27 {
28 USE_OPLINE
29
30 SAVE_OPLINE();
31 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
32 op_1 = ZVAL_UNDEFINED_OP1();
33 }
34 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
35 op_2 = ZVAL_UNDEFINED_OP2();
36 }
37 add_function(EX_VAR(opline->result.var), op_1, op_2);
38 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
39 zval_ptr_dtor_nogc(op_1);
40 }
41 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
42 zval_ptr_dtor_nogc(op_2);
43 }
44 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
45 }
46
47 ZEND_VM_HOT_NOCONSTCONST_HANDLER(1, ZEND_ADD, CONST|TMPVARCV, CONST|TMPVARCV)
48 {
49 USE_OPLINE
50 zval *op1, *op2, *result;
51 double d1, d2;
52
53 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
54 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
55 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
56 /* pass */
57 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
58 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
59 result = EX_VAR(opline->result.var);
60 fast_long_add_function(result, op1, op2);
61 ZEND_VM_NEXT_OPCODE();
62 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
63 d1 = (double)Z_LVAL_P(op1);
64 d2 = Z_DVAL_P(op2);
65 ZEND_VM_C_GOTO(add_double);
66 }
67 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
68 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
69 d1 = Z_DVAL_P(op1);
70 d2 = Z_DVAL_P(op2);
71 ZEND_VM_C_LABEL(add_double):
72 result = EX_VAR(opline->result.var);
73 ZVAL_DOUBLE(result, d1 + d2);
74 ZEND_VM_NEXT_OPCODE();
75 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
76 d1 = Z_DVAL_P(op1);
77 d2 = (double)Z_LVAL_P(op2);
78 ZEND_VM_C_GOTO(add_double);
79 }
80 }
81
82 ZEND_VM_DISPATCH_TO_HELPER(zend_add_helper, op_1, op1, op_2, op2);
83 }
84
ZEND_VM_HELPER(zend_sub_helper,ANY,ANY,zval * op_1,zval * op_2)85 ZEND_VM_HELPER(zend_sub_helper, ANY, ANY, zval *op_1, zval *op_2)
86 {
87 USE_OPLINE
88
89 SAVE_OPLINE();
90 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
91 op_1 = ZVAL_UNDEFINED_OP1();
92 }
93 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
94 op_2 = ZVAL_UNDEFINED_OP2();
95 }
96 sub_function(EX_VAR(opline->result.var), op_1, op_2);
97 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
98 zval_ptr_dtor_nogc(op_1);
99 }
100 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
101 zval_ptr_dtor_nogc(op_2);
102 }
103 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
104 }
105
106 ZEND_VM_HOT_NOCONSTCONST_HANDLER(2, ZEND_SUB, CONST|TMPVARCV, CONST|TMPVARCV)
107 {
108 USE_OPLINE
109 zval *op1, *op2, *result;
110 double d1, d2;
111
112 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
113 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
114 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
115 /* pass */
116 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
117 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
118 result = EX_VAR(opline->result.var);
119 fast_long_sub_function(result, op1, op2);
120 ZEND_VM_NEXT_OPCODE();
121 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
122 d1 = (double)Z_LVAL_P(op1);
123 d2 = Z_DVAL_P(op2);
124 ZEND_VM_C_GOTO(sub_double);
125 }
126 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
127 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
128 d1 = Z_DVAL_P(op1);
129 d2 = Z_DVAL_P(op2);
130 ZEND_VM_C_LABEL(sub_double):
131 result = EX_VAR(opline->result.var);
132 ZVAL_DOUBLE(result, d1 - d2);
133 ZEND_VM_NEXT_OPCODE();
134 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
135 d1 = Z_DVAL_P(op1);
136 d2 = (double)Z_LVAL_P(op2);
137 ZEND_VM_C_GOTO(sub_double);
138 }
139 }
140
141 ZEND_VM_DISPATCH_TO_HELPER(zend_sub_helper, op_1, op1, op_2, op2);
142 }
143
ZEND_VM_HELPER(zend_mul_helper,ANY,ANY,zval * op_1,zval * op_2)144 ZEND_VM_HELPER(zend_mul_helper, ANY, ANY, zval *op_1, zval *op_2)
145 {
146 USE_OPLINE
147
148 SAVE_OPLINE();
149 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
150 op_1 = ZVAL_UNDEFINED_OP1();
151 }
152 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
153 op_2 = ZVAL_UNDEFINED_OP2();
154 }
155 mul_function(EX_VAR(opline->result.var), op_1, op_2);
156 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
157 zval_ptr_dtor_nogc(op_1);
158 }
159 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
160 zval_ptr_dtor_nogc(op_2);
161 }
162 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
163 }
164
165 ZEND_VM_COLD_CONSTCONST_HANDLER(3, ZEND_MUL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
166 {
167 USE_OPLINE
168 zval *op1, *op2, *result;
169 double d1, d2;
170
171 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
172 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
173 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
174 /* pass */
175 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
176 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
177 zend_long overflow;
178
179 result = EX_VAR(opline->result.var);
180 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
181 Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
182 ZEND_VM_NEXT_OPCODE();
183 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
184 d1 = (double)Z_LVAL_P(op1);
185 d2 = Z_DVAL_P(op2);
186 ZEND_VM_C_GOTO(mul_double);
187 }
188 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
189 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
190 d1 = Z_DVAL_P(op1);
191 d2 = Z_DVAL_P(op2);
192 ZEND_VM_C_LABEL(mul_double):
193 result = EX_VAR(opline->result.var);
194 ZVAL_DOUBLE(result, d1 * d2);
195 ZEND_VM_NEXT_OPCODE();
196 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
197 d1 = Z_DVAL_P(op1);
198 d2 = (double)Z_LVAL_P(op2);
199 ZEND_VM_C_GOTO(mul_double);
200 }
201 }
202
203 ZEND_VM_DISPATCH_TO_HELPER(zend_mul_helper, op_1, op1, op_2, op2);
204 }
205
206 ZEND_VM_COLD_CONSTCONST_HANDLER(4, ZEND_DIV, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
207 {
208 USE_OPLINE
209 zval *op1, *op2;
210
211 SAVE_OPLINE();
212 op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
213 op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
214 div_function(EX_VAR(opline->result.var), op1, op2);
215 FREE_OP1();
216 FREE_OP2();
217 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
218 }
219
ZEND_VM_COLD_HELPER(zend_mod_by_zero_helper,ANY,ANY)220 ZEND_VM_COLD_HELPER(zend_mod_by_zero_helper, ANY, ANY)
221 {
222 USE_OPLINE
223
224 SAVE_OPLINE();
225 zend_throw_exception_ex(zend_ce_division_by_zero_error, 0, "Modulo by zero");
226 ZVAL_UNDEF(EX_VAR(opline->result.var));
227 HANDLE_EXCEPTION();
228 }
229
ZEND_VM_HELPER(zend_mod_helper,ANY,ANY,zval * op_1,zval * op_2)230 ZEND_VM_HELPER(zend_mod_helper, ANY, ANY, zval *op_1, zval *op_2)
231 {
232 USE_OPLINE
233
234 SAVE_OPLINE();
235 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
236 op_1 = ZVAL_UNDEFINED_OP1();
237 }
238 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
239 op_2 = ZVAL_UNDEFINED_OP2();
240 }
241 mod_function(EX_VAR(opline->result.var), op_1, op_2);
242 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
243 zval_ptr_dtor_nogc(op_1);
244 }
245 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
246 zval_ptr_dtor_nogc(op_2);
247 }
248 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
249 }
250
251 ZEND_VM_COLD_CONSTCONST_HANDLER(5, ZEND_MOD, CONST|TMPVARCV, CONST|TMPVARCV)
252 {
253 USE_OPLINE
254 zval *op1, *op2, *result;
255
256 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
257 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
258 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
259 /* pass */
260 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
261 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
262 result = EX_VAR(opline->result.var);
263 if (UNEXPECTED(Z_LVAL_P(op2) == 0)) {
264 ZEND_VM_DISPATCH_TO_HELPER(zend_mod_by_zero_helper);
265 } else if (UNEXPECTED(Z_LVAL_P(op2) == -1)) {
266 /* Prevent overflow error/crash if op1==ZEND_LONG_MIN */
267 ZVAL_LONG(result, 0);
268 } else {
269 ZVAL_LONG(result, Z_LVAL_P(op1) % Z_LVAL_P(op2));
270 }
271 ZEND_VM_NEXT_OPCODE();
272 }
273 }
274
275 ZEND_VM_DISPATCH_TO_HELPER(zend_mod_helper, op_1, op1, op_2, op2);
276 }
277
ZEND_VM_HELPER(zend_shift_left_helper,ANY,ANY,zval * op_1,zval * op_2)278 ZEND_VM_HELPER(zend_shift_left_helper, ANY, ANY, zval *op_1, zval *op_2)
279 {
280 USE_OPLINE
281
282 SAVE_OPLINE();
283 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
284 op_1 = ZVAL_UNDEFINED_OP1();
285 }
286 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
287 op_2 = ZVAL_UNDEFINED_OP2();
288 }
289 shift_left_function(EX_VAR(opline->result.var), op_1, op_2);
290 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
291 zval_ptr_dtor_nogc(op_1);
292 }
293 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
294 zval_ptr_dtor_nogc(op_2);
295 }
296 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
297 }
298
299 ZEND_VM_COLD_CONSTCONST_HANDLER(6, ZEND_SL, CONST|TMPVARCV, CONST|TMPVARCV)
300 {
301 USE_OPLINE
302 zval *op1, *op2;
303
304 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
305 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
306 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
307 /* pass */
308 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
309 && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)
310 && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) {
311 /* Perform shift on unsigned numbers to get well-defined wrap behavior. */
312 ZVAL_LONG(EX_VAR(opline->result.var),
313 (zend_long) ((zend_ulong) Z_LVAL_P(op1) << Z_LVAL_P(op2)));
314 ZEND_VM_NEXT_OPCODE();
315 }
316
317 ZEND_VM_DISPATCH_TO_HELPER(zend_shift_left_helper, op_1, op1, op_2, op2);
318 }
319
ZEND_VM_HELPER(zend_shift_right_helper,ANY,ANY,zval * op_1,zval * op_2)320 ZEND_VM_HELPER(zend_shift_right_helper, ANY, ANY, zval *op_1, zval *op_2)
321 {
322 USE_OPLINE
323
324 SAVE_OPLINE();
325 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
326 op_1 = ZVAL_UNDEFINED_OP1();
327 }
328 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
329 op_2 = ZVAL_UNDEFINED_OP2();
330 }
331 shift_right_function(EX_VAR(opline->result.var), op_1, op_2);
332 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
333 zval_ptr_dtor_nogc(op_1);
334 }
335 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
336 zval_ptr_dtor_nogc(op_2);
337 }
338 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
339 }
340
341 ZEND_VM_COLD_CONSTCONST_HANDLER(7, ZEND_SR, CONST|TMPVARCV, CONST|TMPVARCV)
342 {
343 USE_OPLINE
344 zval *op1, *op2;
345
346 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
347 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
348 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
349 /* pass */
350 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
351 && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)
352 && EXPECTED((zend_ulong)Z_LVAL_P(op2) < SIZEOF_ZEND_LONG * 8)) {
353 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) >> Z_LVAL_P(op2));
354 ZEND_VM_NEXT_OPCODE();
355 }
356
357 ZEND_VM_DISPATCH_TO_HELPER(zend_shift_right_helper, op_1, op1, op_2, op2);
358 }
359
360 ZEND_VM_COLD_CONSTCONST_HANDLER(12, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
361 {
362 USE_OPLINE
363 zval *op1, *op2;
364
365 SAVE_OPLINE();
366 op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
367 op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
368 pow_function(EX_VAR(opline->result.var), op1, op2);
369 FREE_OP1();
370 FREE_OP2();
371 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
372 }
373
374 ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_CONST))
375 {
376 USE_OPLINE
377 zval *op1, *op2;
378
379 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
380 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
381
382 if ((OP1_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
383 (OP2_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
384 zend_string *op1_str = Z_STR_P(op1);
385 zend_string *op2_str = Z_STR_P(op2);
386 zend_string *str;
387 uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str);
388
389 if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) {
390 if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) {
391 ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
392 } else {
393 ZVAL_STR(EX_VAR(opline->result.var), op2_str);
394 }
395 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
396 zend_string_release_ex(op1_str, 0);
397 }
398 } else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) {
399 if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) {
400 ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
401 } else {
402 ZVAL_STR(EX_VAR(opline->result.var), op1_str);
403 }
404 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
405 zend_string_release_ex(op2_str, 0);
406 }
407 } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV &&
408 !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
409 size_t len = ZSTR_LEN(op1_str);
410
411 if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
412 zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
413 }
414 str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
415 memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
416 GC_ADD_FLAGS(str, flags);
417 ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
418 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
419 zend_string_release_ex(op2_str, 0);
420 }
421 } else {
422 str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
423 memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
424 memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
425 GC_ADD_FLAGS(str, flags);
426 ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
427 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
428 zend_string_release_ex(op1_str, 0);
429 }
430 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
431 zend_string_release_ex(op2_str, 0);
432 }
433 }
434 ZEND_VM_NEXT_OPCODE();
435 } else {
436 SAVE_OPLINE();
437
438 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
439 op1 = ZVAL_UNDEFINED_OP1();
440 }
441 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
442 op2 = ZVAL_UNDEFINED_OP2();
443 }
444 concat_function(EX_VAR(opline->result.var), op1, op2);
445 FREE_OP1();
446 FREE_OP2();
447 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
448 }
449 }
450
451 ZEND_VM_COLD_CONSTCONST_HANDLER(16, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
452 {
453 USE_OPLINE
454 zval *op1, *op2;
455 bool result;
456
457 SAVE_OPLINE();
458 op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
459 op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
460 result = fast_is_identical_function(op1, op2);
461 FREE_OP1();
462 FREE_OP2();
463 ZEND_VM_SMART_BRANCH(result, 1);
464 }
465
466 ZEND_VM_HANDLER(196, ZEND_CASE_STRICT, TMP|VAR, CONST|TMP|VAR|CV)
467 {
468 USE_OPLINE
469 zval *op1, *op2;
470 bool result;
471
472 SAVE_OPLINE();
473 op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
474 op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
475 result = fast_is_identical_function(op1, op2);
476 FREE_OP2();
477 ZEND_VM_SMART_BRANCH(result, 1);
478 }
479
480 ZEND_VM_COLD_CONSTCONST_HANDLER(17, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV, SPEC(COMMUTATIVE))
481 {
482 USE_OPLINE
483 zval *op1, *op2;
484 bool result;
485
486 SAVE_OPLINE();
487 op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
488 op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
489 result = fast_is_not_identical_function(op1, op2);
490 FREE_OP1();
491 FREE_OP2();
492 ZEND_VM_SMART_BRANCH(result, 1);
493 }
494
ZEND_VM_HELPER(zend_is_equal_helper,ANY,ANY,zval * op_1,zval * op_2)495 ZEND_VM_HELPER(zend_is_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
496 {
497 int ret;
498 USE_OPLINE
499
500 SAVE_OPLINE();
501 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
502 op_1 = ZVAL_UNDEFINED_OP1();
503 }
504 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
505 op_2 = ZVAL_UNDEFINED_OP2();
506 }
507 ret = zend_compare(op_1, op_2);
508 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
509 zval_ptr_dtor_nogc(op_1);
510 }
511 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
512 zval_ptr_dtor_nogc(op_2);
513 }
514 ZEND_VM_SMART_BRANCH(ret == 0, 1);
515 }
516
517 ZEND_VM_COLD_CONSTCONST_HANDLER(18, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
518 {
519 USE_OPLINE
520 zval *op1, *op2;
521 double d1, d2;
522
523 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
524 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
525 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
526 /* pass */
527 } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
528 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
529 if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) {
530 ZEND_VM_C_LABEL(is_equal_true):
531 ZEND_VM_SMART_BRANCH_TRUE();
532 } else {
533 ZEND_VM_C_LABEL(is_equal_false):
534 ZEND_VM_SMART_BRANCH_FALSE();
535 }
536 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
537 d1 = (double)Z_LVAL_P(op1);
538 d2 = Z_DVAL_P(op2);
539 ZEND_VM_C_GOTO(is_equal_double);
540 }
541 } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
542 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
543 d1 = Z_DVAL_P(op1);
544 d2 = Z_DVAL_P(op2);
545 ZEND_VM_C_LABEL(is_equal_double):
546 if (d1 == d2) {
547 ZEND_VM_C_GOTO(is_equal_true);
548 } else {
549 ZEND_VM_C_GOTO(is_equal_false);
550 }
551 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
552 d1 = Z_DVAL_P(op1);
553 d2 = (double)Z_LVAL_P(op2);
554 ZEND_VM_C_GOTO(is_equal_double);
555 }
556 } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
557 if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
558 bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
559 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
560 zval_ptr_dtor_str(op1);
561 }
562 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
563 zval_ptr_dtor_str(op2);
564 }
565 if (result) {
566 ZEND_VM_C_GOTO(is_equal_true);
567 } else {
568 ZEND_VM_C_GOTO(is_equal_false);
569 }
570 }
571 }
572 ZEND_VM_DISPATCH_TO_HELPER(zend_is_equal_helper, op_1, op1, op_2, op2);
573 }
574
ZEND_VM_HELPER(zend_is_not_equal_helper,ANY,ANY,zval * op_1,zval * op_2)575 ZEND_VM_HELPER(zend_is_not_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
576 {
577 int ret;
578 USE_OPLINE
579
580 SAVE_OPLINE();
581 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
582 op_1 = ZVAL_UNDEFINED_OP1();
583 }
584 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
585 op_2 = ZVAL_UNDEFINED_OP2();
586 }
587 ret = zend_compare(op_1, op_2);
588 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
589 zval_ptr_dtor_nogc(op_1);
590 }
591 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
592 zval_ptr_dtor_nogc(op_2);
593 }
594 ZEND_VM_SMART_BRANCH(ret != 0, 1);
595 }
596
597 ZEND_VM_COLD_CONSTCONST_HANDLER(19, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(SMART_BRANCH,COMMUTATIVE))
598 {
599 USE_OPLINE
600 zval *op1, *op2;
601 double d1, d2;
602
603 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
604 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
605 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
606 /* pass */
607 } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
608 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
609 if (EXPECTED(Z_LVAL_P(op1) != Z_LVAL_P(op2))) {
610 ZEND_VM_C_LABEL(is_not_equal_true):
611 ZEND_VM_SMART_BRANCH_TRUE();
612 } else {
613 ZEND_VM_C_LABEL(is_not_equal_false):
614 ZEND_VM_SMART_BRANCH_FALSE();
615 }
616 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
617 d1 = (double)Z_LVAL_P(op1);
618 d2 = Z_DVAL_P(op2);
619 ZEND_VM_C_GOTO(is_not_equal_double);
620 }
621 } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
622 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
623 d1 = Z_DVAL_P(op1);
624 d2 = Z_DVAL_P(op2);
625 ZEND_VM_C_LABEL(is_not_equal_double):
626 if (d1 != d2) {
627 ZEND_VM_C_GOTO(is_not_equal_true);
628 } else {
629 ZEND_VM_C_GOTO(is_not_equal_false);
630 }
631 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
632 d1 = Z_DVAL_P(op1);
633 d2 = (double)Z_LVAL_P(op2);
634 ZEND_VM_C_GOTO(is_not_equal_double);
635 }
636 } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
637 if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
638 bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
639 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
640 zval_ptr_dtor_str(op1);
641 }
642 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
643 zval_ptr_dtor_str(op2);
644 }
645 if (!result) {
646 ZEND_VM_C_GOTO(is_not_equal_true);
647 } else {
648 ZEND_VM_C_GOTO(is_not_equal_false);
649 }
650 }
651 }
652 ZEND_VM_DISPATCH_TO_HELPER(zend_is_not_equal_helper, op_1, op1, op_2, op2);
653 }
654
ZEND_VM_HELPER(zend_is_smaller_helper,ANY,ANY,zval * op_1,zval * op_2)655 ZEND_VM_HELPER(zend_is_smaller_helper, ANY, ANY, zval *op_1, zval *op_2)
656 {
657 int ret;
658 USE_OPLINE
659
660 SAVE_OPLINE();
661 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
662 op_1 = ZVAL_UNDEFINED_OP1();
663 }
664 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
665 op_2 = ZVAL_UNDEFINED_OP2();
666 }
667 ret = zend_compare(op_1, op_2);
668 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
669 zval_ptr_dtor_nogc(op_1);
670 }
671 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
672 zval_ptr_dtor_nogc(op_2);
673 }
674 ZEND_VM_SMART_BRANCH(ret < 0, 1);
675 }
676
677 ZEND_VM_HOT_NOCONSTCONST_HANDLER(20, ZEND_IS_SMALLER, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH))
678 {
679 USE_OPLINE
680 zval *op1, *op2;
681 double d1, d2;
682
683 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
684 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
685 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
686 /* pass */
687 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
688 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
689 if (EXPECTED(Z_LVAL_P(op1) < Z_LVAL_P(op2))) {
690 ZEND_VM_C_LABEL(is_smaller_true):
691 ZEND_VM_SMART_BRANCH_TRUE();
692 } else {
693 ZEND_VM_C_LABEL(is_smaller_false):
694 ZEND_VM_SMART_BRANCH_FALSE();
695 }
696 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
697 d1 = (double)Z_LVAL_P(op1);
698 d2 = Z_DVAL_P(op2);
699 ZEND_VM_C_GOTO(is_smaller_double);
700 }
701 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
702 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
703 d1 = Z_DVAL_P(op1);
704 d2 = Z_DVAL_P(op2);
705 ZEND_VM_C_LABEL(is_smaller_double):
706 if (d1 < d2) {
707 ZEND_VM_C_GOTO(is_smaller_true);
708 } else {
709 ZEND_VM_C_GOTO(is_smaller_false);
710 }
711 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
712 d1 = Z_DVAL_P(op1);
713 d2 = (double)Z_LVAL_P(op2);
714 ZEND_VM_C_GOTO(is_smaller_double);
715 }
716 }
717 ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_helper, op_1, op1, op_2, op2);
718 }
719
ZEND_VM_HELPER(zend_is_smaller_or_equal_helper,ANY,ANY,zval * op_1,zval * op_2)720 ZEND_VM_HELPER(zend_is_smaller_or_equal_helper, ANY, ANY, zval *op_1, zval *op_2)
721 {
722 int ret;
723 USE_OPLINE
724
725 SAVE_OPLINE();
726 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
727 op_1 = ZVAL_UNDEFINED_OP1();
728 }
729 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
730 op_2 = ZVAL_UNDEFINED_OP2();
731 }
732 ret = zend_compare(op_1, op_2);
733 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
734 zval_ptr_dtor_nogc(op_1);
735 }
736 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
737 zval_ptr_dtor_nogc(op_2);
738 }
739 ZEND_VM_SMART_BRANCH(ret <= 0, 1);
740 }
741
742 ZEND_VM_HOT_NOCONSTCONST_HANDLER(21, ZEND_IS_SMALLER_OR_EQUAL, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH))
743 {
744 USE_OPLINE
745 zval *op1, *op2;
746 double d1, d2;
747
748 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
749 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
750 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
751 /* pass */
752 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
753 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
754 if (EXPECTED(Z_LVAL_P(op1) <= Z_LVAL_P(op2))) {
755 ZEND_VM_C_LABEL(is_smaller_or_equal_true):
756 ZEND_VM_SMART_BRANCH_TRUE();
757 ZVAL_TRUE(EX_VAR(opline->result.var));
758 ZEND_VM_NEXT_OPCODE();
759 } else {
760 ZEND_VM_C_LABEL(is_smaller_or_equal_false):
761 ZEND_VM_SMART_BRANCH_FALSE();
762 ZVAL_FALSE(EX_VAR(opline->result.var));
763 ZEND_VM_NEXT_OPCODE();
764 }
765 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
766 d1 = (double)Z_LVAL_P(op1);
767 d2 = Z_DVAL_P(op2);
768 ZEND_VM_C_GOTO(is_smaller_or_equal_double);
769 }
770 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
771 if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
772 d1 = Z_DVAL_P(op1);
773 d2 = Z_DVAL_P(op2);
774 ZEND_VM_C_LABEL(is_smaller_or_equal_double):
775 if (d1 <= d2) {
776 ZEND_VM_C_GOTO(is_smaller_or_equal_true);
777 } else {
778 ZEND_VM_C_GOTO(is_smaller_or_equal_false);
779 }
780 } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
781 d1 = Z_DVAL_P(op1);
782 d2 = (double)Z_LVAL_P(op2);
783 ZEND_VM_C_GOTO(is_smaller_or_equal_double);
784 }
785 }
786 ZEND_VM_DISPATCH_TO_HELPER(zend_is_smaller_or_equal_helper, op_1, op1, op_2, op2);
787 }
788
789 ZEND_VM_COLD_CONSTCONST_HANDLER(170, ZEND_SPACESHIP, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
790 {
791 USE_OPLINE
792 zval *op1, *op2;
793
794 SAVE_OPLINE();
795 op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
796 op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
797 compare_function(EX_VAR(opline->result.var), op1, op2);
798 FREE_OP1();
799 FREE_OP2();
800 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
801 }
802
ZEND_VM_HELPER(zend_bw_or_helper,ANY,ANY,zval * op_1,zval * op_2)803 ZEND_VM_HELPER(zend_bw_or_helper, ANY, ANY, zval *op_1, zval *op_2)
804 {
805 USE_OPLINE
806
807 SAVE_OPLINE();
808 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
809 op_1 = ZVAL_UNDEFINED_OP1();
810 }
811 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
812 op_2 = ZVAL_UNDEFINED_OP2();
813 }
814 bitwise_or_function(EX_VAR(opline->result.var), op_1, op_2);
815 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
816 zval_ptr_dtor_nogc(op_1);
817 }
818 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
819 zval_ptr_dtor_nogc(op_2);
820 }
821 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
822 }
823
824 ZEND_VM_HOT_NOCONSTCONST_HANDLER(9, ZEND_BW_OR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
825 {
826 USE_OPLINE
827 zval *op1, *op2;
828
829 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
830 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
831 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
832 /* pass */
833 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
834 && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
835 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) | Z_LVAL_P(op2));
836 ZEND_VM_NEXT_OPCODE();
837 }
838
839 ZEND_VM_DISPATCH_TO_HELPER(zend_bw_or_helper, op_1, op1, op_2, op2);
840 }
841
ZEND_VM_HELPER(zend_bw_and_helper,ANY,ANY,zval * op_1,zval * op_2)842 ZEND_VM_HELPER(zend_bw_and_helper, ANY, ANY, zval *op_1, zval *op_2)
843 {
844 USE_OPLINE
845
846 SAVE_OPLINE();
847 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
848 op_1 = ZVAL_UNDEFINED_OP1();
849 }
850 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
851 op_2 = ZVAL_UNDEFINED_OP2();
852 }
853 bitwise_and_function(EX_VAR(opline->result.var), op_1, op_2);
854 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
855 zval_ptr_dtor_nogc(op_1);
856 }
857 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
858 zval_ptr_dtor_nogc(op_2);
859 }
860 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
861 }
862
863 ZEND_VM_HOT_NOCONSTCONST_HANDLER(10, ZEND_BW_AND, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
864 {
865 USE_OPLINE
866 zval *op1, *op2;
867
868 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
869 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
870 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
871 /* pass */
872 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
873 && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
874 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) & Z_LVAL_P(op2));
875 ZEND_VM_NEXT_OPCODE();
876 }
877
878 ZEND_VM_DISPATCH_TO_HELPER(zend_bw_and_helper, op_1, op1, op_2, op2);
879 }
880
ZEND_VM_HELPER(zend_bw_xor_helper,ANY,ANY,zval * op_1,zval * op_2)881 ZEND_VM_HELPER(zend_bw_xor_helper, ANY, ANY, zval *op_1, zval *op_2)
882 {
883 USE_OPLINE
884
885 SAVE_OPLINE();
886 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
887 op_1 = ZVAL_UNDEFINED_OP1();
888 }
889 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
890 op_2 = ZVAL_UNDEFINED_OP2();
891 }
892 bitwise_xor_function(EX_VAR(opline->result.var), op_1, op_2);
893 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
894 zval_ptr_dtor_nogc(op_1);
895 }
896 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
897 zval_ptr_dtor_nogc(op_2);
898 }
899 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
900 }
901
902 ZEND_VM_HOT_NOCONSTCONST_HANDLER(11, ZEND_BW_XOR, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(COMMUTATIVE))
903 {
904 USE_OPLINE
905 zval *op1, *op2;
906
907 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
908 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
909 if (ZEND_VM_SPEC && OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
910 /* pass */
911 } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)
912 && EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
913 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(op1) ^ Z_LVAL_P(op2));
914 ZEND_VM_NEXT_OPCODE();
915 }
916
917 ZEND_VM_DISPATCH_TO_HELPER(zend_bw_xor_helper, op_1, op1, op_2, op2);
918 }
919
920 ZEND_VM_COLD_CONSTCONST_HANDLER(15, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(COMMUTATIVE))
921 {
922 USE_OPLINE
923 zval *op1, *op2;
924
925 SAVE_OPLINE();
926 op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
927 op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
928 boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
929 FREE_OP1();
930 FREE_OP2();
931 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
932 }
933
ZEND_VM_HELPER(zend_bw_not_helper,ANY,ANY,zval * op_1)934 ZEND_VM_HELPER(zend_bw_not_helper, ANY, ANY, zval *op_1)
935 {
936 USE_OPLINE
937
938 SAVE_OPLINE();
939 if (UNEXPECTED(Z_TYPE_P(op_1) == IS_UNDEF)) {
940 op_1 = ZVAL_UNDEFINED_OP1();
941 }
942 bitwise_not_function(EX_VAR(opline->result.var), op_1);
943 FREE_OP1();
944 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
945 }
946
947 ZEND_VM_HOT_NOCONST_HANDLER(13, ZEND_BW_NOT, CONST|TMPVARCV, ANY)
948 {
949 USE_OPLINE
950 zval *op1;
951
952 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
953 if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
954 ZVAL_LONG(EX_VAR(opline->result.var), ~Z_LVAL_P(op1));
955 ZEND_VM_NEXT_OPCODE();
956 }
957
958 ZEND_VM_DISPATCH_TO_HELPER(zend_bw_not_helper, op_1, op1);
959 }
960
961 ZEND_VM_COLD_CONST_HANDLER(14, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
962 {
963 USE_OPLINE
964 zval *val;
965
966 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
967 if (Z_TYPE_INFO_P(val) == IS_TRUE) {
968 ZVAL_FALSE(EX_VAR(opline->result.var));
969 } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
970 /* The result and op1 can be the same cv zval */
971 const uint32_t orig_val_type = Z_TYPE_INFO_P(val);
972 ZVAL_TRUE(EX_VAR(opline->result.var));
973 if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) {
974 SAVE_OPLINE();
975 ZVAL_UNDEFINED_OP1();
976 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
977 }
978 } else {
979 SAVE_OPLINE();
980 ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val));
981 FREE_OP1();
982 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
983 }
984 ZEND_VM_NEXT_OPCODE();
985 }
986
ZEND_VM_COLD_HELPER(zend_this_not_in_object_context_helper,ANY,ANY)987 ZEND_VM_COLD_HELPER(zend_this_not_in_object_context_helper, ANY, ANY)
988 {
989 USE_OPLINE
990
991 SAVE_OPLINE();
992 zend_throw_error(NULL, "Using $this when not in object context");
993 UNDEF_RESULT();
994 HANDLE_EXCEPTION();
995 }
996
ZEND_VM_COLD_HELPER(zend_undefined_function_helper,ANY,ANY)997 ZEND_VM_COLD_HELPER(zend_undefined_function_helper, ANY, ANY)
998 {
999 USE_OPLINE
1000 zval *function_name;
1001
1002 SAVE_OPLINE();
1003 function_name = RT_CONSTANT(opline, opline->op2);
1004 zend_throw_error(NULL, "Call to undefined function %s()", Z_STRVAL_P(function_name));
1005 HANDLE_EXCEPTION();
1006 }
1007
1008 ZEND_VM_HANDLER(28, ZEND_ASSIGN_OBJ_OP, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, OP)
1009 {
1010 USE_OPLINE
1011 zval *object;
1012 zval *property;
1013 zval *value;
1014 zval *zptr;
1015 void *_cache_slot[3] = {0};
1016 void **cache_slot;
1017 zend_property_info *prop_info;
1018 zend_object *zobj;
1019 zend_string *name, *tmp_name;
1020
1021 SAVE_OPLINE();
1022 object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1023 property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1024
1025 do {
1026 value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
1027
1028 if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
1029 if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
1030 object = Z_REFVAL_P(object);
1031 ZEND_VM_C_GOTO(assign_op_object);
1032 }
1033 if (OP1_TYPE == IS_CV
1034 && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
1035 ZVAL_UNDEFINED_OP1();
1036 }
1037 zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC);
1038 break;
1039 }
1040
1041 ZEND_VM_C_LABEL(assign_op_object):
1042 /* here we are sure we are dealing with an object */
1043 zobj = Z_OBJ_P(object);
1044 if (OP2_TYPE == IS_CONST) {
1045 name = Z_STR_P(property);
1046 } else {
1047 name = zval_try_get_tmp_string(property, &tmp_name);
1048 if (UNEXPECTED(!name)) {
1049 UNDEF_RESULT();
1050 break;
1051 }
1052 }
1053 cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR((opline+1)->extended_value) : _cache_slot;
1054 if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) {
1055 if (UNEXPECTED(Z_ISERROR_P(zptr))) {
1056 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1057 ZVAL_NULL(EX_VAR(opline->result.var));
1058 }
1059 } else {
1060 zend_reference *ref;
1061
1062 do {
1063 if (UNEXPECTED(Z_ISREF_P(zptr))) {
1064 ref = Z_REF_P(zptr);
1065 zptr = Z_REFVAL_P(zptr);
1066 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1067 zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC);
1068 break;
1069 }
1070 }
1071
1072 prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
1073 if (prop_info) {
1074 /* special case for typed properties */
1075 zend_binary_assign_op_typed_prop(prop_info, zptr, value OPLINE_CC EXECUTE_DATA_CC);
1076 } else {
1077 zend_binary_op(zptr, zptr, value OPLINE_CC);
1078 }
1079 } while (0);
1080
1081 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1082 ZVAL_COPY(EX_VAR(opline->result.var), zptr);
1083 }
1084 }
1085 } else {
1086 zend_assign_op_overloaded_property(zobj, name, cache_slot, value OPLINE_CC EXECUTE_DATA_CC);
1087 }
1088 if (OP2_TYPE != IS_CONST) {
1089 zend_tmp_string_release(tmp_name);
1090 }
1091 } while (0);
1092
1093 FREE_OP_DATA();
1094 FREE_OP2();
1095 FREE_OP1();
1096 /* assign_obj has two opcodes! */
1097 ZEND_VM_NEXT_OPCODE_EX(1, 2);
1098 }
1099
1100 /* No specialization for op_types (CONST|TMP|VAR|CV, UNUSED|CONST|TMPVAR) */
1101 ZEND_VM_HANDLER(29, ZEND_ASSIGN_STATIC_PROP_OP, ANY, ANY, OP)
1102 {
1103 /* This helper actually never will receive IS_VAR as second op, and has the same handling for VAR and TMP in the first op, but for interoperability with the other binary_assign_op helpers, it is necessary to "include" it */
1104
1105 USE_OPLINE
1106 zval *prop, *value;
1107 zend_property_info *prop_info;
1108 zend_reference *ref;
1109
1110 SAVE_OPLINE();
1111
1112 if (UNEXPECTED(zend_fetch_static_property_address(&prop, &prop_info, (opline+1)->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) {
1113 UNDEF_RESULT();
1114 FREE_OP_DATA();
1115 HANDLE_EXCEPTION();
1116 }
1117
1118 value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
1119
1120 do {
1121 if (UNEXPECTED(Z_ISREF_P(prop))) {
1122 ref = Z_REF_P(prop);
1123 prop = Z_REFVAL_P(prop);
1124 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1125 zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC);
1126 break;
1127 }
1128 }
1129
1130 if (ZEND_TYPE_IS_SET(prop_info->type)) {
1131 /* special case for typed properties */
1132 zend_binary_assign_op_typed_prop(prop_info, prop, value OPLINE_CC EXECUTE_DATA_CC);
1133 } else {
1134 zend_binary_op(prop, prop, value OPLINE_CC);
1135 }
1136 } while (0);
1137
1138 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1139 ZVAL_COPY(EX_VAR(opline->result.var), prop);
1140 }
1141
1142 FREE_OP_DATA();
1143 /* assign_static_prop has two opcodes! */
1144 ZEND_VM_NEXT_OPCODE_EX(1, 2);
1145 }
1146
1147 ZEND_VM_HANDLER(27, ZEND_ASSIGN_DIM_OP, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, OP)
1148 {
1149 USE_OPLINE
1150 zval *var_ptr;
1151 zval *value, *container, *dim;
1152 HashTable *ht;
1153
1154 SAVE_OPLINE();
1155 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1156
1157 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1158 ZEND_VM_C_LABEL(assign_dim_op_array):
1159 SEPARATE_ARRAY(container);
1160 ht = Z_ARRVAL_P(container);
1161 ZEND_VM_C_LABEL(assign_dim_op_new_array):
1162 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
1163 if (OP2_TYPE == IS_UNUSED) {
1164 var_ptr = zend_hash_next_index_insert(ht, &EG(uninitialized_zval));
1165 if (UNEXPECTED(!var_ptr)) {
1166 zend_cannot_add_element();
1167 ZEND_VM_C_GOTO(assign_dim_op_ret_null);
1168 }
1169 } else {
1170 if (OP2_TYPE == IS_CONST) {
1171 var_ptr = zend_fetch_dimension_address_inner_RW_CONST(ht, dim EXECUTE_DATA_CC);
1172 } else {
1173 var_ptr = zend_fetch_dimension_address_inner_RW(ht, dim EXECUTE_DATA_CC);
1174 }
1175 if (UNEXPECTED(!var_ptr)) {
1176 ZEND_VM_C_GOTO(assign_dim_op_ret_null);
1177 }
1178 }
1179
1180 value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
1181
1182 do {
1183 if (OP2_TYPE != IS_UNUSED && UNEXPECTED(Z_ISREF_P(var_ptr))) {
1184 zend_reference *ref = Z_REF_P(var_ptr);
1185 var_ptr = Z_REFVAL_P(var_ptr);
1186 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1187 zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC);
1188 break;
1189 }
1190 }
1191 zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
1192 } while (0);
1193
1194 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1195 ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
1196 }
1197 FREE_OP((opline+1)->op1_type, (opline+1)->op1.var);
1198 } else {
1199 if (EXPECTED(Z_ISREF_P(container))) {
1200 container = Z_REFVAL_P(container);
1201 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1202 ZEND_VM_C_GOTO(assign_dim_op_array);
1203 }
1204 }
1205
1206 if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1207 zend_object *obj = Z_OBJ_P(container);
1208
1209 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
1210 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
1211 dim++;
1212 }
1213 zend_binary_assign_op_obj_dim(obj, dim OPLINE_CC EXECUTE_DATA_CC);
1214 } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
1215 uint8_t old_type;
1216
1217 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
1218 ZVAL_UNDEFINED_OP1();
1219 }
1220 ht = zend_new_array(8);
1221 old_type = Z_TYPE_P(container);
1222 ZVAL_ARR(container, ht);
1223 if (UNEXPECTED(old_type == IS_FALSE)) {
1224 GC_ADDREF(ht);
1225 zend_false_to_array_deprecated();
1226 if (UNEXPECTED(GC_DELREF(ht) == 0)) {
1227 zend_array_destroy(ht);
1228 ZEND_VM_C_GOTO(assign_dim_op_ret_null);
1229 }
1230 }
1231 ZEND_VM_C_GOTO(assign_dim_op_new_array);
1232 } else {
1233 dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
1234 zend_binary_assign_op_dim_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
1235 ZEND_VM_C_LABEL(assign_dim_op_ret_null):
1236 FREE_OP_DATA();
1237 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1238 ZVAL_NULL(EX_VAR(opline->result.var));
1239 }
1240 }
1241 }
1242
1243 FREE_OP2();
1244 FREE_OP1();
1245 ZEND_VM_NEXT_OPCODE_EX(1, 2);
1246 }
1247
1248 ZEND_VM_HANDLER(26, ZEND_ASSIGN_OP, VAR|CV, CONST|TMPVAR|CV, OP)
1249 {
1250 USE_OPLINE
1251 zval *var_ptr;
1252 zval *value;
1253
1254 SAVE_OPLINE();
1255 value = GET_OP2_ZVAL_PTR(BP_VAR_R);
1256 var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
1257
1258 do {
1259 if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
1260 zend_reference *ref = Z_REF_P(var_ptr);
1261 var_ptr = Z_REFVAL_P(var_ptr);
1262 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1263 zend_binary_assign_op_typed_ref(ref, value OPLINE_CC EXECUTE_DATA_CC);
1264 break;
1265 }
1266 }
1267 zend_binary_op(var_ptr, var_ptr, value OPLINE_CC);
1268 } while (0);
1269
1270 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1271 ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
1272 }
1273
1274 FREE_OP2();
1275 FREE_OP1();
1276 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1277 }
1278
1279 ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
1280 {
1281 USE_OPLINE
1282 zval *object;
1283 zval *property;
1284 zval *zptr;
1285 void *_cache_slot[3] = {0};
1286 void **cache_slot;
1287 zend_property_info *prop_info;
1288 zend_object *zobj;
1289 zend_string *name, *tmp_name;
1290
1291 SAVE_OPLINE();
1292 object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1293 property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1294
1295 do {
1296 if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
1297 if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
1298 object = Z_REFVAL_P(object);
1299 ZEND_VM_C_GOTO(pre_incdec_object);
1300 }
1301 if (OP1_TYPE == IS_CV
1302 && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
1303 ZVAL_UNDEFINED_OP1();
1304 }
1305 zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC);
1306 break;
1307 }
1308
1309 ZEND_VM_C_LABEL(pre_incdec_object):
1310 /* here we are sure we are dealing with an object */
1311 zobj = Z_OBJ_P(object);
1312 if (OP2_TYPE == IS_CONST) {
1313 name = Z_STR_P(property);
1314 } else {
1315 name = zval_try_get_tmp_string(property, &tmp_name);
1316 if (UNEXPECTED(!name)) {
1317 UNDEF_RESULT();
1318 break;
1319 }
1320 }
1321 cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot;
1322 if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) {
1323 if (UNEXPECTED(Z_ISERROR_P(zptr))) {
1324 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1325 ZVAL_NULL(EX_VAR(opline->result.var));
1326 }
1327 } else {
1328 prop_info = (zend_property_info *) CACHED_PTR_EX(cache_slot + 2);
1329 zend_pre_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
1330 }
1331 } else {
1332 zend_pre_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
1333 }
1334 if (OP2_TYPE != IS_CONST) {
1335 zend_tmp_string_release(tmp_name);
1336 }
1337 } while (0);
1338
1339 FREE_OP2();
1340 FREE_OP1();
1341 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1342 }
1343
1344 ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
1345 {
1346 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_PRE_INC_OBJ);
1347 }
1348
1349 ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
1350 {
1351 USE_OPLINE
1352 zval *object;
1353 zval *property;
1354 zval *zptr;
1355 void *_cache_slot[3] = {0};
1356 void **cache_slot;
1357 zend_property_info *prop_info;
1358 zend_object *zobj;
1359 zend_string *name, *tmp_name;
1360
1361 SAVE_OPLINE();
1362 object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1363 property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1364
1365 do {
1366 if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
1367 if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
1368 object = Z_REFVAL_P(object);
1369 ZEND_VM_C_GOTO(post_incdec_object);
1370 }
1371 if (OP1_TYPE == IS_CV
1372 && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
1373 ZVAL_UNDEFINED_OP1();
1374 }
1375 zend_throw_non_object_error(object, property OPLINE_CC EXECUTE_DATA_CC);
1376 break;
1377 }
1378
1379 ZEND_VM_C_LABEL(post_incdec_object):
1380 /* here we are sure we are dealing with an object */
1381 zobj = Z_OBJ_P(object);
1382 if (OP2_TYPE == IS_CONST) {
1383 name = Z_STR_P(property);
1384 } else {
1385 name = zval_try_get_tmp_string(property, &tmp_name);
1386 if (UNEXPECTED(!name)) {
1387 ZVAL_UNDEF(EX_VAR(opline->result.var));
1388 break;
1389 }
1390 }
1391 cache_slot = (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : _cache_slot;
1392 if (EXPECTED((zptr = zobj->handlers->get_property_ptr_ptr(zobj, name, BP_VAR_RW, cache_slot)) != NULL)) {
1393 if (UNEXPECTED(Z_ISERROR_P(zptr))) {
1394 ZVAL_NULL(EX_VAR(opline->result.var));
1395 } else {
1396 prop_info = (zend_property_info*)CACHED_PTR_EX(cache_slot + 2);
1397 zend_post_incdec_property_zval(zptr, prop_info OPLINE_CC EXECUTE_DATA_CC);
1398 }
1399 } else {
1400 zend_post_incdec_overloaded_property(zobj, name, cache_slot OPLINE_CC EXECUTE_DATA_CC);
1401 }
1402 if (OP2_TYPE != IS_CONST) {
1403 zend_tmp_string_release(tmp_name);
1404 }
1405 } while (0);
1406
1407 FREE_OP2();
1408 FREE_OP1();
1409 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1410 }
1411
1412 ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
1413 {
1414 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_POST_INC_OBJ);
1415 }
1416
1417 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
1418 ZEND_VM_HANDLER(38, ZEND_PRE_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
1419 {
1420 USE_OPLINE
1421 zval *prop;
1422 zend_property_info *prop_info;
1423
1424 SAVE_OPLINE();
1425
1426 if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
1427 UNDEF_RESULT();
1428 HANDLE_EXCEPTION();
1429 }
1430
1431 zend_pre_incdec_property_zval(prop,
1432 ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
1433
1434 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1435 }
1436
1437 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
1438 ZEND_VM_HANDLER(39, ZEND_PRE_DEC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
1439 {
1440 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_PRE_INC_STATIC_PROP);
1441 }
1442
1443 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
1444 ZEND_VM_HANDLER(40, ZEND_POST_INC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
1445 {
1446 USE_OPLINE
1447 zval *prop;
1448 zend_property_info *prop_info;
1449
1450 SAVE_OPLINE();
1451
1452 if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
1453 UNDEF_RESULT();
1454 HANDLE_EXCEPTION();
1455 }
1456
1457 zend_post_incdec_property_zval(prop,
1458 ZEND_TYPE_IS_SET(prop_info->type) ? prop_info : NULL OPLINE_CC EXECUTE_DATA_CC);
1459
1460 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1461 }
1462
1463 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
1464 ZEND_VM_HANDLER(41, ZEND_POST_DEC_STATIC_PROP, ANY, ANY, CACHE_SLOT)
1465 {
1466 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_POST_INC_STATIC_PROP);
1467 }
1468
1469 ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY)
1470 {
1471 USE_OPLINE
1472 zval *var_ptr;
1473
1474 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1475
1476 SAVE_OPLINE();
1477 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1478 ZVAL_UNDEFINED_OP1();
1479 ZVAL_NULL(var_ptr);
1480 }
1481
1482 do {
1483 if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
1484 zend_reference *ref = Z_REF_P(var_ptr);
1485 var_ptr = Z_REFVAL_P(var_ptr);
1486 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1487 zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC);
1488 break;
1489 }
1490 }
1491 increment_function(var_ptr);
1492 } while (0);
1493
1494 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1495 ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
1496 }
1497
1498 FREE_OP1();
1499 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1500 }
1501
1502 ZEND_VM_HOT_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL))
1503 {
1504 USE_OPLINE
1505 zval *var_ptr;
1506
1507 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1508
1509 if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
1510 fast_long_increment_function(var_ptr);
1511 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1512 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
1513 }
1514 ZEND_VM_NEXT_OPCODE();
1515 }
1516
1517 ZEND_VM_DISPATCH_TO_HELPER(zend_pre_inc_helper);
1518 }
1519
1520 ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY)
1521 {
1522 USE_OPLINE
1523 zval *var_ptr;
1524
1525 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1526
1527 SAVE_OPLINE();
1528 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1529 ZVAL_UNDEFINED_OP1();
1530 ZVAL_NULL(var_ptr);
1531 }
1532
1533 do {
1534 if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
1535 zend_reference *ref = Z_REF_P(var_ptr);
1536 var_ptr = Z_REFVAL_P(var_ptr);
1537
1538 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1539 zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC);
1540 break;
1541 }
1542 }
1543 decrement_function(var_ptr);
1544 } while (0);
1545
1546 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1547 ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
1548 }
1549
1550 FREE_OP1();
1551 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1552 }
1553
1554 ZEND_VM_HOT_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL))
1555 {
1556 USE_OPLINE
1557 zval *var_ptr;
1558
1559 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1560
1561 if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
1562 fast_long_decrement_function(var_ptr);
1563 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1564 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
1565 }
1566 ZEND_VM_NEXT_OPCODE();
1567 }
1568
1569 ZEND_VM_DISPATCH_TO_HELPER(zend_pre_dec_helper);
1570 }
1571
1572 ZEND_VM_HELPER(zend_post_inc_helper, VAR|CV, ANY)
1573 {
1574 USE_OPLINE
1575 zval *var_ptr;
1576
1577 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1578
1579 SAVE_OPLINE();
1580 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1581 ZVAL_UNDEFINED_OP1();
1582 ZVAL_NULL(var_ptr);
1583 }
1584
1585 do {
1586 if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
1587 zend_reference *ref = Z_REF_P(var_ptr);
1588 var_ptr = Z_REFVAL_P(var_ptr);
1589
1590 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1591 zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
1592 break;
1593 }
1594 }
1595 ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
1596
1597 increment_function(var_ptr);
1598 } while (0);
1599
1600 FREE_OP1();
1601 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1602 }
1603
1604 ZEND_VM_HOT_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
1605 {
1606 USE_OPLINE
1607 zval *var_ptr;
1608
1609 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1610
1611 if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
1612 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
1613 fast_long_increment_function(var_ptr);
1614 ZEND_VM_NEXT_OPCODE();
1615 }
1616
1617 ZEND_VM_DISPATCH_TO_HELPER(zend_post_inc_helper);
1618 }
1619
1620 ZEND_VM_HELPER(zend_post_dec_helper, VAR|CV, ANY)
1621 {
1622 USE_OPLINE
1623 zval *var_ptr;
1624
1625 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1626
1627 SAVE_OPLINE();
1628 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) {
1629 ZVAL_UNDEFINED_OP1();
1630 ZVAL_NULL(var_ptr);
1631 }
1632
1633 do {
1634 if (UNEXPECTED(Z_TYPE_P(var_ptr) == IS_REFERENCE)) {
1635 zend_reference *ref = Z_REF_P(var_ptr);
1636 var_ptr = Z_REFVAL_P(var_ptr);
1637
1638 if (UNEXPECTED(ZEND_REF_HAS_TYPE_SOURCES(ref))) {
1639 zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
1640 break;
1641 }
1642 }
1643 ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
1644
1645 decrement_function(var_ptr);
1646 } while (0);
1647
1648 FREE_OP1();
1649 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1650 }
1651
1652 ZEND_VM_HOT_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
1653 {
1654 USE_OPLINE
1655 zval *var_ptr;
1656
1657 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1658
1659 if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
1660 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
1661 fast_long_decrement_function(var_ptr);
1662 ZEND_VM_NEXT_OPCODE();
1663 }
1664
1665 ZEND_VM_DISPATCH_TO_HELPER(zend_post_dec_helper);
1666 }
1667
1668 ZEND_VM_HANDLER(136, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
1669 {
1670 USE_OPLINE
1671 zval *z;
1672
1673 SAVE_OPLINE();
1674 z = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
1675
1676 if (Z_TYPE_P(z) == IS_STRING) {
1677 zend_string *str = Z_STR_P(z);
1678
1679 if (ZSTR_LEN(str) != 0) {
1680 zend_write(ZSTR_VAL(str), ZSTR_LEN(str));
1681 }
1682 } else {
1683 zend_string *str = zval_get_string_func(z);
1684
1685 if (ZSTR_LEN(str) != 0) {
1686 zend_write(ZSTR_VAL(str), ZSTR_LEN(str));
1687 } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) {
1688 ZVAL_UNDEFINED_OP1();
1689 }
1690 zend_string_release_ex(str, 0);
1691 }
1692
1693 FREE_OP1();
1694 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1695 }
1696
1697 ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
1698 {
1699 USE_OPLINE
1700 zval *varname;
1701 zval *retval;
1702 zend_string *name, *tmp_name;
1703 HashTable *target_symbol_table;
1704
1705 SAVE_OPLINE();
1706 varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
1707
1708 if (OP1_TYPE == IS_CONST) {
1709 name = Z_STR_P(varname);
1710 } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
1711 name = Z_STR_P(varname);
1712 tmp_name = NULL;
1713 } else {
1714 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
1715 ZVAL_UNDEFINED_OP1();
1716 }
1717 name = zval_try_get_tmp_string(varname, &tmp_name);
1718 if (UNEXPECTED(!name)) {
1719 if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) {
1720 FREE_OP1();
1721 }
1722 ZVAL_UNDEF(EX_VAR(opline->result.var));
1723 HANDLE_EXCEPTION();
1724 }
1725 }
1726
1727 target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
1728 retval = zend_hash_find_ex(target_symbol_table, name, OP1_TYPE == IS_CONST);
1729 if (retval == NULL) {
1730 if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
1731 ZEND_VM_C_LABEL(fetch_this):
1732 zend_fetch_this_var(type OPLINE_CC EXECUTE_DATA_CC);
1733 if (OP1_TYPE != IS_CONST) {
1734 zend_tmp_string_release(tmp_name);
1735 }
1736 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1737 }
1738 if (type == BP_VAR_W) {
1739 retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
1740 } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) {
1741 retval = &EG(uninitialized_zval);
1742 } else {
1743 if (OP1_TYPE == IS_CV) {
1744 /* Keep name alive in case an error handler tries to free it. */
1745 zend_string_addref(name);
1746 }
1747 zend_error_unchecked(E_WARNING, "Undefined %svariable $%S",
1748 (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name);
1749 if (type == BP_VAR_RW && !EG(exception)) {
1750 retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
1751 } else {
1752 retval = &EG(uninitialized_zval);
1753 }
1754 if (OP1_TYPE == IS_CV) {
1755 zend_string_release(name);
1756 }
1757 }
1758 /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
1759 } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
1760 retval = Z_INDIRECT_P(retval);
1761 if (Z_TYPE_P(retval) == IS_UNDEF) {
1762 if (UNEXPECTED(zend_string_equals(name, ZSTR_KNOWN(ZEND_STR_THIS)))) {
1763 ZEND_VM_C_GOTO(fetch_this);
1764 }
1765 if (type == BP_VAR_W) {
1766 ZVAL_NULL(retval);
1767 } else if (type == BP_VAR_IS || type == BP_VAR_UNSET) {
1768 retval = &EG(uninitialized_zval);
1769 } else {
1770 zend_error_unchecked(E_WARNING, "Undefined %svariable $%S",
1771 (opline->extended_value & ZEND_FETCH_GLOBAL ? "global " : ""), name);
1772 if (type == BP_VAR_RW && !EG(exception)) {
1773 ZVAL_NULL(retval);
1774 } else {
1775 retval = &EG(uninitialized_zval);
1776 }
1777 }
1778 }
1779 }
1780
1781 if (!(opline->extended_value & ZEND_FETCH_GLOBAL_LOCK)) {
1782 FREE_OP1();
1783 }
1784
1785 if (OP1_TYPE != IS_CONST) {
1786 zend_tmp_string_release(tmp_name);
1787 }
1788
1789 ZEND_ASSERT(retval != NULL);
1790 if (type == BP_VAR_R || type == BP_VAR_IS) {
1791 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
1792 } else {
1793 ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
1794 }
1795 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1796 }
1797
1798 ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
1799 {
1800 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_R);
1801 }
1802
1803 ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
1804 {
1805 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_W);
1806 }
1807
1808 ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
1809 {
1810 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_RW);
1811 }
1812
1813 ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
1814 {
1815 int fetch_type =
1816 (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ?
1817 BP_VAR_W : BP_VAR_R;
1818 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, fetch_type);
1819 }
1820
1821 ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
1822 {
1823 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
1824 }
1825
1826 ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
1827 {
1828 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_var_address_helper, type, BP_VAR_IS);
1829 }
1830
1831 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
ZEND_VM_HELPER(zend_fetch_static_prop_helper,ANY,ANY,int type)1832 ZEND_VM_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type)
1833 {
1834 USE_OPLINE
1835 zval *prop;
1836
1837 SAVE_OPLINE();
1838
1839 if (UNEXPECTED(zend_fetch_static_property_address(&prop, NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, opline->extended_value OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) {
1840 ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS));
1841 prop = &EG(uninitialized_zval);
1842 }
1843
1844 if (type == BP_VAR_R || type == BP_VAR_IS) {
1845 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), prop);
1846 } else {
1847 ZVAL_INDIRECT(EX_VAR(opline->result.var), prop);
1848 }
1849 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1850 }
1851
1852 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
1853 ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, ANY, CLASS_FETCH, CACHE_SLOT)
1854 {
1855 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_R);
1856 }
1857
1858 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
1859 ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, ANY, CLASS_FETCH, FETCH_REF|DIM_WRITE|CACHE_SLOT)
1860 {
1861 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_W);
1862 }
1863
1864 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
1865 ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, ANY, CLASS_FETCH, CACHE_SLOT)
1866 {
1867 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_RW);
1868 }
1869
1870 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
1871 ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, ANY, CLASS_FETCH, FETCH_REF|CACHE_SLOT)
1872 {
1873 int fetch_type =
1874 (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) ?
1875 BP_VAR_W : BP_VAR_R;
1876 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, fetch_type);
1877 }
1878
1879 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
1880 ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, ANY, CLASS_FETCH, CACHE_SLOT)
1881 {
1882 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_UNSET);
1883 }
1884
1885 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
1886 ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, ANY, CLASS_FETCH, CACHE_SLOT)
1887 {
1888 ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_static_prop_helper, type, BP_VAR_IS);
1889 }
1890
1891 ZEND_VM_COLD_CONSTCONST_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
1892 {
1893 USE_OPLINE
1894 zval *container, *dim, *value;
1895
1896 SAVE_OPLINE();
1897 container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
1898 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
1899 if (OP1_TYPE != IS_CONST) {
1900 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1901 ZEND_VM_C_LABEL(fetch_dim_r_array):
1902 value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, OP2_TYPE, BP_VAR_R EXECUTE_DATA_CC);
1903 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value);
1904 } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1905 container = Z_REFVAL_P(container);
1906 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1907 ZEND_VM_C_GOTO(fetch_dim_r_array);
1908 } else {
1909 ZEND_VM_C_GOTO(fetch_dim_r_slow);
1910 }
1911 } else {
1912 ZEND_VM_C_LABEL(fetch_dim_r_slow):
1913 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
1914 dim++;
1915 }
1916 zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
1917 }
1918 } else {
1919 zend_fetch_dimension_address_read_R(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
1920 }
1921 FREE_OP2();
1922 FREE_OP1();
1923 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1924 }
1925
1926 ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
1927 {
1928 USE_OPLINE
1929 zval *container;
1930
1931 SAVE_OPLINE();
1932 container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1933 zend_fetch_dimension_address_W(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
1934 FREE_OP2();
1935 if (OP1_TYPE == IS_VAR) {
1936 FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
1937 }
1938 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1939 }
1940
1941 ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
1942 {
1943 USE_OPLINE
1944 zval *container;
1945
1946 SAVE_OPLINE();
1947 container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
1948 zend_fetch_dimension_address_RW(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
1949 FREE_OP2();
1950 if (OP1_TYPE == IS_VAR) {
1951 FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
1952 }
1953 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1954 }
1955
1956 ZEND_VM_COLD_CONSTCONST_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
1957 {
1958 USE_OPLINE
1959 zval *container;
1960
1961 SAVE_OPLINE();
1962 container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_IS);
1963 zend_fetch_dimension_address_read_IS(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
1964 FREE_OP2();
1965 FREE_OP1();
1966 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
1967 }
1968
ZEND_VM_COLD_HELPER(zend_use_tmp_in_write_context_helper,ANY,ANY)1969 ZEND_VM_COLD_HELPER(zend_use_tmp_in_write_context_helper, ANY, ANY)
1970 {
1971 USE_OPLINE
1972
1973 SAVE_OPLINE();
1974 zend_throw_error(NULL, "Cannot use temporary expression in write context");
1975 FREE_OP2();
1976 FREE_OP1();
1977 ZVAL_UNDEF(EX_VAR(opline->result.var));
1978 HANDLE_EXCEPTION();
1979 }
1980
ZEND_VM_COLD_HELPER(zend_use_undef_in_read_context_helper,ANY,ANY)1981 ZEND_VM_COLD_HELPER(zend_use_undef_in_read_context_helper, ANY, ANY)
1982 {
1983 USE_OPLINE
1984
1985 SAVE_OPLINE();
1986 zend_throw_error(NULL, "Cannot use [] for reading");
1987 FREE_OP2();
1988 FREE_OP1();
1989 ZVAL_UNDEF(EX_VAR(opline->result.var));
1990 HANDLE_EXCEPTION();
1991 }
1992
1993 ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV)
1994 {
1995 #if !ZEND_VM_SPEC
1996 USE_OPLINE
1997 #endif
1998
1999 if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
2000 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
2001 ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper);
2002 }
2003 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_W);
2004 } else {
2005 if (OP2_TYPE == IS_UNUSED) {
2006 ZEND_VM_DISPATCH_TO_HELPER(zend_use_undef_in_read_context_helper);
2007 }
2008 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_R);
2009 }
2010 }
2011
2012 ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV)
2013 {
2014 USE_OPLINE
2015 zval *container;
2016
2017 SAVE_OPLINE();
2018 container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
2019 zend_fetch_dimension_address_UNSET(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
2020 FREE_OP2();
2021 if (OP1_TYPE == IS_VAR) {
2022 FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
2023 }
2024 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2025 }
2026
2027 ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
2028 {
2029 USE_OPLINE
2030 zval *container;
2031 void **cache_slot = NULL;
2032
2033 SAVE_OPLINE();
2034 container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
2035
2036 if (OP1_TYPE == IS_CONST ||
2037 (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
2038 do {
2039 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
2040 container = Z_REFVAL_P(container);
2041 if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2042 break;
2043 }
2044 }
2045 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2046 ZVAL_UNDEFINED_OP1();
2047 }
2048 zend_wrong_property_read(container, GET_OP2_ZVAL_PTR(BP_VAR_R));
2049 ZVAL_NULL(EX_VAR(opline->result.var));
2050 ZEND_VM_C_GOTO(fetch_obj_r_finish);
2051 } while (0);
2052 }
2053
2054 /* here we are sure we are dealing with an object */
2055 do {
2056 zend_object *zobj = Z_OBJ_P(container);
2057 zend_string *name, *tmp_name;
2058 zval *retval;
2059
2060 if (OP2_TYPE == IS_CONST) {
2061 cache_slot = CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_REF /* FUNC_ARG fetch may contain it */);
2062
2063 if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) {
2064 uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
2065
2066 if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
2067 ZEND_VM_C_LABEL(fetch_obj_r_simple):
2068 retval = OBJ_PROP(zobj, prop_offset);
2069 if (EXPECTED(Z_TYPE_INFO_P(retval) != IS_UNDEF)) {
2070 if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
2071 ZEND_VM_C_GOTO(fetch_obj_r_copy);
2072 } else {
2073 ZEND_VM_C_LABEL(fetch_obj_r_fast_copy):
2074 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
2075 ZEND_VM_NEXT_OPCODE();
2076 }
2077 }
2078 } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) {
2079 zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
2080 if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) {
2081 prop_offset = prop_info->offset;
2082 ZEND_VM_C_GOTO(fetch_obj_r_simple);
2083 } else if (EXPECTED(ZEND_IS_PROPERTY_HOOK_SIMPLE_GET(prop_offset))) {
2084 zend_function *hook = prop_info->hooks[ZEND_PROPERTY_HOOK_GET];
2085 ZEND_ASSERT(hook->type == ZEND_USER_FUNCTION);
2086 ZEND_ASSERT(RUN_TIME_CACHE(&hook->op_array));
2087
2088 uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
2089 if (OP1_TYPE & IS_CV) {
2090 GC_ADDREF(zobj);
2091 }
2092 if (OP1_TYPE & (IS_CV|IS_VAR|IS_TMP_VAR)) {
2093 call_info |= ZEND_CALL_RELEASE_THIS;
2094 }
2095 zend_execute_data *call = zend_vm_stack_push_call_frame(call_info, hook, 0, zobj);
2096 call->prev_execute_data = execute_data;
2097 call->call = NULL;
2098 call->return_value = EX_VAR(opline->result.var);
2099 call->run_time_cache = RUN_TIME_CACHE(&hook->op_array);
2100
2101 execute_data = call;
2102 EG(current_execute_data) = execute_data;
2103 zend_init_cvs(0, hook->op_array.last_var EXECUTE_DATA_CC);
2104
2105 #if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
2106 opline = hook->op_array.opcodes;
2107 #else
2108 EX(opline) = hook->op_array.opcodes;
2109 #endif
2110 LOAD_OPLINE_EX();
2111 ZEND_OBSERVER_SAVE_OPLINE();
2112 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
2113
2114 ZEND_VM_ENTER_EX();
2115 }
2116 /* Fall through to read_property for hooks. */
2117 } else if (EXPECTED(zobj->properties != NULL)) {
2118 ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset));
2119 name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
2120 if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) {
2121 uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset);
2122
2123 if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) {
2124 Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
2125
2126 if (EXPECTED(p->key == name) ||
2127 (EXPECTED(p->h == ZSTR_H(name)) &&
2128 EXPECTED(p->key != NULL) &&
2129 EXPECTED(zend_string_equal_content(p->key, name)))) {
2130 retval = &p->val;
2131 if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
2132 ZEND_VM_C_GOTO(fetch_obj_r_copy);
2133 } else {
2134 ZEND_VM_C_GOTO(fetch_obj_r_fast_copy);
2135 }
2136 }
2137 }
2138 CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
2139 }
2140 retval = zend_hash_find_known_hash(zobj->properties, name);
2141 if (EXPECTED(retval)) {
2142 uintptr_t idx = (char*)retval - (char*)zobj->properties->arData;
2143 CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
2144 if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
2145 ZEND_VM_C_GOTO(fetch_obj_r_copy);
2146 } else {
2147 ZEND_VM_C_GOTO(fetch_obj_r_fast_copy);
2148 }
2149 }
2150 }
2151 }
2152 name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
2153 } else {
2154 name = zval_try_get_tmp_string(GET_OP2_ZVAL_PTR(BP_VAR_R), &tmp_name);
2155 if (UNEXPECTED(!name)) {
2156 ZVAL_UNDEF(EX_VAR(opline->result.var));
2157 break;
2158 }
2159 }
2160
2161 #if ZEND_DEBUG
2162 /* For non-standard object handlers, verify a declared property type in debug builds.
2163 * Fetch prop_info before calling read_property(), as it may deallocate the object. */
2164 zend_property_info *prop_info = NULL;
2165 if (zobj->handlers->read_property != zend_std_read_property) {
2166 prop_info = zend_get_property_info(zobj->ce, name, /* silent */ true);
2167 }
2168 #endif
2169 retval = zobj->handlers->read_property(zobj, name, BP_VAR_R, cache_slot, EX_VAR(opline->result.var));
2170 #if ZEND_DEBUG
2171 if (!EG(exception) && prop_info && prop_info != ZEND_WRONG_PROPERTY_INFO
2172 && ZEND_TYPE_IS_SET(prop_info->type)) {
2173 ZVAL_OPT_DEREF(retval);
2174 zend_verify_property_type(prop_info, retval, /* strict */ true);
2175 }
2176 #endif
2177
2178 if (OP2_TYPE != IS_CONST) {
2179 zend_tmp_string_release(tmp_name);
2180 }
2181
2182 if (retval != EX_VAR(opline->result.var)) {
2183 ZEND_VM_C_LABEL(fetch_obj_r_copy):
2184 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
2185 } else if (UNEXPECTED(Z_ISREF_P(retval))) {
2186 zend_unwrap_reference(retval);
2187 }
2188 } while (0);
2189
2190 ZEND_VM_C_LABEL(fetch_obj_r_finish):
2191 FREE_OP2();
2192 FREE_OP1();
2193 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2194 }
2195
2196 ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|DIM_WRITE|CACHE_SLOT)
2197 {
2198 USE_OPLINE
2199 zval *property, *container, *result;
2200
2201 SAVE_OPLINE();
2202
2203 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2204 property = GET_OP2_ZVAL_PTR(BP_VAR_R);
2205 result = EX_VAR(opline->result.var);
2206 zend_fetch_property_address(
2207 result, container, OP1_TYPE, property, OP2_TYPE,
2208 ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL),
2209 BP_VAR_W, opline->extended_value, NULL OPLINE_CC EXECUTE_DATA_CC);
2210 FREE_OP2();
2211 if (OP1_TYPE == IS_VAR) {
2212 FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
2213 }
2214 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2215 }
2216
2217 ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
2218 {
2219 USE_OPLINE
2220 zval *property, *container, *result;
2221
2222 SAVE_OPLINE();
2223 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
2224 property = GET_OP2_ZVAL_PTR(BP_VAR_R);
2225 result = EX_VAR(opline->result.var);
2226 zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, NULL OPLINE_CC EXECUTE_DATA_CC);
2227 FREE_OP2();
2228 if (OP1_TYPE == IS_VAR) {
2229 FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
2230 }
2231 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2232 }
2233
2234 ZEND_VM_COLD_CONST_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
2235 {
2236 USE_OPLINE
2237 zval *container;
2238 void **cache_slot = NULL;
2239
2240 SAVE_OPLINE();
2241 container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
2242
2243 if (OP1_TYPE == IS_CONST ||
2244 (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
2245 do {
2246 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
2247 container = Z_REFVAL_P(container);
2248 if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2249 break;
2250 }
2251 }
2252 if (OP2_TYPE == IS_CV && Z_TYPE_P(EX_VAR(opline->op2.var)) == IS_UNDEF) {
2253 ZVAL_UNDEFINED_OP2();
2254 }
2255 ZVAL_NULL(EX_VAR(opline->result.var));
2256 ZEND_VM_C_GOTO(fetch_obj_is_finish);
2257 } while (0);
2258 }
2259
2260 /* here we are sure we are dealing with an object */
2261 do {
2262 zend_object *zobj = Z_OBJ_P(container);
2263 zend_string *name, *tmp_name;
2264 zval *retval;
2265
2266 if (OP2_TYPE == IS_CONST) {
2267 cache_slot = CACHE_ADDR(opline->extended_value);
2268
2269 if (EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) {
2270 uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
2271
2272 if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
2273 ZEND_VM_C_LABEL(fetch_obj_is_simple):
2274 retval = OBJ_PROP(zobj, prop_offset);
2275 if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
2276 if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
2277 ZEND_VM_C_GOTO(fetch_obj_is_copy);
2278 } else {
2279 ZEND_VM_C_LABEL(fetch_obj_is_fast_copy):
2280 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
2281 ZEND_VM_NEXT_OPCODE();
2282 }
2283 }
2284 } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) {
2285 if (ZEND_IS_PROPERTY_HOOK_SIMPLE_READ(prop_offset)) {
2286 zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
2287 prop_offset = prop_info->offset;
2288 ZEND_VM_C_GOTO(fetch_obj_is_simple);
2289 }
2290 /* Fall through to read_property for hooks. */
2291 } else if (EXPECTED(zobj->properties != NULL)) {
2292 ZEND_ASSERT(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset));
2293 name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
2294 if (!IS_UNKNOWN_DYNAMIC_PROPERTY_OFFSET(prop_offset)) {
2295 uintptr_t idx = ZEND_DECODE_DYN_PROP_OFFSET(prop_offset);
2296
2297 if (EXPECTED(idx < zobj->properties->nNumUsed * sizeof(Bucket))) {
2298 Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
2299
2300 if (EXPECTED(p->key == name) ||
2301 (EXPECTED(p->h == ZSTR_H(name)) &&
2302 EXPECTED(p->key != NULL) &&
2303 EXPECTED(zend_string_equal_content(p->key, name)))) {
2304 retval = &p->val;
2305 if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
2306 ZEND_VM_C_GOTO(fetch_obj_is_copy);
2307 } else {
2308 ZEND_VM_C_GOTO(fetch_obj_is_fast_copy);
2309 }
2310 }
2311 }
2312 CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_DYNAMIC_PROPERTY_OFFSET);
2313 }
2314 retval = zend_hash_find_known_hash(zobj->properties, name);
2315 if (EXPECTED(retval)) {
2316 uintptr_t idx = (char*)retval - (char*)zobj->properties->arData;
2317 CACHE_PTR_EX(cache_slot + 1, (void*)ZEND_ENCODE_DYN_PROP_OFFSET(idx));
2318 if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
2319 ZEND_VM_C_GOTO(fetch_obj_is_copy);
2320 } else {
2321 ZEND_VM_C_GOTO(fetch_obj_is_fast_copy);
2322 }
2323 }
2324 }
2325 }
2326 name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
2327 } else {
2328 name = zval_try_get_tmp_string(GET_OP2_ZVAL_PTR(BP_VAR_R), &tmp_name);
2329 if (UNEXPECTED(!name)) {
2330 ZVAL_UNDEF(EX_VAR(opline->result.var));
2331 break;
2332 }
2333 }
2334
2335 retval = zobj->handlers->read_property(zobj, name, BP_VAR_IS, cache_slot, EX_VAR(opline->result.var));
2336
2337 if (OP2_TYPE != IS_CONST) {
2338 zend_tmp_string_release(tmp_name);
2339 }
2340
2341 if (retval != EX_VAR(opline->result.var)) {
2342 ZEND_VM_C_LABEL(fetch_obj_is_copy):
2343 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), retval);
2344 } else if (UNEXPECTED(Z_ISREF_P(retval))) {
2345 zend_unwrap_reference(retval);
2346 }
2347 } while (0);
2348
2349 ZEND_VM_C_LABEL(fetch_obj_is_finish):
2350 FREE_OP2();
2351 FREE_OP1();
2352 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2353 }
2354
2355 ZEND_VM_COLD_CONST_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH_REF|CACHE_SLOT)
2356 {
2357 #if !ZEND_VM_SPEC
2358 USE_OPLINE
2359 #endif
2360
2361 if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
2362 /* Behave like FETCH_OBJ_W */
2363 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
2364 ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper);
2365 }
2366 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_W);
2367 } else {
2368 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_R);
2369 }
2370 }
2371
2372 ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
2373 {
2374 USE_OPLINE
2375 zval *container, *property, *result;
2376
2377 SAVE_OPLINE();
2378 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
2379 property = GET_OP2_ZVAL_PTR(BP_VAR_R);
2380 result = EX_VAR(opline->result.var);
2381 zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, NULL OPLINE_CC EXECUTE_DATA_CC);
2382 FREE_OP2();
2383 if (OP1_TYPE == IS_VAR) {
2384 FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
2385 }
2386 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2387 }
2388
2389 ZEND_VM_HANDLER(98, ZEND_FETCH_LIST_R, CONST|TMPVARCV, CONST|TMPVAR|CV)
2390 {
2391 USE_OPLINE
2392 zval *container;
2393
2394 SAVE_OPLINE();
2395 container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
2396 zend_fetch_dimension_address_LIST_r(container, GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R), OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
2397 FREE_OP2();
2398 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2399 }
2400
2401 ZEND_VM_HANDLER(155, ZEND_FETCH_LIST_W, VAR, CONST|TMPVAR|CV)
2402 {
2403 USE_OPLINE
2404 zval *container, *dim;
2405
2406 SAVE_OPLINE();
2407 container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2408 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
2409
2410 if (OP1_TYPE == IS_VAR
2411 && Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT
2412 && UNEXPECTED(!Z_ISREF_P(container))
2413 ) {
2414 zend_error(E_NOTICE, "Attempting to set reference to non referenceable value");
2415 zend_fetch_dimension_address_LIST_r(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
2416 } else {
2417 zend_fetch_dimension_address_W(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
2418 }
2419
2420 FREE_OP2();
2421 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2422 }
2423
2424 ZEND_VM_HANDLER(24, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV))
2425 {
2426 USE_OPLINE
2427 zval *object, *value, tmp;
2428 zend_object *zobj;
2429 zend_string *name, *tmp_name;
2430 zend_refcounted *garbage = NULL;
2431
2432 SAVE_OPLINE();
2433 object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2434 value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
2435
2436 if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
2437 if (Z_ISREF_P(object) && Z_TYPE_P(Z_REFVAL_P(object)) == IS_OBJECT) {
2438 object = Z_REFVAL_P(object);
2439 ZEND_VM_C_GOTO(assign_object);
2440 }
2441 zend_throw_non_object_error(object, GET_OP2_ZVAL_PTR(BP_VAR_R) OPLINE_CC EXECUTE_DATA_CC);
2442 value = &EG(uninitialized_zval);
2443 ZEND_VM_C_GOTO(free_and_exit_assign_obj);
2444 }
2445
2446 ZEND_VM_C_LABEL(assign_object):
2447 zobj = Z_OBJ_P(object);
2448 if (OP2_TYPE == IS_CONST) {
2449 if (EXPECTED(zobj->ce == CACHED_PTR(opline->extended_value))) {
2450 void **cache_slot = CACHE_ADDR(opline->extended_value);
2451 uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
2452 zval *property_val;
2453
2454 if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
2455 property_val = OBJ_PROP(zobj, prop_offset);
2456 if (Z_TYPE_P(property_val) != IS_UNDEF) {
2457 zend_property_info *prop_info = (zend_property_info*) CACHED_PTR_EX(cache_slot + 2);
2458
2459 if (prop_info != NULL) {
2460 value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC);
2461 ZEND_VM_C_GOTO(free_and_exit_assign_obj);
2462 } else {
2463 ZEND_VM_C_LABEL(fast_assign_obj):
2464 value = zend_assign_to_variable_ex(property_val, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES(), &garbage);
2465 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2466 ZVAL_COPY(EX_VAR(opline->result.var), value);
2467 }
2468 ZEND_VM_C_GOTO(exit_assign_obj);
2469 }
2470 }
2471 } else if (EXPECTED(IS_DYNAMIC_PROPERTY_OFFSET(prop_offset))) {
2472 name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
2473 if (UNEXPECTED(zend_lazy_object_must_init(zobj))) {
2474 zobj = zend_lazy_object_init(zobj);
2475 if (!zobj) {
2476 value = &EG(uninitialized_zval);
2477 ZEND_VM_C_GOTO(free_and_exit_assign_obj);
2478 }
2479 }
2480 if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
2481 rebuild_object_properties_internal(zobj);
2482 }
2483 if (EXPECTED(zobj->properties != NULL)) {
2484 if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
2485 if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
2486 GC_DELREF(zobj->properties);
2487 }
2488 zobj->properties = zend_array_dup(zobj->properties);
2489 }
2490 property_val = zend_hash_find_known_hash(zobj->properties, name);
2491 if (property_val) {
2492 ZEND_VM_C_GOTO(fast_assign_obj);
2493 }
2494 }
2495
2496 if (!zobj->ce->__set && (zobj->ce->ce_flags & ZEND_ACC_ALLOW_DYNAMIC_PROPERTIES)) {
2497 if (OP_DATA_TYPE == IS_CONST) {
2498 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(value))) {
2499 Z_ADDREF_P(value);
2500 }
2501 } else if (OP_DATA_TYPE != IS_TMP_VAR) {
2502 if (Z_ISREF_P(value)) {
2503 if (OP_DATA_TYPE == IS_VAR) {
2504 zend_reference *ref = Z_REF_P(value);
2505 if (GC_DELREF(ref) == 0) {
2506 ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value));
2507 efree_size(ref, sizeof(zend_reference));
2508 value = &tmp;
2509 } else {
2510 value = Z_REFVAL_P(value);
2511 Z_TRY_ADDREF_P(value);
2512 }
2513 } else {
2514 value = Z_REFVAL_P(value);
2515 Z_TRY_ADDREF_P(value);
2516 }
2517 } else if (OP_DATA_TYPE == IS_CV) {
2518 Z_TRY_ADDREF_P(value);
2519 }
2520 }
2521 zend_hash_add_new(zobj->properties, name, value);
2522 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2523 ZVAL_COPY(EX_VAR(opline->result.var), value);
2524 }
2525 ZEND_VM_C_GOTO(exit_assign_obj);
2526 }
2527 } else {
2528 ZEND_ASSERT(IS_HOOKED_PROPERTY_OFFSET(prop_offset));
2529 if (ZEND_IS_PROPERTY_HOOK_SIMPLE_WRITE(prop_offset)) {
2530 zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
2531 property_val = OBJ_PROP(zobj, prop_info->offset);
2532 if (ZEND_TYPE_IS_SET(prop_info->type)) {
2533 value = zend_assign_to_typed_prop(prop_info, property_val, value, &garbage EXECUTE_DATA_CC);
2534 ZEND_VM_C_GOTO(free_and_exit_assign_obj);
2535 } else {
2536 ZEND_VM_C_GOTO(fast_assign_obj);
2537 }
2538 }
2539 /* Fall through to write_property for hooks. */
2540 }
2541 }
2542 name = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
2543 } else {
2544 name = zval_try_get_tmp_string(GET_OP2_ZVAL_PTR(BP_VAR_R), &tmp_name);
2545 if (UNEXPECTED(!name)) {
2546 FREE_OP_DATA();
2547 UNDEF_RESULT();
2548 ZEND_VM_C_GOTO(exit_assign_obj);
2549 }
2550 }
2551
2552 if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) {
2553 ZVAL_DEREF(value);
2554 }
2555
2556 value = zobj->handlers->write_property(zobj, name, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL);
2557
2558 if (OP2_TYPE != IS_CONST) {
2559 zend_tmp_string_release(tmp_name);
2560 }
2561
2562 ZEND_VM_C_LABEL(free_and_exit_assign_obj):
2563 if (UNEXPECTED(RETURN_VALUE_USED(opline)) && value) {
2564 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value);
2565 }
2566 FREE_OP_DATA();
2567 ZEND_VM_C_LABEL(exit_assign_obj):
2568 if (garbage) {
2569 GC_DTOR_NO_REF(garbage);
2570 }
2571 FREE_OP2();
2572 FREE_OP1();
2573 /* assign_obj has two opcodes! */
2574 ZEND_VM_NEXT_OPCODE_EX(1, 2);
2575 }
2576
2577 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
2578 ZEND_VM_HANDLER(25, ZEND_ASSIGN_STATIC_PROP, ANY, ANY, CACHE_SLOT, SPEC(OP_DATA=CONST|TMP|VAR|CV))
2579 {
2580 USE_OPLINE
2581 zval *prop, *value;
2582 zend_property_info *prop_info;
2583 zend_refcounted *garbage = NULL;
2584
2585 SAVE_OPLINE();
2586
2587 if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
2588 FREE_OP_DATA();
2589 UNDEF_RESULT();
2590 HANDLE_EXCEPTION();
2591 }
2592
2593 value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
2594
2595 if (ZEND_TYPE_IS_SET(prop_info->type)) {
2596 value = zend_assign_to_typed_prop(prop_info, prop, value, &garbage EXECUTE_DATA_CC);
2597 FREE_OP_DATA();
2598 } else {
2599 value = zend_assign_to_variable_ex(prop, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES(), &garbage);
2600 }
2601
2602 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2603 ZVAL_COPY(EX_VAR(opline->result.var), value);
2604 }
2605
2606 if (garbage) {
2607 GC_DTOR_NO_REF(garbage);
2608 }
2609
2610 /* assign_static_prop has two opcodes! */
2611 ZEND_VM_NEXT_OPCODE_EX(1, 2);
2612 }
2613
2614 ZEND_VM_HANDLER(23, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV))
2615 {
2616 USE_OPLINE
2617 zval *object_ptr, *orig_object_ptr;
2618 zval *value;
2619 zval *variable_ptr;
2620 zval *dim;
2621 zend_refcounted *garbage = NULL;
2622
2623 SAVE_OPLINE();
2624 orig_object_ptr = object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2625
2626 if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
2627 ZEND_VM_C_LABEL(try_assign_dim_array):
2628 SEPARATE_ARRAY(object_ptr);
2629 if (OP2_TYPE == IS_UNUSED) {
2630 value = GET_OP_DATA_ZVAL_PTR_UNDEF(BP_VAR_R);
2631 if (OP_DATA_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
2632 HashTable *ht = Z_ARRVAL_P(object_ptr);
2633 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2634 GC_ADDREF(ht);
2635 }
2636 value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC);
2637 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2638 zend_array_destroy(ht);
2639 ZEND_VM_C_GOTO(assign_dim_error);
2640 }
2641 }
2642 if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) {
2643 ZVAL_DEREF(value);
2644 }
2645 value = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value);
2646 if (UNEXPECTED(value == NULL)) {
2647 zend_cannot_add_element();
2648 ZEND_VM_C_GOTO(assign_dim_error);
2649 } else if (OP_DATA_TYPE == IS_CV) {
2650 if (Z_REFCOUNTED_P(value)) {
2651 Z_ADDREF_P(value);
2652 }
2653 } else if (OP_DATA_TYPE == IS_VAR) {
2654 zval *free_op_data = EX_VAR((opline+1)->op1.var);
2655 if (Z_ISREF_P(free_op_data)) {
2656 if (Z_REFCOUNTED_P(value)) {
2657 Z_ADDREF_P(value);
2658 }
2659 zval_ptr_dtor_nogc(free_op_data);
2660 }
2661 } else if (OP_DATA_TYPE == IS_CONST) {
2662 if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
2663 Z_ADDREF_P(value);
2664 }
2665 }
2666 } else {
2667 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
2668 if (OP2_TYPE == IS_CONST) {
2669 variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC);
2670 } else {
2671 variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC);
2672 }
2673 if (UNEXPECTED(variable_ptr == NULL)) {
2674 ZEND_VM_C_GOTO(assign_dim_error);
2675 }
2676 value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
2677 value = zend_assign_to_variable_ex(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES(), &garbage);
2678 }
2679 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2680 ZVAL_COPY(EX_VAR(opline->result.var), value);
2681 }
2682 if (garbage) {
2683 GC_DTOR_NO_REF(garbage);
2684 }
2685 } else {
2686 if (EXPECTED(Z_ISREF_P(object_ptr))) {
2687 object_ptr = Z_REFVAL_P(object_ptr);
2688 if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
2689 ZEND_VM_C_GOTO(try_assign_dim_array);
2690 }
2691 }
2692 if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
2693 zend_object *obj = Z_OBJ_P(object_ptr);
2694
2695 GC_ADDREF(obj);
2696 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
2697 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(dim))) {
2698 dim = ZVAL_UNDEFINED_OP2();
2699 } else if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
2700 dim++;
2701 }
2702
2703 value = GET_OP_DATA_ZVAL_PTR_UNDEF(BP_VAR_R);
2704 if (OP_DATA_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(value))) {
2705 value = zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC);
2706 } else if (OP_DATA_TYPE & (IS_CV|IS_VAR)) {
2707 ZVAL_DEREF(value);
2708 }
2709
2710 zend_assign_to_object_dim(obj, dim, value OPLINE_CC EXECUTE_DATA_CC);
2711
2712 FREE_OP_DATA();
2713 if (UNEXPECTED(GC_DELREF(obj) == 0)) {
2714 zend_objects_store_del(obj);
2715 }
2716 } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
2717 if (OP2_TYPE == IS_UNUSED) {
2718 zend_use_new_element_for_string();
2719 FREE_OP_DATA();
2720 UNDEF_RESULT();
2721 } else {
2722 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
2723 value = GET_OP_DATA_ZVAL_PTR_UNDEF(BP_VAR_R);
2724 zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC);
2725 FREE_OP_DATA();
2726 }
2727 } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
2728 if (Z_ISREF_P(orig_object_ptr)
2729 && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr))
2730 && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) {
2731 dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
2732 FREE_OP_DATA();
2733 UNDEF_RESULT();
2734 } else {
2735 HashTable *ht = zend_new_array(8);
2736 uint8_t old_type = Z_TYPE_P(object_ptr);
2737
2738 ZVAL_ARR(object_ptr, ht);
2739 if (UNEXPECTED(old_type == IS_FALSE)) {
2740 GC_ADDREF(ht);
2741 zend_false_to_array_deprecated();
2742 if (UNEXPECTED(GC_DELREF(ht) == 0)) {
2743 zend_array_destroy(ht);
2744 ZEND_VM_C_GOTO(assign_dim_error);
2745 }
2746 }
2747 ZEND_VM_C_GOTO(try_assign_dim_array);
2748 }
2749 } else {
2750 zend_use_scalar_as_array();
2751 dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
2752 ZEND_VM_C_LABEL(assign_dim_error):
2753 FREE_OP_DATA();
2754 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2755 ZVAL_NULL(EX_VAR(opline->result.var));
2756 }
2757 }
2758 }
2759 if (OP2_TYPE != IS_UNUSED) {
2760 FREE_OP2();
2761 }
2762 FREE_OP1();
2763 /* assign_dim has two opcodes! */
2764 ZEND_VM_NEXT_OPCODE_EX(1, 2);
2765 }
2766
2767 ZEND_VM_HANDLER(22, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL))
2768 {
2769 USE_OPLINE
2770 zval *value;
2771 zval *variable_ptr;
2772
2773 SAVE_OPLINE();
2774 value = GET_OP2_ZVAL_PTR(BP_VAR_R);
2775 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2776
2777 if (!ZEND_VM_SPEC || UNEXPECTED(RETURN_VALUE_USED(opline))) {
2778 zend_refcounted *garbage = NULL;
2779
2780 value = zend_assign_to_variable_ex(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES(), &garbage);
2781 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2782 ZVAL_COPY(EX_VAR(opline->result.var), value);
2783 }
2784 if (garbage) {
2785 GC_DTOR_NO_REF(garbage);
2786 }
2787 } else {
2788 value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE, EX_USES_STRICT_TYPES());
2789 }
2790 FREE_OP1();
2791 /* zend_assign_to_variable() always takes care of op2, never free it! */
2792
2793 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2794 }
2795
2796 ZEND_VM_HANDLER(30, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC)
2797 {
2798 USE_OPLINE
2799 zval *variable_ptr;
2800 zval *value_ptr;
2801 zend_refcounted *garbage = NULL;
2802
2803 SAVE_OPLINE();
2804 value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W);
2805 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2806
2807 if (OP1_TYPE == IS_VAR &&
2808 UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
2809
2810 zend_throw_error(NULL, "Cannot assign by reference to an array dimension of an object");
2811 variable_ptr = &EG(uninitialized_zval);
2812 } else if (OP2_TYPE == IS_VAR &&
2813 opline->extended_value == ZEND_RETURNS_FUNCTION &&
2814 UNEXPECTED(!Z_ISREF_P(value_ptr))) {
2815
2816 variable_ptr = zend_wrong_assign_to_variable_reference(
2817 variable_ptr, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC);
2818 } else {
2819 zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage);
2820 }
2821
2822 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2823 ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
2824 }
2825
2826 if (garbage) {
2827 GC_DTOR(garbage);
2828 }
2829
2830 FREE_OP2();
2831 FREE_OP1();
2832 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
2833 }
2834
2835 ZEND_VM_HANDLER(32, ZEND_ASSIGN_OBJ_REF, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT|SRC, SPEC(OP_DATA=VAR|CV))
2836 {
2837 USE_OPLINE
2838 zval *property, *container, *value_ptr;
2839
2840 SAVE_OPLINE();
2841
2842 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
2843 property = GET_OP2_ZVAL_PTR(BP_VAR_R);
2844
2845 value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W);
2846
2847 if (ZEND_VM_SPEC) {
2848 if (OP1_TYPE == IS_UNUSED) {
2849 if (OP2_TYPE == IS_CONST) {
2850 zend_assign_to_property_reference_this_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC);
2851 } else {
2852 zend_assign_to_property_reference_this_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC);
2853 }
2854 } else {
2855 if (OP2_TYPE == IS_CONST) {
2856 zend_assign_to_property_reference_var_const(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC);
2857 } else {
2858 zend_assign_to_property_reference_var_var(container, property, value_ptr OPLINE_CC EXECUTE_DATA_CC);
2859 }
2860 }
2861 } else {
2862 zend_assign_to_property_reference(container, OP1_TYPE, property, OP2_TYPE, value_ptr OPLINE_CC EXECUTE_DATA_CC);
2863 }
2864
2865 FREE_OP1();
2866 FREE_OP2();
2867 FREE_OP_DATA();
2868 ZEND_VM_NEXT_OPCODE_EX(1, 2);
2869 }
2870
2871 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CONST|VAR) */
2872 ZEND_VM_HANDLER(33, ZEND_ASSIGN_STATIC_PROP_REF, ANY, ANY, CACHE_SLOT|SRC)
2873 {
2874 USE_OPLINE
2875 zval *prop, *value_ptr;
2876 zend_property_info *prop_info;
2877 zend_refcounted *garbage = NULL;
2878
2879 SAVE_OPLINE();
2880
2881 if (zend_fetch_static_property_address(&prop, &prop_info, opline->extended_value & ~ZEND_RETURNS_FUNCTION, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
2882 FREE_OP_DATA();
2883 UNDEF_RESULT();
2884 HANDLE_EXCEPTION();
2885 }
2886
2887 value_ptr = GET_OP_DATA_ZVAL_PTR_PTR(BP_VAR_W);
2888
2889 if (OP_DATA_TYPE == IS_VAR && (opline->extended_value & ZEND_RETURNS_FUNCTION) && UNEXPECTED(!Z_ISREF_P(value_ptr))) {
2890 if (UNEXPECTED(!zend_wrong_assign_to_variable_reference(prop, value_ptr, &garbage OPLINE_CC EXECUTE_DATA_CC))) {
2891 prop = &EG(uninitialized_zval);
2892 }
2893 } else if (ZEND_TYPE_IS_SET(prop_info->type)) {
2894 prop = zend_assign_to_typed_property_reference(prop_info, prop, value_ptr, &garbage EXECUTE_DATA_CC);
2895 } else {
2896 zend_assign_to_variable_reference(prop, value_ptr, &garbage);
2897 }
2898
2899 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2900 ZVAL_COPY(EX_VAR(opline->result.var), prop);
2901 }
2902
2903 if (garbage) {
2904 GC_DTOR(garbage);
2905 }
2906
2907 FREE_OP_DATA();
2908 ZEND_VM_NEXT_OPCODE_EX(1, 2);
2909 }
2910
ZEND_VM_HOT_HELPER(zend_leave_helper,ANY,ANY)2911 ZEND_VM_HOT_HELPER(zend_leave_helper, ANY, ANY)
2912 {
2913 zend_execute_data *old_execute_data;
2914 uint32_t call_info = EX_CALL_INFO();
2915 SAVE_OPLINE();
2916
2917 if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) == 0)) {
2918 EG(current_execute_data) = EX(prev_execute_data);
2919 i_free_compiled_variables(execute_data);
2920
2921 #ifdef ZEND_PREFER_RELOAD
2922 call_info = EX_CALL_INFO();
2923 #endif
2924 if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
2925 OBJ_RELEASE(Z_OBJ(execute_data->This));
2926 } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
2927 OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
2928 }
2929 EG(vm_stack_top) = (zval*)execute_data;
2930 execute_data = EX(prev_execute_data);
2931
2932 if (UNEXPECTED(EG(exception) != NULL)) {
2933 zend_rethrow_exception(execute_data);
2934 HANDLE_EXCEPTION_LEAVE();
2935 }
2936
2937 LOAD_NEXT_OPLINE();
2938 ZEND_VM_LEAVE();
2939 } else if (EXPECTED((call_info & (ZEND_CALL_CODE|ZEND_CALL_TOP)) == 0)) {
2940 EG(current_execute_data) = EX(prev_execute_data);
2941 i_free_compiled_variables(execute_data);
2942
2943 #ifdef ZEND_PREFER_RELOAD
2944 call_info = EX_CALL_INFO();
2945 #endif
2946 if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
2947 zend_clean_and_cache_symbol_table(EX(symbol_table));
2948 }
2949
2950 if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
2951 zend_free_extra_named_params(EX(extra_named_params));
2952 }
2953
2954 /* Free extra args before releasing the closure,
2955 * as that may free the op_array. */
2956 zend_vm_stack_free_extra_args_ex(call_info, execute_data);
2957
2958 if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
2959 OBJ_RELEASE(Z_OBJ(execute_data->This));
2960 } else if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
2961 OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
2962 }
2963
2964 old_execute_data = execute_data;
2965 execute_data = EX(prev_execute_data);
2966 zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
2967
2968 if (UNEXPECTED(EG(exception) != NULL)) {
2969 zend_rethrow_exception(execute_data);
2970 HANDLE_EXCEPTION_LEAVE();
2971 }
2972
2973 LOAD_NEXT_OPLINE();
2974 ZEND_VM_LEAVE();
2975 } else if (EXPECTED((call_info & ZEND_CALL_TOP) == 0)) {
2976 if (EX(func)->op_array.last_var > 0) {
2977 zend_detach_symbol_table(execute_data);
2978 call_info |= ZEND_CALL_NEEDS_REATTACH;
2979 }
2980 zend_destroy_static_vars(&EX(func)->op_array);
2981 destroy_op_array(&EX(func)->op_array);
2982 efree_size(EX(func), sizeof(zend_op_array));
2983 old_execute_data = execute_data;
2984 execute_data = EG(current_execute_data) = EX(prev_execute_data);
2985 zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
2986
2987 if (call_info & ZEND_CALL_NEEDS_REATTACH) {
2988 if (EX(func)->op_array.last_var > 0) {
2989 zend_attach_symbol_table(execute_data);
2990 } else {
2991 ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_NEEDS_REATTACH);
2992 }
2993 }
2994 if (UNEXPECTED(EG(exception) != NULL)) {
2995 zend_rethrow_exception(execute_data);
2996 HANDLE_EXCEPTION_LEAVE();
2997 }
2998
2999 LOAD_NEXT_OPLINE();
3000 ZEND_VM_LEAVE();
3001 } else {
3002 if (EXPECTED((call_info & ZEND_CALL_CODE) == 0)) {
3003 EG(current_execute_data) = EX(prev_execute_data);
3004 i_free_compiled_variables(execute_data);
3005 #ifdef ZEND_PREFER_RELOAD
3006 call_info = EX_CALL_INFO();
3007 #endif
3008 if (UNEXPECTED(call_info & (ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS))) {
3009 if (UNEXPECTED(call_info & ZEND_CALL_HAS_SYMBOL_TABLE)) {
3010 zend_clean_and_cache_symbol_table(EX(symbol_table));
3011 }
3012 zend_vm_stack_free_extra_args_ex(call_info, execute_data);
3013 if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
3014 zend_free_extra_named_params(EX(extra_named_params));
3015 }
3016 }
3017 if (UNEXPECTED(call_info & ZEND_CALL_CLOSURE)) {
3018 OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
3019 }
3020 ZEND_VM_RETURN();
3021 } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ {
3022 zend_array *symbol_table = EX(symbol_table);
3023
3024 if (EX(func)->op_array.last_var > 0) {
3025 zend_detach_symbol_table(execute_data);
3026 call_info |= ZEND_CALL_NEEDS_REATTACH;
3027 }
3028 if (call_info & ZEND_CALL_NEEDS_REATTACH) {
3029 old_execute_data = EX(prev_execute_data);
3030 while (old_execute_data) {
3031 if (old_execute_data->func && (ZEND_CALL_INFO(old_execute_data) & ZEND_CALL_HAS_SYMBOL_TABLE)) {
3032 if (old_execute_data->symbol_table == symbol_table) {
3033 if (old_execute_data->func->op_array.last_var > 0) {
3034 zend_attach_symbol_table(old_execute_data);
3035 } else {
3036 ZEND_ADD_CALL_FLAG(old_execute_data, ZEND_CALL_NEEDS_REATTACH);
3037 }
3038 }
3039 break;
3040 }
3041 old_execute_data = old_execute_data->prev_execute_data;
3042 }
3043 }
3044 EG(current_execute_data) = EX(prev_execute_data);
3045 ZEND_VM_RETURN();
3046 }
3047 }
3048 }
3049
3050 ZEND_VM_HOT_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
3051 {
3052 USE_OPLINE
3053
3054 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0);
3055 }
3056
3057 ZEND_VM_HOT_NOCONST_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
3058 {
3059 USE_OPLINE
3060 zval *val;
3061 uint8_t op1_type;
3062
3063 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
3064
3065 if (Z_TYPE_INFO_P(val) == IS_TRUE) {
3066 ZEND_VM_NEXT_OPCODE();
3067 } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
3068 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
3069 SAVE_OPLINE();
3070 ZVAL_UNDEFINED_OP1();
3071 if (UNEXPECTED(EG(exception))) {
3072 HANDLE_EXCEPTION();
3073 }
3074 }
3075 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
3076 }
3077
3078 SAVE_OPLINE();
3079 op1_type = OP1_TYPE;
3080 if (i_zend_is_true(val)) {
3081 opline++;
3082 } else {
3083 opline = OP_JMP_ADDR(opline, opline->op2);
3084 }
3085 if (op1_type & (IS_TMP_VAR|IS_VAR)) {
3086 zval_ptr_dtor_nogc(val);
3087 }
3088 ZEND_VM_JMP(opline);
3089 }
3090
3091 ZEND_VM_HOT_NOCONST_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
3092 {
3093 USE_OPLINE
3094 zval *val;
3095 uint8_t op1_type;
3096
3097 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
3098
3099 if (Z_TYPE_INFO_P(val) == IS_TRUE) {
3100 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
3101 } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
3102 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
3103 SAVE_OPLINE();
3104 ZVAL_UNDEFINED_OP1();
3105 if (UNEXPECTED(EG(exception))) {
3106 HANDLE_EXCEPTION();
3107 }
3108 }
3109 ZEND_VM_NEXT_OPCODE();
3110 }
3111
3112 SAVE_OPLINE();
3113 op1_type = OP1_TYPE;
3114 if (i_zend_is_true(val)) {
3115 opline = OP_JMP_ADDR(opline, opline->op2);
3116 } else {
3117 opline++;
3118 }
3119 if (op1_type & (IS_TMP_VAR|IS_VAR)) {
3120 zval_ptr_dtor_nogc(val);
3121 }
3122 ZEND_VM_JMP(opline);
3123 }
3124
3125 ZEND_VM_COLD_CONST_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
3126 {
3127 USE_OPLINE
3128 zval *val;
3129 bool ret;
3130
3131 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
3132
3133 if (Z_TYPE_INFO_P(val) == IS_TRUE) {
3134 ZVAL_TRUE(EX_VAR(opline->result.var));
3135 ZEND_VM_NEXT_OPCODE();
3136 } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
3137 ZVAL_FALSE(EX_VAR(opline->result.var));
3138 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
3139 SAVE_OPLINE();
3140 ZVAL_UNDEFINED_OP1();
3141 if (UNEXPECTED(EG(exception))) {
3142 HANDLE_EXCEPTION();
3143 }
3144 }
3145 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
3146 }
3147
3148 SAVE_OPLINE();
3149 ret = i_zend_is_true(val);
3150 FREE_OP1();
3151 if (ret) {
3152 ZVAL_TRUE(EX_VAR(opline->result.var));
3153 opline++;
3154 } else {
3155 ZVAL_FALSE(EX_VAR(opline->result.var));
3156 opline = OP_JMP_ADDR(opline, opline->op2);
3157 }
3158 ZEND_VM_JMP(opline);
3159 }
3160
3161 ZEND_VM_COLD_CONST_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
3162 {
3163 USE_OPLINE
3164 zval *val;
3165 bool ret;
3166
3167 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
3168
3169 if (Z_TYPE_INFO_P(val) == IS_TRUE) {
3170 ZVAL_TRUE(EX_VAR(opline->result.var));
3171 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
3172 } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
3173 ZVAL_FALSE(EX_VAR(opline->result.var));
3174 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(val) == IS_UNDEF)) {
3175 SAVE_OPLINE();
3176 ZVAL_UNDEFINED_OP1();
3177 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3178 } else {
3179 ZEND_VM_NEXT_OPCODE();
3180 }
3181 }
3182
3183 SAVE_OPLINE();
3184 ret = i_zend_is_true(val);
3185 FREE_OP1();
3186 if (ret) {
3187 ZVAL_TRUE(EX_VAR(opline->result.var));
3188 opline = OP_JMP_ADDR(opline, opline->op2);
3189 } else {
3190 ZVAL_FALSE(EX_VAR(opline->result.var));
3191 opline++;
3192 }
3193 ZEND_VM_JMP(opline);
3194 }
3195
3196 ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY)
3197 {
3198 USE_OPLINE
3199
3200 SAVE_OPLINE();
3201 zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
3202 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3203 }
3204
3205 ZEND_VM_HOT_HANDLER(127, ZEND_FE_FREE, TMPVAR, ANY)
3206 {
3207 zval *var;
3208 USE_OPLINE
3209
3210 var = EX_VAR(opline->op1.var);
3211 if (Z_TYPE_P(var) != IS_ARRAY) {
3212 SAVE_OPLINE();
3213 if (Z_FE_ITER_P(var) != (uint32_t)-1) {
3214 zend_hash_iterator_del(Z_FE_ITER_P(var));
3215 }
3216 zval_ptr_dtor_nogc(var);
3217 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3218 }
3219
3220 /* This is freeing an array. Use an inlined version of zval_ptr_dtor_nogc. */
3221 /* PHP only needs to save the opline and check for an exception if the last reference to the array was garbage collected (destructors of elements in the array could throw an exception) */
3222 if (Z_REFCOUNTED_P(var) && !Z_DELREF_P(var)) {
3223 SAVE_OPLINE();
3224 rc_dtor_func(Z_COUNTED_P(var));
3225 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3226 }
3227 ZEND_VM_NEXT_OPCODE();
3228 }
3229
3230 ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
3231 {
3232 USE_OPLINE
3233 zval *op1, *op2;
3234 zend_string *op1_str, *op2_str, *str;
3235
3236
3237 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
3238 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3239 if ((OP1_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
3240 (OP2_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
3241 zend_string *op1_str = Z_STR_P(op1);
3242 zend_string *op2_str = Z_STR_P(op2);
3243 zend_string *str;
3244 uint32_t flags = ZSTR_GET_COPYABLE_CONCAT_PROPERTIES_BOTH(op1_str, op2_str);
3245
3246 if (OP1_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op1_str) == 0)) {
3247 if (OP2_TYPE == IS_CONST || OP2_TYPE == IS_CV) {
3248 ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
3249 } else {
3250 ZVAL_STR(EX_VAR(opline->result.var), op2_str);
3251 }
3252 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
3253 zend_string_release_ex(op1_str, 0);
3254 }
3255 } else if (OP2_TYPE != IS_CONST && UNEXPECTED(ZSTR_LEN(op2_str) == 0)) {
3256 if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_CV) {
3257 ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
3258 } else {
3259 ZVAL_STR(EX_VAR(opline->result.var), op1_str);
3260 }
3261 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
3262 zend_string_release_ex(op2_str, 0);
3263 }
3264 } else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV &&
3265 !ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
3266 size_t len = ZSTR_LEN(op1_str);
3267
3268 str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
3269 memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
3270 GC_ADD_FLAGS(str, flags);
3271 ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
3272 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
3273 zend_string_release_ex(op2_str, 0);
3274 }
3275 } else {
3276 str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
3277 memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
3278 memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
3279 GC_ADD_FLAGS(str, flags);
3280 ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
3281 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
3282 zend_string_release_ex(op1_str, 0);
3283 }
3284 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
3285 zend_string_release_ex(op2_str, 0);
3286 }
3287 }
3288 ZEND_VM_NEXT_OPCODE();
3289 }
3290
3291 SAVE_OPLINE();
3292 if (OP1_TYPE == IS_CONST) {
3293 op1_str = Z_STR_P(op1);
3294 } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
3295 op1_str = zend_string_copy(Z_STR_P(op1));
3296 } else {
3297 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
3298 ZVAL_UNDEFINED_OP1();
3299 }
3300 op1_str = zval_get_string_func(op1);
3301 }
3302 if (OP2_TYPE == IS_CONST) {
3303 op2_str = Z_STR_P(op2);
3304 } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
3305 op2_str = zend_string_copy(Z_STR_P(op2));
3306 } else {
3307 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
3308 ZVAL_UNDEFINED_OP2();
3309 }
3310 op2_str = zval_get_string_func(op2);
3311 }
3312 do {
3313 if (OP1_TYPE != IS_CONST) {
3314 if (UNEXPECTED(ZSTR_LEN(op1_str) == 0)) {
3315 if (OP2_TYPE == IS_CONST) {
3316 if (UNEXPECTED(Z_REFCOUNTED_P(op2))) {
3317 GC_ADDREF(op2_str);
3318 }
3319 }
3320 ZVAL_STR(EX_VAR(opline->result.var), op2_str);
3321 zend_string_release_ex(op1_str, 0);
3322 break;
3323 }
3324 }
3325 if (OP2_TYPE != IS_CONST) {
3326 if (UNEXPECTED(ZSTR_LEN(op2_str) == 0)) {
3327 if (OP1_TYPE == IS_CONST) {
3328 if (UNEXPECTED(Z_REFCOUNTED_P(op1))) {
3329 GC_ADDREF(op1_str);
3330 }
3331 }
3332 ZVAL_STR(EX_VAR(opline->result.var), op1_str);
3333 zend_string_release_ex(op2_str, 0);
3334 break;
3335 }
3336 }
3337 str = zend_string_alloc(ZSTR_LEN(op1_str) + ZSTR_LEN(op2_str), 0);
3338 memcpy(ZSTR_VAL(str), ZSTR_VAL(op1_str), ZSTR_LEN(op1_str));
3339 memcpy(ZSTR_VAL(str) + ZSTR_LEN(op1_str), ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
3340
3341 ZSTR_COPY_CONCAT_PROPERTIES_BOTH(str, op1_str, op2_str);
3342 ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
3343 if (OP1_TYPE != IS_CONST) {
3344 zend_string_release_ex(op1_str, 0);
3345 }
3346 if (OP2_TYPE != IS_CONST) {
3347 zend_string_release_ex(op2_str, 0);
3348 }
3349 } while (0);
3350 FREE_OP1();
3351 FREE_OP2();
3352 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3353 }
3354
3355 ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV, NUM)
3356 {
3357 USE_OPLINE
3358 zend_string **rope;
3359 zval *var;
3360
3361 /* Compiler allocates the necessary number of zval slots to keep the rope */
3362 rope = (zend_string**)EX_VAR(opline->result.var);
3363 if (OP2_TYPE == IS_CONST) {
3364 var = GET_OP2_ZVAL_PTR(BP_VAR_R);
3365 rope[0] = Z_STR_P(var);
3366 if (UNEXPECTED(Z_REFCOUNTED_P(var))) {
3367 Z_ADDREF_P(var);
3368 }
3369 } else {
3370 var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3371 if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
3372 if (OP2_TYPE == IS_CV) {
3373 rope[0] = zend_string_copy(Z_STR_P(var));
3374 } else {
3375 rope[0] = Z_STR_P(var);
3376 }
3377 } else {
3378 SAVE_OPLINE();
3379 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
3380 ZVAL_UNDEFINED_OP2();
3381 }
3382 rope[0] = zval_get_string_func(var);
3383 FREE_OP2();
3384 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3385 }
3386 }
3387 ZEND_VM_NEXT_OPCODE();
3388 }
3389
3390 ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV, NUM)
3391 {
3392 USE_OPLINE
3393 zend_string **rope;
3394 zval *var;
3395
3396 /* op1 and result are the same */
3397 rope = (zend_string**)EX_VAR(opline->op1.var);
3398 if (OP2_TYPE == IS_CONST) {
3399 var = GET_OP2_ZVAL_PTR(BP_VAR_R);
3400 rope[opline->extended_value] = Z_STR_P(var);
3401 if (UNEXPECTED(Z_REFCOUNTED_P(var))) {
3402 Z_ADDREF_P(var);
3403 }
3404 } else {
3405 var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3406 if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
3407 if (OP2_TYPE == IS_CV) {
3408 rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
3409 } else {
3410 rope[opline->extended_value] = Z_STR_P(var);
3411 }
3412 } else {
3413 SAVE_OPLINE();
3414 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
3415 ZVAL_UNDEFINED_OP2();
3416 }
3417 rope[opline->extended_value] = zval_get_string_func(var);
3418 FREE_OP2();
3419 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3420 }
3421 }
3422 ZEND_VM_NEXT_OPCODE();
3423 }
3424
3425 ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM)
3426 {
3427 USE_OPLINE
3428 zend_string **rope;
3429 zval *var, *ret;
3430 uint32_t i;
3431
3432 rope = (zend_string**)EX_VAR(opline->op1.var);
3433 if (OP2_TYPE == IS_CONST) {
3434 var = GET_OP2_ZVAL_PTR(BP_VAR_R);
3435 rope[opline->extended_value] = Z_STR_P(var);
3436 if (UNEXPECTED(Z_REFCOUNTED_P(var))) {
3437 Z_ADDREF_P(var);
3438 }
3439 } else {
3440 var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3441 if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
3442 if (OP2_TYPE == IS_CV) {
3443 rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
3444 } else {
3445 rope[opline->extended_value] = Z_STR_P(var);
3446 }
3447 } else {
3448 SAVE_OPLINE();
3449 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
3450 ZVAL_UNDEFINED_OP2();
3451 }
3452 rope[opline->extended_value] = zval_get_string_func(var);
3453 FREE_OP2();
3454 if (UNEXPECTED(EG(exception))) {
3455 for (i = 0; i <= opline->extended_value; i++) {
3456 zend_string_release_ex(rope[i], 0);
3457 }
3458 ZVAL_UNDEF(EX_VAR(opline->result.var));
3459 HANDLE_EXCEPTION();
3460 }
3461 }
3462 }
3463
3464 size_t len = 0;
3465 uint32_t flags = ZSTR_COPYABLE_CONCAT_PROPERTIES;
3466 for (i = 0; i <= opline->extended_value; i++) {
3467 flags &= ZSTR_GET_COPYABLE_CONCAT_PROPERTIES(rope[i]);
3468 len += ZSTR_LEN(rope[i]);
3469 }
3470 ret = EX_VAR(opline->result.var);
3471 ZVAL_STR(ret, zend_string_alloc(len, 0));
3472 GC_ADD_FLAGS(Z_STR_P(ret), flags);
3473
3474 char *target = Z_STRVAL_P(ret);
3475 for (i = 0; i <= opline->extended_value; i++) {
3476 memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i]));
3477 target += ZSTR_LEN(rope[i]);
3478 zend_string_release_ex(rope[i], 0);
3479 }
3480 *target = '\0';
3481
3482 ZEND_VM_NEXT_OPCODE();
3483 }
3484
3485 ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, UNUSED|CLASS_FETCH, CONST|TMPVAR|UNUSED|CV, CACHE_SLOT)
3486 {
3487 zval *class_name;
3488 USE_OPLINE
3489
3490 SAVE_OPLINE();
3491 if (OP2_TYPE == IS_UNUSED) {
3492 Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->op1.num);
3493 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3494 } else if (OP2_TYPE == IS_CONST) {
3495 zend_class_entry *ce = CACHED_PTR(opline->extended_value);
3496
3497 if (UNEXPECTED(ce == NULL)) {
3498 class_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3499 ce = zend_fetch_class_by_name(Z_STR_P(class_name), Z_STR_P(class_name + 1), opline->op1.num);
3500 CACHE_PTR(opline->extended_value, ce);
3501 }
3502 Z_CE_P(EX_VAR(opline->result.var)) = ce;
3503 } else {
3504 class_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3505 ZEND_VM_C_LABEL(try_class_name):
3506 if (Z_TYPE_P(class_name) == IS_OBJECT) {
3507 Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name);
3508 } else if (Z_TYPE_P(class_name) == IS_STRING) {
3509 Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->op1.num);
3510 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) {
3511 class_name = Z_REFVAL_P(class_name);
3512 ZEND_VM_C_GOTO(try_class_name);
3513 } else {
3514 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) {
3515 ZVAL_UNDEFINED_OP2();
3516 if (UNEXPECTED(EG(exception) != NULL)) {
3517 HANDLE_EXCEPTION();
3518 }
3519 }
3520 zend_throw_error(NULL, "Class name must be a valid object or a string");
3521 }
3522 }
3523
3524 FREE_OP2();
3525 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3526 }
3527
3528 ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, NUM|CACHE_SLOT)
3529 {
3530 USE_OPLINE
3531 zval *function_name;
3532 zval *object;
3533 zend_function *fbc;
3534 zend_class_entry *called_scope;
3535 zend_object *obj;
3536 zend_execute_data *call;
3537 uint32_t call_info;
3538
3539 SAVE_OPLINE();
3540
3541 object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
3542
3543 if (OP2_TYPE != IS_CONST) {
3544 function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3545 }
3546
3547 if (OP2_TYPE != IS_CONST &&
3548 UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
3549 do {
3550 if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) {
3551 function_name = Z_REFVAL_P(function_name);
3552 if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
3553 break;
3554 }
3555 } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
3556 ZVAL_UNDEFINED_OP2();
3557 if (UNEXPECTED(EG(exception) != NULL)) {
3558 FREE_OP1();
3559 HANDLE_EXCEPTION();
3560 }
3561 }
3562 zend_throw_error(NULL, "Method name must be a string");
3563 FREE_OP2();
3564 FREE_OP1();
3565 HANDLE_EXCEPTION();
3566 } while (0);
3567 }
3568
3569 if (OP1_TYPE == IS_UNUSED) {
3570 obj = Z_OBJ_P(object);
3571 } else {
3572 do {
3573 if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
3574 obj = Z_OBJ_P(object);
3575 } else {
3576 if ((OP1_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
3577 zend_reference *ref = Z_REF_P(object);
3578
3579 object = &ref->val;
3580 if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
3581 obj = Z_OBJ_P(object);
3582 if (OP1_TYPE & IS_VAR) {
3583 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
3584 efree_size(ref, sizeof(zend_reference));
3585 } else {
3586 Z_ADDREF_P(object);
3587 }
3588 }
3589 break;
3590 }
3591 }
3592 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
3593 object = ZVAL_UNDEFINED_OP1();
3594 if (UNEXPECTED(EG(exception) != NULL)) {
3595 if (OP2_TYPE != IS_CONST) {
3596 FREE_OP2();
3597 }
3598 HANDLE_EXCEPTION();
3599 }
3600 }
3601 if (OP2_TYPE == IS_CONST) {
3602 function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3603 }
3604 zend_invalid_method_call(object, function_name);
3605 FREE_OP2();
3606 FREE_OP1();
3607 HANDLE_EXCEPTION();
3608 }
3609 } while (0);
3610 }
3611
3612 called_scope = obj->ce;
3613
3614 if (OP2_TYPE == IS_CONST &&
3615 EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) {
3616 fbc = CACHED_PTR(opline->result.num + sizeof(void*));
3617 } else {
3618 zend_object *orig_obj = obj;
3619
3620 if (OP2_TYPE == IS_CONST) {
3621 function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3622 }
3623
3624 /* First, locate the function. */
3625 fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL));
3626 if (UNEXPECTED(fbc == NULL)) {
3627 if (EXPECTED(!EG(exception))) {
3628 zend_undefined_method(obj->ce, Z_STR_P(function_name));
3629 }
3630 FREE_OP2();
3631 if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(orig_obj) == 0) {
3632 zend_objects_store_del(orig_obj);
3633 }
3634 HANDLE_EXCEPTION();
3635 }
3636 if (OP2_TYPE == IS_CONST &&
3637 EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
3638 EXPECTED(obj == orig_obj)) {
3639 CACHE_POLYMORPHIC_PTR(opline->result.num, called_scope, fbc);
3640 }
3641 if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && UNEXPECTED(obj != orig_obj)) {
3642 GC_ADDREF(obj); /* For $this pointer */
3643 if (GC_DELREF(orig_obj) == 0) {
3644 zend_objects_store_del(orig_obj);
3645 }
3646 }
3647 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3648 init_func_run_time_cache(&fbc->op_array);
3649 }
3650 }
3651
3652 if (OP2_TYPE != IS_CONST) {
3653 FREE_OP2();
3654 }
3655
3656 call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
3657 if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
3658 if ((OP1_TYPE & (IS_VAR|IS_TMP_VAR)) && GC_DELREF(obj) == 0) {
3659 zend_objects_store_del(obj);
3660 if (UNEXPECTED(EG(exception))) {
3661 HANDLE_EXCEPTION();
3662 }
3663 }
3664 /* call static method */
3665 obj = (zend_object*)called_scope;
3666 call_info = ZEND_CALL_NESTED_FUNCTION;
3667 } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) {
3668 if (OP1_TYPE == IS_CV) {
3669 GC_ADDREF(obj); /* For $this pointer */
3670 }
3671 /* CV may be changed indirectly (e.g. when it's a reference) */
3672 call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
3673 }
3674
3675 call = zend_vm_stack_push_call_frame(call_info,
3676 fbc, opline->extended_value, obj);
3677 call->prev_execute_data = EX(call);
3678 EX(call) = call;
3679
3680 ZEND_VM_NEXT_OPCODE();
3681 }
3682
3683 ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, CONST|TMPVAR|UNUSED|CONSTRUCTOR|CV, NUM|CACHE_SLOT)
3684 {
3685 USE_OPLINE
3686 zval *function_name;
3687 zend_class_entry *ce;
3688 uint32_t call_info;
3689 zend_function *fbc;
3690 zend_execute_data *call;
3691
3692 SAVE_OPLINE();
3693
3694 if (OP1_TYPE == IS_CONST) {
3695 /* no function found. try a static method in class */
3696 ce = CACHED_PTR(opline->result.num);
3697 if (UNEXPECTED(ce == NULL)) {
3698 ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
3699 if (UNEXPECTED(ce == NULL)) {
3700 FREE_OP2();
3701 HANDLE_EXCEPTION();
3702 }
3703 if (OP2_TYPE != IS_CONST) {
3704 CACHE_PTR(opline->result.num, ce);
3705 }
3706 }
3707 } else if (OP1_TYPE == IS_UNUSED) {
3708 ce = zend_fetch_class(NULL, opline->op1.num);
3709 if (UNEXPECTED(ce == NULL)) {
3710 FREE_OP2();
3711 HANDLE_EXCEPTION();
3712 }
3713 } else {
3714 ce = Z_CE_P(EX_VAR(opline->op1.var));
3715 }
3716
3717 if (OP1_TYPE == IS_CONST &&
3718 OP2_TYPE == IS_CONST &&
3719 EXPECTED((fbc = CACHED_PTR(opline->result.num + sizeof(void*))) != NULL)) {
3720 /* nothing to do */
3721 } else if (OP1_TYPE != IS_CONST &&
3722 OP2_TYPE == IS_CONST &&
3723 EXPECTED(CACHED_PTR(opline->result.num) == ce)) {
3724 fbc = CACHED_PTR(opline->result.num + sizeof(void*));
3725 } else if (OP2_TYPE != IS_UNUSED) {
3726 function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3727 if (OP2_TYPE != IS_CONST) {
3728 if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
3729 do {
3730 if (OP2_TYPE & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
3731 function_name = Z_REFVAL_P(function_name);
3732 if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
3733 break;
3734 }
3735 } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
3736 ZVAL_UNDEFINED_OP2();
3737 if (UNEXPECTED(EG(exception) != NULL)) {
3738 HANDLE_EXCEPTION();
3739 }
3740 }
3741 zend_throw_error(NULL, "Method name must be a string");
3742 FREE_OP2();
3743 HANDLE_EXCEPTION();
3744 } while (0);
3745 }
3746 }
3747
3748 if (ce->get_static_method) {
3749 fbc = ce->get_static_method(ce, Z_STR_P(function_name));
3750 } else {
3751 fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (RT_CONSTANT(opline, opline->op2) + 1) : NULL));
3752 }
3753 if (UNEXPECTED(fbc == NULL)) {
3754 if (EXPECTED(!EG(exception))) {
3755 zend_undefined_method(ce, Z_STR_P(function_name));
3756 }
3757 FREE_OP2();
3758 HANDLE_EXCEPTION();
3759 }
3760 if (OP2_TYPE == IS_CONST &&
3761 EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE))) &&
3762 EXPECTED(!(fbc->common.scope->ce_flags & ZEND_ACC_TRAIT))) {
3763 CACHE_POLYMORPHIC_PTR(opline->result.num, ce, fbc);
3764 }
3765 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3766 init_func_run_time_cache(&fbc->op_array);
3767 }
3768 if (OP2_TYPE != IS_CONST) {
3769 FREE_OP2();
3770 }
3771 } else {
3772 if (UNEXPECTED(ce->constructor == NULL)) {
3773 zend_throw_error(NULL, "Cannot call constructor");
3774 HANDLE_EXCEPTION();
3775 }
3776 if (Z_TYPE(EX(This)) == IS_OBJECT && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
3777 zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name));
3778 HANDLE_EXCEPTION();
3779 }
3780 fbc = ce->constructor;
3781 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3782 init_func_run_time_cache(&fbc->op_array);
3783 }
3784 }
3785
3786 if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
3787 if (Z_TYPE(EX(This)) == IS_OBJECT && instanceof_function(Z_OBJCE(EX(This)), ce)) {
3788 ce = (zend_class_entry*)Z_OBJ(EX(This));
3789 call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS;
3790 } else {
3791 zend_non_static_method_call(fbc);
3792 HANDLE_EXCEPTION();
3793 }
3794 } else {
3795 /* previous opcode is ZEND_FETCH_CLASS */
3796 if (OP1_TYPE == IS_UNUSED
3797 && ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
3798 (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF)) {
3799 if (Z_TYPE(EX(This)) == IS_OBJECT) {
3800 ce = Z_OBJCE(EX(This));
3801 } else {
3802 ce = Z_CE(EX(This));
3803 }
3804 }
3805 call_info = ZEND_CALL_NESTED_FUNCTION;
3806 }
3807
3808 call = zend_vm_stack_push_call_frame(call_info,
3809 fbc, opline->extended_value, ce);
3810 call->prev_execute_data = EX(call);
3811 EX(call) = call;
3812
3813 ZEND_VM_NEXT_OPCODE();
3814 }
3815
3816 ZEND_VM_HOT_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
3817 {
3818 USE_OPLINE
3819 zend_function *fbc;
3820 zval *function_name, *func;
3821 zend_execute_data *call;
3822
3823 fbc = CACHED_PTR(opline->result.num);
3824 if (UNEXPECTED(fbc == NULL)) {
3825 function_name = (zval*)RT_CONSTANT(opline, opline->op2);
3826 func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(function_name+1));
3827 if (UNEXPECTED(func == NULL)) {
3828 ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
3829 }
3830 fbc = Z_FUNC_P(func);
3831 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3832 init_func_run_time_cache(&fbc->op_array);
3833 }
3834 CACHE_PTR(opline->result.num, fbc);
3835 }
3836 call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
3837 fbc, opline->extended_value, NULL);
3838 call->prev_execute_data = EX(call);
3839 EX(call) = call;
3840
3841 ZEND_VM_NEXT_OPCODE();
3842 }
3843
3844 ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV, NUM)
3845 {
3846 USE_OPLINE
3847 zval *function_name;
3848 zend_execute_data *call;
3849
3850 SAVE_OPLINE();
3851 function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
3852
3853 ZEND_VM_C_LABEL(try_function_name):
3854 if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
3855 call = zend_init_dynamic_call_string(Z_STR_P(function_name), opline->extended_value);
3856 } else if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT)) {
3857 call = zend_init_dynamic_call_object(Z_OBJ_P(function_name), opline->extended_value);
3858 } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY)) {
3859 call = zend_init_dynamic_call_array(Z_ARRVAL_P(function_name), opline->extended_value);
3860 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(function_name) == IS_REFERENCE)) {
3861 function_name = Z_REFVAL_P(function_name);
3862 ZEND_VM_C_GOTO(try_function_name);
3863 } else {
3864 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
3865 function_name = ZVAL_UNDEFINED_OP2();
3866 if (UNEXPECTED(EG(exception) != NULL)) {
3867 HANDLE_EXCEPTION();
3868 }
3869 }
3870 zend_throw_error(NULL, "Value of type %s is not callable",
3871 zend_zval_type_name(function_name));
3872 call = NULL;
3873 }
3874
3875 if (OP2_TYPE & (IS_VAR|IS_TMP_VAR)) {
3876 FREE_OP2();
3877 if (UNEXPECTED(EG(exception))) {
3878 if (call) {
3879 if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
3880 zend_string_release_ex(call->func->common.function_name, 0);
3881 zend_free_trampoline(call->func);
3882 }
3883 zend_vm_stack_free_call_frame(call);
3884 }
3885 HANDLE_EXCEPTION();
3886 }
3887 } else if (!call) {
3888 HANDLE_EXCEPTION();
3889 }
3890
3891 call->prev_execute_data = EX(call);
3892 EX(call) = call;
3893
3894 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
3895 }
3896
3897 ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
3898 {
3899 USE_OPLINE
3900 zval *function_name;
3901 zend_fcall_info_cache fcc;
3902 char *error = NULL;
3903 zend_function *func;
3904 void *object_or_called_scope;
3905 zend_execute_data *call;
3906 uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
3907
3908 SAVE_OPLINE();
3909 function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
3910 if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
3911 ZEND_ASSERT(!error);
3912 func = fcc.function_handler;
3913 object_or_called_scope = fcc.called_scope;
3914 if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
3915 /* Delay closure destruction until its invocation */
3916 GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
3917 call_info |= ZEND_CALL_CLOSURE;
3918 if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
3919 call_info |= ZEND_CALL_FAKE_CLOSURE;
3920 }
3921 if (fcc.object) {
3922 object_or_called_scope = fcc.object;
3923 call_info |= ZEND_CALL_HAS_THIS;
3924 }
3925 } else if (fcc.object) {
3926 GC_ADDREF(fcc.object); /* For $this pointer */
3927 object_or_called_scope = fcc.object;
3928 call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
3929 }
3930
3931 FREE_OP2();
3932 if ((OP2_TYPE & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
3933 if (call_info & ZEND_CALL_CLOSURE) {
3934 zend_object_release(ZEND_CLOSURE_OBJECT(func));
3935 } else if (call_info & ZEND_CALL_RELEASE_THIS) {
3936 zend_object_release(fcc.object);
3937 }
3938 HANDLE_EXCEPTION();
3939 }
3940
3941 if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) {
3942 init_func_run_time_cache(&func->op_array);
3943 }
3944 } else {
3945 zend_type_error("%s(): Argument #1 ($callback) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error);
3946 efree(error);
3947 FREE_OP2();
3948 HANDLE_EXCEPTION();
3949 }
3950
3951 call = zend_vm_stack_push_call_frame(call_info,
3952 func, opline->extended_value, object_or_called_scope);
3953 call->prev_execute_data = EX(call);
3954 EX(call) = call;
3955
3956 ZEND_VM_NEXT_OPCODE();
3957 }
3958
3959 ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
3960 {
3961 USE_OPLINE
3962 zval *func_name;
3963 zval *func;
3964 zend_function *fbc;
3965 zend_execute_data *call;
3966
3967 fbc = CACHED_PTR(opline->result.num);
3968 if (UNEXPECTED(fbc == NULL)) {
3969 func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3970 func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3971 if (func == NULL) {
3972 func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3973 if (UNEXPECTED(func == NULL)) {
3974 ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
3975 }
3976 }
3977 fbc = Z_FUNC_P(func);
3978 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3979 init_func_run_time_cache(&fbc->op_array);
3980 }
3981 CACHE_PTR(opline->result.num, fbc);
3982 }
3983
3984 call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
3985 fbc, opline->extended_value, NULL);
3986 call->prev_execute_data = EX(call);
3987 EX(call) = call;
3988
3989 ZEND_VM_NEXT_OPCODE();
3990 }
3991
3992 ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
3993 {
3994 USE_OPLINE
3995 zval *fname;
3996 zval *func;
3997 zend_function *fbc;
3998 zend_execute_data *call;
3999
4000 fbc = CACHED_PTR(opline->result.num);
4001 if (UNEXPECTED(fbc == NULL)) {
4002 fname = (zval*)RT_CONSTANT(opline, opline->op2);
4003 func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
4004 ZEND_ASSERT(func != NULL && "Function existence must be checked at compile time");
4005 fbc = Z_FUNC_P(func);
4006 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4007 init_func_run_time_cache(&fbc->op_array);
4008 }
4009 CACHE_PTR(opline->result.num, fbc);
4010 }
4011
4012 call = _zend_vm_stack_push_call_frame_ex(
4013 opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
4014 fbc, opline->extended_value, NULL);
4015 call->prev_execute_data = EX(call);
4016 EX(call) = call;
4017
4018 ZEND_VM_NEXT_OPCODE();
4019 }
4020
4021 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_INIT_FCALL, Z_EXTRA_P(RT_CONSTANT(op, op->op2)) != 0, ZEND_INIT_FCALL_OFFSET, NUM, CONST, NUM|CACHE_SLOT)
4022 {
4023 USE_OPLINE
4024 zend_function *fbc;
4025 zend_execute_data *call;
4026 fbc = CACHED_PTR(opline->result.num);
4027 if (UNEXPECTED(fbc == NULL)) {
4028 fbc = Z_PTR(EG(function_table)->arData[Z_EXTRA_P(RT_CONSTANT(opline, opline->op2))].val);
4029 CACHE_PTR(opline->result.num, fbc);
4030 }
4031 call = _zend_vm_stack_push_call_frame_ex(
4032 opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
4033 fbc, opline->extended_value, NULL);
4034 call->prev_execute_data = EX(call);
4035 EX(call) = call;
4036 ZEND_VM_NEXT_OPCODE();
4037 }
4038
4039 ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
4040 {
4041 USE_OPLINE
4042 zend_execute_data *call = EX(call);
4043 zend_function *fbc = call->func;
4044 zval *ret;
4045 zval retval;
4046
4047 SAVE_OPLINE();
4048 EX(call) = call->prev_execute_data;
4049
4050 call->prev_execute_data = execute_data;
4051 EG(current_execute_data) = call;
4052
4053 #if ZEND_DEBUG
4054 bool should_throw = zend_internal_call_should_throw(fbc, call);
4055 #endif
4056
4057 ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
4058 ZVAL_NULL(ret);
4059
4060 ZEND_OBSERVER_FCALL_BEGIN(call);
4061 fbc->internal_function.handler(call, ret);
4062
4063 #if ZEND_DEBUG
4064 if (!EG(exception) && call->func) {
4065 if (should_throw) {
4066 zend_internal_call_arginfo_violation(call->func);
4067 }
4068 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
4069 zend_verify_internal_return_type(call->func, ret));
4070 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
4071 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
4072 zend_verify_internal_func_info(call->func, ret);
4073 }
4074 #endif
4075 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
4076 ZEND_VM_FCALL_INTERRUPT_CHECK(call);
4077
4078 EG(current_execute_data) = execute_data;
4079 zend_vm_stack_free_args(call);
4080
4081 uint32_t call_info = ZEND_CALL_INFO(call);
4082 if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) {
4083 if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
4084 zend_free_extra_named_params(call->extra_named_params);
4085 }
4086 zend_vm_stack_free_call_frame_ex(call_info, call);
4087 } else {
4088 EG(vm_stack_top) = (zval*)call;
4089 }
4090
4091 if (!RETURN_VALUE_USED(opline)) {
4092 i_zval_ptr_dtor(ret);
4093 }
4094
4095 if (UNEXPECTED(EG(exception) != NULL)) {
4096 zend_rethrow_exception(execute_data);
4097 HANDLE_EXCEPTION();
4098 }
4099
4100 ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1);
4101 ZEND_VM_CONTINUE();
4102 }
4103
4104 ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
4105 {
4106 USE_OPLINE
4107 zend_execute_data *call = EX(call);
4108 zend_function *fbc = call->func;
4109 zval *ret;
4110
4111 SAVE_OPLINE();
4112 EX(call) = call->prev_execute_data;
4113
4114 ret = NULL;
4115 if (RETURN_VALUE_USED(opline)) {
4116 ret = EX_VAR(opline->result.var);
4117 }
4118
4119 call->prev_execute_data = execute_data;
4120 execute_data = call;
4121 i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
4122 LOAD_OPLINE_EX();
4123 ZEND_OBSERVER_SAVE_OPLINE();
4124 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4125
4126 ZEND_VM_ENTER_EX();
4127 }
4128
4129 ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
4130 {
4131 USE_OPLINE
4132 zend_execute_data *call = EX(call);
4133 zend_function *fbc = call->func;
4134 zval *ret;
4135 zval retval;
4136
4137 SAVE_OPLINE();
4138 EX(call) = call->prev_execute_data;
4139
4140 if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
4141 zend_deprecated_function(fbc);
4142 if (UNEXPECTED(EG(exception) != NULL)) {
4143 UNDEF_RESULT();
4144 if (!RETURN_VALUE_USED(opline)) {
4145 ret = &retval;
4146 ZVAL_UNDEF(ret);
4147 }
4148 ZEND_VM_C_GOTO(fcall_by_name_end);
4149 }
4150 }
4151
4152 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
4153 ret = NULL;
4154 if (RETURN_VALUE_USED(opline)) {
4155 ret = EX_VAR(opline->result.var);
4156 }
4157
4158 call->prev_execute_data = execute_data;
4159 execute_data = call;
4160 i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
4161 LOAD_OPLINE_EX();
4162 ZEND_OBSERVER_SAVE_OPLINE();
4163 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4164
4165 ZEND_VM_ENTER_EX();
4166 } else {
4167 ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
4168 if (ZEND_OBSERVER_ENABLED) {
4169 ret = NULL;
4170 }
4171
4172 call->prev_execute_data = execute_data;
4173 EG(current_execute_data) = call;
4174
4175 #if ZEND_DEBUG
4176 bool should_throw = zend_internal_call_should_throw(fbc, call);
4177 #endif
4178
4179 ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
4180 ZVAL_NULL(ret);
4181
4182 ZEND_OBSERVER_FCALL_BEGIN(call);
4183 fbc->internal_function.handler(call, ret);
4184
4185 #if ZEND_DEBUG
4186 if (!EG(exception) && call->func) {
4187 if (should_throw) {
4188 zend_internal_call_arginfo_violation(call->func);
4189 }
4190 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
4191 zend_verify_internal_return_type(call->func, ret));
4192 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
4193 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
4194 zend_verify_internal_func_info(call->func, ret);
4195 }
4196 #endif
4197 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
4198 ZEND_VM_FCALL_INTERRUPT_CHECK(call);
4199
4200 EG(current_execute_data) = execute_data;
4201
4202 ZEND_VM_C_GOTO(fcall_by_name_end);
4203 }
4204
4205 if (0) {
4206 ZEND_VM_C_LABEL(fcall_by_name_end):
4207
4208 zend_vm_stack_free_args(call);
4209
4210 uint32_t call_info = ZEND_CALL_INFO(call);
4211 if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) {
4212 if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
4213 zend_free_extra_named_params(call->extra_named_params);
4214 }
4215 zend_vm_stack_free_call_frame_ex(call_info, call);
4216 } else {
4217 EG(vm_stack_top) = (zval*)call;
4218 }
4219
4220 if (!RETURN_VALUE_USED(opline)) {
4221 i_zval_ptr_dtor(ret);
4222 }
4223 }
4224
4225 if (UNEXPECTED(EG(exception) != NULL)) {
4226 zend_rethrow_exception(execute_data);
4227 HANDLE_EXCEPTION();
4228 }
4229 ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1);
4230 ZEND_VM_CONTINUE();
4231 }
4232
4233 ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
4234 {
4235 USE_OPLINE
4236 zend_execute_data *call = EX(call);
4237 zend_function *fbc = call->func;
4238 zval *ret;
4239 zval retval;
4240
4241 SAVE_OPLINE();
4242 EX(call) = call->prev_execute_data;
4243
4244 if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
4245 zend_deprecated_function(fbc);
4246 if (UNEXPECTED(EG(exception) != NULL)) {
4247 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) {
4248 OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
4249 }
4250 UNDEF_RESULT();
4251 if (!RETURN_VALUE_USED(opline)) {
4252 ret = &retval;
4253 ZVAL_UNDEF(ret);
4254 }
4255 ZEND_VM_C_GOTO(fcall_end);
4256 }
4257 }
4258
4259 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
4260 ret = NULL;
4261 if (RETURN_VALUE_USED(opline)) {
4262 ret = EX_VAR(opline->result.var);
4263 }
4264
4265 call->prev_execute_data = execute_data;
4266 execute_data = call;
4267 i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
4268
4269 if (EXPECTED(zend_execute_ex == execute_ex)) {
4270 LOAD_OPLINE_EX();
4271 ZEND_OBSERVER_SAVE_OPLINE();
4272 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4273 ZEND_VM_ENTER_EX();
4274 } else {
4275 SAVE_OPLINE_EX();
4276 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4277 execute_data = EX(prev_execute_data);
4278 LOAD_OPLINE();
4279 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
4280 zend_execute_ex(call);
4281 }
4282 } else {
4283 ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
4284 if (ZEND_OBSERVER_ENABLED) {
4285 ret = NULL;
4286 }
4287
4288 call->prev_execute_data = execute_data;
4289 EG(current_execute_data) = call;
4290
4291 #if ZEND_DEBUG
4292 bool should_throw = zend_internal_call_should_throw(fbc, call);
4293 #endif
4294
4295 ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
4296 ZVAL_NULL(ret);
4297
4298 ZEND_OBSERVER_FCALL_BEGIN(call);
4299 if (!zend_execute_internal) {
4300 /* saves one function call if zend_execute_internal is not used */
4301 fbc->internal_function.handler(call, ret);
4302 } else {
4303 zend_execute_internal(call, ret);
4304 }
4305
4306 #if ZEND_DEBUG
4307 if (!EG(exception) && call->func && !(call->func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE)) {
4308 if (should_throw) {
4309 zend_internal_call_arginfo_violation(call->func);
4310 }
4311 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
4312 zend_verify_internal_return_type(call->func, ret));
4313 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
4314 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
4315 zend_verify_internal_func_info(call->func, ret);
4316 }
4317 #endif
4318 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
4319 ZEND_VM_FCALL_INTERRUPT_CHECK(call);
4320
4321 EG(current_execute_data) = execute_data;
4322
4323 ZEND_VM_C_GOTO(fcall_end);
4324 }
4325
4326 if (0) {
4327 ZEND_VM_C_LABEL(fcall_end):
4328
4329 zend_vm_stack_free_args(call);
4330 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
4331 zend_free_extra_named_params(call->extra_named_params);
4332 }
4333
4334 if (!RETURN_VALUE_USED(opline)) {
4335 i_zval_ptr_dtor(ret);
4336 }
4337 }
4338
4339 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
4340 OBJ_RELEASE(Z_OBJ(call->This));
4341 }
4342
4343 zend_vm_stack_free_call_frame(call);
4344 if (UNEXPECTED(EG(exception) != NULL)) {
4345 zend_rethrow_exception(execute_data);
4346 HANDLE_EXCEPTION();
4347 }
4348 ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1);
4349 ZEND_VM_CONTINUE();
4350 }
4351
4352 ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED|CACHE_SLOT)
4353 {
4354 if (OP1_TYPE == IS_UNUSED) {
4355 SAVE_OPLINE();
4356 zend_verify_missing_return_type(EX(func));
4357 HANDLE_EXCEPTION();
4358 } else {
4359 /* prevents "undefined variable opline" errors */
4360 #if !ZEND_VM_SPEC || (OP1_TYPE != IS_UNUSED)
4361 USE_OPLINE
4362 zval *retval_ref, *retval_ptr;
4363 zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
4364 retval_ref = retval_ptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4365
4366 if (OP1_TYPE == IS_CONST) {
4367 ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
4368 retval_ref = retval_ptr = EX_VAR(opline->result.var);
4369 } else if (OP1_TYPE == IS_VAR) {
4370 if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) {
4371 retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr);
4372 }
4373 ZVAL_DEREF(retval_ptr);
4374 } else if (OP1_TYPE == IS_CV) {
4375 ZVAL_DEREF(retval_ptr);
4376 }
4377
4378 if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) {
4379 ZEND_VM_NEXT_OPCODE();
4380 }
4381
4382 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
4383 SAVE_OPLINE();
4384 retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
4385 if (UNEXPECTED(EG(exception))) {
4386 HANDLE_EXCEPTION();
4387 }
4388 if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
4389 ZEND_VM_NEXT_OPCODE();
4390 }
4391 }
4392
4393 zend_reference *ref = NULL;
4394 void *cache_slot = CACHE_ADDR(opline->op2.num);
4395 if (UNEXPECTED(retval_ref != retval_ptr)) {
4396 if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
4397 ref = Z_REF_P(retval_ref);
4398 } else {
4399 /* A cast might happen - unwrap the reference if this is a by-value return */
4400 if (Z_REFCOUNT_P(retval_ref) == 1) {
4401 ZVAL_UNREF(retval_ref);
4402 } else {
4403 Z_DELREF_P(retval_ref);
4404 ZVAL_COPY(retval_ref, retval_ptr);
4405 }
4406 retval_ptr = retval_ref;
4407 }
4408 }
4409
4410 SAVE_OPLINE();
4411 if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) {
4412 zend_verify_return_error(EX(func), retval_ptr);
4413 HANDLE_EXCEPTION();
4414 }
4415 ZEND_VM_NEXT_OPCODE();
4416 #endif
4417 }
4418 }
4419
4420 ZEND_VM_COLD_HANDLER(201, ZEND_VERIFY_NEVER_TYPE, UNUSED, UNUSED)
4421 {
4422 SAVE_OPLINE();
4423 zend_verify_never_error(EX(func));
4424 HANDLE_EXCEPTION();
4425 }
4426
4427 ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER))
4428 {
4429 USE_OPLINE
4430 zval *retval_ptr;
4431 zval *return_value;
4432 ZEND_OBSERVER_USE_RETVAL;
4433
4434 retval_ptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4435 return_value = EX(return_value);
4436 ZEND_OBSERVER_SET_RETVAL();
4437 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
4438 SAVE_OPLINE();
4439 retval_ptr = ZVAL_UNDEFINED_OP1();
4440 if (return_value) {
4441 ZVAL_NULL(return_value);
4442 }
4443 } else if (!return_value) {
4444 if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
4445 if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) {
4446 SAVE_OPLINE();
4447 rc_dtor_func(Z_COUNTED_P(retval_ptr));
4448 }
4449 }
4450 } else {
4451 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
4452 ZVAL_COPY_VALUE(return_value, retval_ptr);
4453 if (OP1_TYPE == IS_CONST) {
4454 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) {
4455 Z_ADDREF_P(return_value);
4456 }
4457 }
4458 } else if (OP1_TYPE == IS_CV) {
4459 do {
4460 if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
4461 if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) {
4462 if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) {
4463 zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
4464 ZVAL_COPY_VALUE(return_value, retval_ptr);
4465 if (GC_MAY_LEAK(ref)) {
4466 SAVE_OPLINE();
4467 gc_possible_root(ref);
4468 }
4469 ZVAL_NULL(retval_ptr);
4470 break;
4471 } else {
4472 Z_ADDREF_P(retval_ptr);
4473 }
4474 } else {
4475 retval_ptr = Z_REFVAL_P(retval_ptr);
4476 if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
4477 Z_ADDREF_P(retval_ptr);
4478 }
4479 }
4480 }
4481 ZVAL_COPY_VALUE(return_value, retval_ptr);
4482 } while (0);
4483 } else /* if (OP1_TYPE == IS_VAR) */ {
4484 if (UNEXPECTED(Z_ISREF_P(retval_ptr))) {
4485 zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
4486
4487 retval_ptr = Z_REFVAL_P(retval_ptr);
4488 ZVAL_COPY_VALUE(return_value, retval_ptr);
4489 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4490 efree_size(ref, sizeof(zend_reference));
4491 } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
4492 Z_ADDREF_P(retval_ptr);
4493 }
4494 } else {
4495 ZVAL_COPY_VALUE(return_value, retval_ptr);
4496 }
4497 }
4498 }
4499 ZEND_OBSERVER_SAVE_OPLINE();
4500 ZEND_OBSERVER_FCALL_END(execute_data, return_value);
4501 ZEND_OBSERVER_FREE_RETVAL();
4502 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
4503 }
4504
4505 ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, SPEC(OBSERVER))
4506 {
4507 USE_OPLINE
4508 zval *retval_ptr;
4509 zval *return_value;
4510 ZEND_OBSERVER_USE_RETVAL;
4511
4512 SAVE_OPLINE();
4513
4514 return_value = EX(return_value);
4515 ZEND_OBSERVER_SET_RETVAL();
4516 do {
4517 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR)) ||
4518 (OP1_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) {
4519 /* Not supposed to happen, but we'll allow it */
4520 zend_error(E_NOTICE, "Only variable references should be returned by reference");
4521
4522 retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4523 if (!return_value) {
4524 FREE_OP1();
4525 } else {
4526 if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) {
4527 ZVAL_COPY_VALUE(return_value, retval_ptr);
4528 break;
4529 }
4530
4531 ZVAL_NEW_REF(return_value, retval_ptr);
4532 if (OP1_TYPE == IS_CONST) {
4533 Z_TRY_ADDREF_P(retval_ptr);
4534 }
4535 }
4536 break;
4537 }
4538
4539 retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
4540
4541 if (OP1_TYPE == IS_VAR) {
4542 ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval));
4543 if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) {
4544 zend_error(E_NOTICE, "Only variable references should be returned by reference");
4545 if (return_value) {
4546 ZVAL_NEW_REF(return_value, retval_ptr);
4547 } else {
4548 FREE_OP1();
4549 }
4550 break;
4551 }
4552 }
4553
4554 if (return_value) {
4555 if (Z_ISREF_P(retval_ptr)) {
4556 Z_ADDREF_P(retval_ptr);
4557 } else {
4558 ZVAL_MAKE_REF_EX(retval_ptr, 2);
4559 }
4560 ZVAL_REF(return_value, Z_REF_P(retval_ptr));
4561 }
4562
4563 FREE_OP1();
4564 } while (0);
4565
4566 ZEND_OBSERVER_FCALL_END(execute_data, return_value);
4567 ZEND_OBSERVER_FREE_RETVAL();
4568 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
4569 }
4570
4571 ZEND_VM_HANDLER(139, ZEND_GENERATOR_CREATE, ANY, ANY)
4572 {
4573 zval *return_value = EX(return_value);
4574
4575 if (EXPECTED(return_value)) {
4576 USE_OPLINE
4577 zend_generator *generator;
4578 zend_execute_data *gen_execute_data;
4579 uint32_t num_args, used_stack, call_info;
4580
4581 SAVE_OPLINE();
4582 object_init_ex(return_value, zend_ce_generator);
4583
4584 /*
4585 * Normally the execute_data is allocated on the VM stack (because it does
4586 * not actually do any allocation and thus is faster). For generators
4587 * though this behavior would be suboptimal, because the (rather large)
4588 * structure would have to be copied back and forth every time execution is
4589 * suspended or resumed. That's why for generators the execution context
4590 * is allocated on heap.
4591 */
4592 num_args = EX_NUM_ARGS();
4593 if (EXPECTED(num_args <= EX(func)->op_array.num_args)) {
4594 used_stack = (ZEND_CALL_FRAME_SLOT + EX(func)->op_array.last_var + EX(func)->op_array.T) * sizeof(zval);
4595 gen_execute_data = (zend_execute_data*)emalloc(used_stack);
4596 used_stack = (ZEND_CALL_FRAME_SLOT + EX(func)->op_array.last_var) * sizeof(zval);
4597 } else {
4598 used_stack = (ZEND_CALL_FRAME_SLOT + num_args + EX(func)->op_array.last_var + EX(func)->op_array.T - EX(func)->op_array.num_args) * sizeof(zval);
4599 gen_execute_data = (zend_execute_data*)emalloc(used_stack);
4600 }
4601 memcpy(gen_execute_data, execute_data, used_stack);
4602
4603 /* Save execution context in generator object. */
4604 generator = (zend_generator *) Z_OBJ_P(EX(return_value));
4605 generator->func = gen_execute_data->func;
4606 generator->execute_data = gen_execute_data;
4607 generator->frozen_call_stack = NULL;
4608 generator->execute_fake.opline = NULL;
4609 generator->execute_fake.func = NULL;
4610 generator->execute_fake.prev_execute_data = NULL;
4611 ZVAL_OBJ(&generator->execute_fake.This, (zend_object *) generator);
4612
4613 gen_execute_data->opline = opline;
4614 /* EX(return_value) keeps pointer to zend_object (not a real zval) */
4615 gen_execute_data->return_value = (zval*)generator;
4616 call_info = Z_TYPE_INFO(EX(This));
4617 if ((call_info & Z_TYPE_MASK) == IS_OBJECT
4618 && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS))
4619 /* Bug #72523 */
4620 || UNEXPECTED(zend_execute_ex != execute_ex))) {
4621 ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS);
4622 Z_ADDREF(gen_execute_data->This);
4623 }
4624 ZEND_ADD_CALL_FLAG_EX(call_info, (ZEND_CALL_TOP_FUNCTION | ZEND_CALL_ALLOCATED | ZEND_CALL_GENERATOR));
4625 Z_TYPE_INFO(gen_execute_data->This) = call_info;
4626 gen_execute_data->prev_execute_data = NULL;
4627
4628 call_info = EX_CALL_INFO();
4629 EG(current_execute_data) = EX(prev_execute_data);
4630 if (EXPECTED(!(call_info & (ZEND_CALL_TOP|ZEND_CALL_ALLOCATED)))) {
4631 EG(vm_stack_top) = (zval*)execute_data;
4632 execute_data = EX(prev_execute_data);
4633 LOAD_NEXT_OPLINE();
4634 ZEND_VM_LEAVE();
4635 } else if (EXPECTED(!(call_info & ZEND_CALL_TOP))) {
4636 zend_execute_data *old_execute_data = execute_data;
4637 execute_data = EX(prev_execute_data);
4638 zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
4639 LOAD_NEXT_OPLINE();
4640 ZEND_VM_LEAVE();
4641 } else {
4642 ZEND_VM_RETURN();
4643 }
4644 } else {
4645 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
4646 }
4647 }
4648
4649 ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER))
4650 {
4651 USE_OPLINE
4652 zval *retval;
4653
4654 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
4655
4656 SAVE_OPLINE();
4657 retval = GET_OP1_ZVAL_PTR(BP_VAR_R);
4658
4659 /* Copy return value into generator->retval */
4660 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
4661 ZVAL_COPY_VALUE(&generator->retval, retval);
4662 if (OP1_TYPE == IS_CONST) {
4663 if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) {
4664 Z_ADDREF(generator->retval);
4665 }
4666 }
4667 } else if (OP1_TYPE == IS_CV) {
4668 ZVAL_COPY_DEREF(&generator->retval, retval);
4669 } else /* if (OP1_TYPE == IS_VAR) */ {
4670 if (UNEXPECTED(Z_ISREF_P(retval))) {
4671 zend_refcounted *ref = Z_COUNTED_P(retval);
4672
4673 retval = Z_REFVAL_P(retval);
4674 ZVAL_COPY_VALUE(&generator->retval, retval);
4675 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4676 efree_size(ref, sizeof(zend_reference));
4677 } else if (Z_OPT_REFCOUNTED_P(retval)) {
4678 Z_ADDREF_P(retval);
4679 }
4680 } else {
4681 ZVAL_COPY_VALUE(&generator->retval, retval);
4682 }
4683 }
4684
4685 ZEND_OBSERVER_FCALL_END(generator->execute_data, &generator->retval);
4686
4687 EG(current_execute_data) = EX(prev_execute_data);
4688
4689 /* Close the generator to free up resources */
4690 zend_generator_close(generator, 1);
4691
4692 /* Pass execution back to handling code */
4693 ZEND_VM_RETURN();
4694 }
4695
4696 ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMPVAR|CV, ANY)
4697 {
4698 USE_OPLINE
4699 zval *value;
4700
4701 SAVE_OPLINE();
4702 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4703
4704 do {
4705 if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
4706 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
4707 value = Z_REFVAL_P(value);
4708 if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
4709 break;
4710 }
4711 }
4712 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
4713 ZVAL_UNDEFINED_OP1();
4714 if (UNEXPECTED(EG(exception) != NULL)) {
4715 HANDLE_EXCEPTION();
4716 }
4717 }
4718 zend_throw_error(NULL, "Can only throw objects");
4719 FREE_OP1();
4720 HANDLE_EXCEPTION();
4721 }
4722 } while (0);
4723
4724 zend_exception_save();
4725 Z_TRY_ADDREF_P(value);
4726 zend_throw_exception_object(value);
4727 zend_exception_restore();
4728 FREE_OP1();
4729 HANDLE_EXCEPTION();
4730 }
4731
4732 ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, JMP_ADDR, LAST_CATCH|CACHE_SLOT)
4733 {
4734 USE_OPLINE
4735 zend_class_entry *ce, *catch_ce;
4736 zend_object *exception;
4737
4738 SAVE_OPLINE();
4739 /* Check whether an exception has been thrown, if not, jump over code */
4740 zend_exception_restore();
4741 if (EG(exception) == NULL) {
4742 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
4743 }
4744 catch_ce = CACHED_PTR(opline->extended_value & ~ZEND_LAST_CATCH);
4745 if (UNEXPECTED(catch_ce == NULL)) {
4746 catch_ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD | ZEND_FETCH_CLASS_SILENT);
4747
4748 CACHE_PTR(opline->extended_value & ~ZEND_LAST_CATCH, catch_ce);
4749 }
4750 ce = EG(exception)->ce;
4751
4752 #ifdef HAVE_DTRACE
4753 if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
4754 DTRACE_EXCEPTION_CAUGHT((char *)ce->name);
4755 }
4756 #endif /* HAVE_DTRACE */
4757
4758 if (ce != catch_ce) {
4759 if (!catch_ce || !instanceof_function(ce, catch_ce)) {
4760 if (opline->extended_value & ZEND_LAST_CATCH) {
4761 zend_rethrow_exception(execute_data);
4762 HANDLE_EXCEPTION();
4763 }
4764 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
4765 }
4766 }
4767
4768 exception = EG(exception);
4769 EG(exception) = NULL;
4770 if (RETURN_VALUE_USED(opline)) {
4771 /* Always perform a strict assignment. There is a reasonable expectation that if you
4772 * write "catch (Exception $e)" then $e will actually be instanceof Exception. As such,
4773 * we should not permit coercion to string here. */
4774 zval tmp;
4775 ZVAL_OBJ(&tmp, exception);
4776 zend_assign_to_variable(EX_VAR(opline->result.var), &tmp, IS_TMP_VAR, /* strict */ 1);
4777 } else {
4778 OBJ_RELEASE(exception);
4779 }
4780 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4781 }
4782
4783 ZEND_VM_HOT_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, CONST|UNUSED|NUM)
4784 {
4785 USE_OPLINE
4786 zval *value, *arg;
4787
4788 if (OP2_TYPE == IS_CONST) {
4789 SAVE_OPLINE();
4790 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4791 uint32_t arg_num;
4792 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4793 if (UNEXPECTED(!arg)) {
4794 FREE_OP1();
4795 HANDLE_EXCEPTION();
4796 }
4797 } else {
4798 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4799 }
4800
4801 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
4802 ZVAL_COPY_VALUE(arg, value);
4803 if (OP1_TYPE == IS_CONST) {
4804 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) {
4805 Z_ADDREF_P(arg);
4806 }
4807 }
4808 ZEND_VM_NEXT_OPCODE();
4809 }
4810
ZEND_VM_COLD_HELPER(zend_cannot_pass_by_ref_helper,ANY,ANY,uint32_t _arg_num,zval * _arg)4811 ZEND_VM_COLD_HELPER(zend_cannot_pass_by_ref_helper, ANY, ANY, uint32_t _arg_num, zval *_arg)
4812 {
4813 USE_OPLINE
4814
4815 SAVE_OPLINE();
4816
4817 zend_cannot_pass_by_reference(_arg_num);
4818 FREE_OP1();
4819 ZVAL_UNDEF(_arg);
4820 HANDLE_EXCEPTION();
4821 }
4822
4823 ZEND_VM_HOT_SEND_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
4824 {
4825 USE_OPLINE
4826 zval *value, *arg;
4827 uint32_t arg_num;
4828
4829 if (OP2_TYPE == IS_CONST) {
4830 SAVE_OPLINE();
4831 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4832 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4833 if (UNEXPECTED(!arg)) {
4834 FREE_OP1();
4835 HANDLE_EXCEPTION();
4836 }
4837 } else {
4838 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4839 arg_num = opline->op2.num;
4840 }
4841
4842 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
4843 if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4844 ZEND_VM_C_GOTO(send_val_by_ref);
4845 }
4846 } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4847 ZEND_VM_C_LABEL(send_val_by_ref):
4848 ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper, _arg_num, arg_num, _arg, arg);
4849 }
4850 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
4851 ZVAL_COPY_VALUE(arg, value);
4852 if (OP1_TYPE == IS_CONST) {
4853 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) {
4854 Z_ADDREF_P(arg);
4855 }
4856 }
4857 ZEND_VM_NEXT_OPCODE();
4858 }
4859
4860 ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, CONST|UNUSED|NUM)
4861 {
4862 USE_OPLINE
4863 zval *varptr, *arg;
4864
4865 if (OP2_TYPE == IS_CONST) {
4866 SAVE_OPLINE();
4867 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4868 uint32_t arg_num;
4869 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4870 if (UNEXPECTED(!arg)) {
4871 FREE_OP1();
4872 HANDLE_EXCEPTION();
4873 }
4874 } else {
4875 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4876 }
4877
4878 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4879 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
4880 SAVE_OPLINE();
4881 ZVAL_UNDEFINED_OP1();
4882 ZVAL_NULL(arg);
4883 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4884 }
4885
4886 if (OP1_TYPE == IS_CV) {
4887 ZVAL_COPY_DEREF(arg, varptr);
4888 } else /* if (OP1_TYPE == IS_VAR) */ {
4889 if (UNEXPECTED(Z_ISREF_P(varptr))) {
4890 zend_refcounted *ref = Z_COUNTED_P(varptr);
4891
4892 varptr = Z_REFVAL_P(varptr);
4893 ZVAL_COPY_VALUE(arg, varptr);
4894 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4895 efree_size(ref, sizeof(zend_reference));
4896 } else if (Z_OPT_REFCOUNTED_P(arg)) {
4897 Z_ADDREF_P(arg);
4898 }
4899 } else {
4900 ZVAL_COPY_VALUE(arg, varptr);
4901 }
4902 }
4903
4904 ZEND_VM_NEXT_OPCODE();
4905 }
4906
4907 ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, CONST|UNUSED|NUM)
4908 {
4909 USE_OPLINE
4910 zval *varptr, *arg;
4911
4912 if (OP2_TYPE == IS_CONST) {
4913 SAVE_OPLINE();
4914 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4915 uint32_t arg_num;
4916 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4917 if (UNEXPECTED(!arg)) {
4918 FREE_OP1();
4919 HANDLE_EXCEPTION();
4920 }
4921 } else {
4922 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4923 }
4924
4925 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4926 ZVAL_COPY_VALUE(arg, varptr);
4927
4928 if (EXPECTED(Z_ISREF_P(varptr))) {
4929 ZEND_VM_NEXT_OPCODE();
4930 }
4931
4932 SAVE_OPLINE();
4933 ZVAL_NEW_REF(arg, arg);
4934 zend_error(E_NOTICE, "Only variables should be passed by reference");
4935 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4936 }
4937
4938 ZEND_VM_HOT_SEND_HANDLER(50, ZEND_SEND_VAR_NO_REF_EX, VAR, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
4939 {
4940 USE_OPLINE
4941 zval *varptr, *arg;
4942 uint32_t arg_num;
4943
4944 if (OP2_TYPE == IS_CONST) {
4945 SAVE_OPLINE();
4946 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4947 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4948 if (UNEXPECTED(!arg)) {
4949 FREE_OP1();
4950 HANDLE_EXCEPTION();
4951 }
4952 } else {
4953 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4954 arg_num = opline->op2.num;
4955 }
4956
4957 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
4958 if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4959 ZEND_VM_C_GOTO(send_var);
4960 }
4961
4962 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4963 ZVAL_COPY_VALUE(arg, varptr);
4964
4965 if (EXPECTED(Z_ISREF_P(varptr) ||
4966 QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) {
4967 ZEND_VM_NEXT_OPCODE();
4968 }
4969 } else {
4970 if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4971 ZEND_VM_C_GOTO(send_var);
4972 }
4973
4974 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4975 ZVAL_COPY_VALUE(arg, varptr);
4976
4977 if (EXPECTED(Z_ISREF_P(varptr) ||
4978 ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) {
4979 ZEND_VM_NEXT_OPCODE();
4980 }
4981 }
4982
4983 SAVE_OPLINE();
4984 ZVAL_NEW_REF(arg, arg);
4985 zend_error(E_NOTICE, "Only variables should be passed by reference");
4986 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4987
4988 ZEND_VM_C_LABEL(send_var):
4989 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4990 if (UNEXPECTED(Z_ISREF_P(varptr))) {
4991 zend_refcounted *ref = Z_COUNTED_P(varptr);
4992
4993 varptr = Z_REFVAL_P(varptr);
4994 ZVAL_COPY_VALUE(arg, varptr);
4995 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4996 efree_size(ref, sizeof(zend_reference));
4997 } else if (Z_OPT_REFCOUNTED_P(arg)) {
4998 Z_ADDREF_P(arg);
4999 }
5000 } else {
5001 ZVAL_COPY_VALUE(arg, varptr);
5002 }
5003 ZEND_VM_NEXT_OPCODE();
5004 }
5005
5006 ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, CONST|UNUSED|NUM)
5007 {
5008 USE_OPLINE
5009 zval *varptr, *arg;
5010
5011 SAVE_OPLINE();
5012 if (OP2_TYPE == IS_CONST) {
5013 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5014 uint32_t arg_num;
5015 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
5016 if (UNEXPECTED(!arg)) {
5017 FREE_OP1();
5018 HANDLE_EXCEPTION();
5019 }
5020 } else {
5021 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
5022 }
5023
5024 varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
5025 if (Z_ISREF_P(varptr)) {
5026 Z_ADDREF_P(varptr);
5027 } else {
5028 ZVAL_MAKE_REF_EX(varptr, 2);
5029 }
5030 ZVAL_REF(arg, Z_REF_P(varptr));
5031
5032 FREE_OP1();
5033 ZEND_VM_NEXT_OPCODE();
5034 }
5035
5036 ZEND_VM_HOT_SEND_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
5037 {
5038 USE_OPLINE
5039 zval *varptr, *arg;
5040 uint32_t arg_num;
5041
5042 if (OP2_TYPE == IS_CONST) {
5043 SAVE_OPLINE();
5044 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5045 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
5046 if (UNEXPECTED(!arg)) {
5047 FREE_OP1();
5048 HANDLE_EXCEPTION();
5049 }
5050 } else {
5051 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
5052 arg_num = opline->op2.num;
5053 }
5054
5055 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
5056 if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5057 ZEND_VM_C_GOTO(send_var_by_ref);
5058 }
5059 } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5060 ZEND_VM_C_LABEL(send_var_by_ref):
5061 varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
5062 if (Z_ISREF_P(varptr)) {
5063 Z_ADDREF_P(varptr);
5064 } else {
5065 ZVAL_MAKE_REF_EX(varptr, 2);
5066 }
5067 ZVAL_REF(arg, Z_REF_P(varptr));
5068
5069 FREE_OP1();
5070 ZEND_VM_NEXT_OPCODE();
5071 }
5072
5073 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5074 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
5075 SAVE_OPLINE();
5076 ZVAL_UNDEFINED_OP1();
5077 ZVAL_NULL(arg);
5078 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5079 }
5080
5081 if (OP1_TYPE == IS_CV) {
5082 ZVAL_COPY_DEREF(arg, varptr);
5083 } else /* if (OP1_TYPE == IS_VAR) */ {
5084 if (UNEXPECTED(Z_ISREF_P(varptr))) {
5085 zend_refcounted *ref = Z_COUNTED_P(varptr);
5086
5087 varptr = Z_REFVAL_P(varptr);
5088 ZVAL_COPY_VALUE(arg, varptr);
5089 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
5090 efree_size(ref, sizeof(zend_reference));
5091 } else if (Z_OPT_REFCOUNTED_P(arg)) {
5092 Z_ADDREF_P(arg);
5093 }
5094 } else {
5095 ZVAL_COPY_VALUE(arg, varptr);
5096 }
5097 }
5098
5099 ZEND_VM_NEXT_OPCODE();
5100 }
5101
5102 ZEND_VM_HOT_SEND_HANDLER(100, ZEND_CHECK_FUNC_ARG, UNUSED, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
5103 {
5104 USE_OPLINE
5105 uint32_t arg_num;
5106
5107 if (OP2_TYPE == IS_CONST) {
5108 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5109 arg_num = zend_get_arg_offset_by_name(
5110 EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1;
5111 if (UNEXPECTED(arg_num == 0)) {
5112 /* Treat this as a by-value argument, and throw an error during SEND. */
5113 ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5114 ZEND_VM_NEXT_OPCODE();
5115 }
5116 } else {
5117 arg_num = opline->op2.num;
5118 }
5119
5120 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
5121 if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5122 ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5123 } else {
5124 ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5125 }
5126 } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5127 ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5128 } else {
5129 ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5130 }
5131 ZEND_VM_NEXT_OPCODE();
5132 }
5133
5134 ZEND_VM_HOT_HANDLER(185, ZEND_SEND_FUNC_ARG, VAR, CONST|UNUSED|NUM)
5135 {
5136 USE_OPLINE
5137 zval *varptr, *arg;
5138
5139 if (OP2_TYPE == IS_CONST) {
5140 // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG?
5141 SAVE_OPLINE();
5142 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5143 uint32_t arg_num;
5144 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
5145 if (UNEXPECTED(!arg)) {
5146 FREE_OP1();
5147 HANDLE_EXCEPTION();
5148 }
5149 } else {
5150 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
5151 }
5152
5153 if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
5154 varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
5155 if (Z_ISREF_P(varptr)) {
5156 Z_ADDREF_P(varptr);
5157 } else {
5158 ZVAL_MAKE_REF_EX(varptr, 2);
5159 }
5160 ZVAL_REF(arg, Z_REF_P(varptr));
5161
5162 FREE_OP1();
5163 ZEND_VM_NEXT_OPCODE();
5164 }
5165
5166 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5167
5168 if (UNEXPECTED(Z_ISREF_P(varptr))) {
5169 zend_refcounted *ref = Z_COUNTED_P(varptr);
5170
5171 varptr = Z_REFVAL_P(varptr);
5172 ZVAL_COPY_VALUE(arg, varptr);
5173 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
5174 efree_size(ref, sizeof(zend_reference));
5175 } else if (Z_OPT_REFCOUNTED_P(arg)) {
5176 Z_ADDREF_P(arg);
5177 }
5178 } else {
5179 ZVAL_COPY_VALUE(arg, varptr);
5180 }
5181
5182 ZEND_VM_NEXT_OPCODE();
5183 }
5184
5185 ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
5186 {
5187 USE_OPLINE
5188 zval *args;
5189 uint32_t arg_num;
5190
5191 SAVE_OPLINE();
5192 args = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5193 arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1;
5194
5195 ZEND_VM_C_LABEL(send_again):
5196 if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
5197 HashTable *ht = Z_ARRVAL_P(args);
5198 zval *arg, *top;
5199 zend_string *name;
5200 bool have_named_params = 0;
5201
5202 zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
5203
5204 // TODO: Speed this up using a flag that specifies whether there are any ref parameters.
5205 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_REFCOUNT_P(args) > 1) {
5206 uint32_t tmp_arg_num = arg_num;
5207 bool separate = 0;
5208
5209 /* check if any of arguments are going to be passed by reference */
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,name,arg)5210 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
5211 if (UNEXPECTED(name)) {
5212 void *cache_slot[2] = {NULL, NULL};
5213 tmp_arg_num = zend_get_arg_offset_by_name(
5214 EX(call)->func, name, cache_slot) + 1;
5215 }
5216 if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, tmp_arg_num)) {
5217 separate = 1;
5218 break;
5219 }
5220 tmp_arg_num++;
5221 } ZEND_HASH_FOREACH_END();
5222 if (separate) {
5223 SEPARATE_ARRAY(args);
5224 ht = Z_ARRVAL_P(args);
5225 }
5226 }
5227
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,name,arg)5228 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
5229 if (UNEXPECTED(name)) {
5230 void *cache_slot[2] = {NULL, NULL};
5231 have_named_params = 1;
5232 top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot);
5233 if (UNEXPECTED(!top)) {
5234 FREE_OP1();
5235 HANDLE_EXCEPTION();
5236 }
5237 } else {
5238 if (have_named_params) {
5239 zend_throw_error(NULL,
5240 "Cannot use positional argument after named argument during unpacking");
5241 FREE_OP1();
5242 HANDLE_EXCEPTION();
5243 }
5244
5245 top = ZEND_CALL_ARG(EX(call), arg_num);
5246 ZEND_CALL_NUM_ARGS(EX(call))++;
5247 }
5248
5249 if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5250 if (Z_ISREF_P(arg)) {
5251 Z_ADDREF_P(arg);
5252 ZVAL_REF(top, Z_REF_P(arg));
5253 } else if (OP1_TYPE & (IS_VAR|IS_CV)) {
5254 /* array is already separated above */
5255 ZVAL_MAKE_REF_EX(arg, 2);
5256 ZVAL_REF(top, Z_REF_P(arg));
5257 } else {
5258 Z_TRY_ADDREF_P(arg);
5259 ZVAL_NEW_REF(top, arg);
5260 }
5261 } else {
5262 ZVAL_COPY_DEREF(top, arg);
5263 }
5264
5265 arg_num++;
5266 } ZEND_HASH_FOREACH_END();
5267
5268 } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) {
5269 zend_class_entry *ce = Z_OBJCE_P(args);
5270 zend_object_iterator *iter;
5271 bool have_named_params = 0;
5272
5273 if (!ce || !ce->get_iterator) {
5274 zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(args));
5275 } else {
5276
5277 iter = ce->get_iterator(ce, args, 0);
5278 if (UNEXPECTED(!iter)) {
5279 FREE_OP1();
5280 if (!EG(exception)) {
5281 zend_throw_exception_ex(
5282 NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)
5283 );
5284 }
5285 HANDLE_EXCEPTION();
5286 }
5287
5288 const zend_object_iterator_funcs *funcs = iter->funcs;
5289 if (funcs->rewind) {
5290 funcs->rewind(iter);
5291 }
5292
5293 for (; funcs->valid(iter) == SUCCESS; ++arg_num) {
5294 zval *arg, *top;
5295
5296 if (UNEXPECTED(EG(exception) != NULL)) {
5297 break;
5298 }
5299
5300 arg = funcs->get_current_data(iter);
5301 if (UNEXPECTED(EG(exception) != NULL)) {
5302 break;
5303 }
5304
5305 zend_string *name = NULL;
5306 if (funcs->get_current_key) {
5307 zval key;
5308 funcs->get_current_key(iter, &key);
5309 if (UNEXPECTED(EG(exception) != NULL)) {
5310 break;
5311 }
5312
5313 if (UNEXPECTED(Z_TYPE(key) != IS_LONG)) {
5314 if (UNEXPECTED(Z_TYPE(key) != IS_STRING)) {
5315 zend_throw_error(NULL,
5316 "Keys must be of type int|string during argument unpacking");
5317 zval_ptr_dtor(&key);
5318 break;
5319 }
5320
5321 name = Z_STR_P(&key);
5322 }
5323 }
5324
5325 if (UNEXPECTED(name)) {
5326 void *cache_slot[2] = {NULL, NULL};
5327 have_named_params = 1;
5328 top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot);
5329 if (UNEXPECTED(!top)) {
5330 zend_string_release(name);
5331 break;
5332 }
5333
5334 ZVAL_DEREF(arg);
5335 Z_TRY_ADDREF_P(arg);
5336
5337 if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5338 zend_error(
5339 E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
5340 " by unpacking a Traversable, passing by-value instead", arg_num,
5341 EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
5342 EX(call)->func->common.scope ? "::" : "",
5343 ZSTR_VAL(EX(call)->func->common.function_name)
5344 );
5345 ZVAL_NEW_REF(top, arg);
5346 } else {
5347 ZVAL_COPY_VALUE(top, arg);
5348 }
5349
5350 zend_string_release(name);
5351 } else {
5352 if (have_named_params) {
5353 zend_throw_error(NULL,
5354 "Cannot use positional argument after named argument during unpacking");
5355 break;
5356 }
5357
5358 zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1);
5359 top = ZEND_CALL_ARG(EX(call), arg_num);
5360 ZVAL_DEREF(arg);
5361 Z_TRY_ADDREF_P(arg);
5362
5363 if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5364 zend_error(
5365 E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
5366 " by unpacking a Traversable, passing by-value instead", arg_num,
5367 EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
5368 EX(call)->func->common.scope ? "::" : "",
5369 ZSTR_VAL(EX(call)->func->common.function_name)
5370 );
5371 ZVAL_NEW_REF(top, arg);
5372 } else {
5373 ZVAL_COPY_VALUE(top, arg);
5374 }
5375
5376 ZEND_CALL_NUM_ARGS(EX(call))++;
5377 }
5378
5379 funcs->move_forward(iter);
5380 }
5381
5382 zend_iterator_dtor(iter);
5383 }
5384 } else if (EXPECTED(Z_ISREF_P(args))) {
5385 args = Z_REFVAL_P(args);
5386 ZEND_VM_C_GOTO(send_again);
5387 } else {
5388 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) {
5389 ZVAL_UNDEFINED_OP1();
5390 }
5391 zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(args));
5392 }
5393
5394 FREE_OP1();
5395 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5396 }
5397
5398 ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM)
5399 {
5400 USE_OPLINE
5401 zval *args;
5402
5403 SAVE_OPLINE();
5404 args = GET_OP1_ZVAL_PTR(BP_VAR_R);
5405
5406 if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) {
5407 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(args)) {
5408 args = Z_REFVAL_P(args);
5409 if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
5410 ZEND_VM_C_GOTO(send_array);
5411 }
5412 }
5413 zend_type_error("call_user_func_array(): Argument #2 ($args) must be of type array, %s given", zend_zval_value_name(args));
5414 FREE_OP2();
5415 FREE_OP1();
5416 HANDLE_EXCEPTION();
5417 } else {
5418 uint32_t arg_num;
5419 HashTable *ht;
5420 zval *arg, *param;
5421
5422 ZEND_VM_C_LABEL(send_array):
5423 ht = Z_ARRVAL_P(args);
5424 if (OP2_TYPE != IS_UNUSED) {
5425 /* We don't need to handle named params in this case,
5426 * because array_slice() is called with $preserve_keys == false. */
5427 zval *op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
5428 uint32_t skip = opline->extended_value;
5429 uint32_t count = zend_hash_num_elements(ht);
5430 zend_long len;
5431 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
5432 len = Z_LVAL_P(op2);
5433 } else if (Z_TYPE_P(op2) == IS_NULL) {
5434 len = count - skip;
5435 } else if (EX_USES_STRICT_TYPES()
5436 || !zend_parse_arg_long_weak(op2, &len, /* arg_num */ 3)) {
5437 zend_type_error(
5438 "array_slice(): Argument #3 ($length) must be of type ?int, %s given",
5439 zend_zval_value_name(op2));
5440 FREE_OP2();
5441 FREE_OP1();
5442 HANDLE_EXCEPTION();
5443 }
5444
5445 if (len < 0) {
5446 len += (zend_long)(count - skip);
5447 }
5448 if (skip < count && len > 0) {
5449 if (len > (zend_long)(count - skip)) {
5450 len = (zend_long)(count - skip);
5451 }
5452 zend_vm_stack_extend_call_frame(&EX(call), 0, len);
5453 arg_num = 1;
5454 param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht,arg)5455 ZEND_HASH_FOREACH_VAL(ht, arg) {
5456 bool must_wrap = 0;
5457 if (skip > 0) {
5458 skip--;
5459 continue;
5460 } else if ((zend_long)(arg_num - 1) >= len) {
5461 break;
5462 } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5463 if (UNEXPECTED(!Z_ISREF_P(arg))) {
5464 if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5465 /* By-value send is not allowed -- emit a warning,
5466 * but still perform the call. */
5467 zend_param_must_be_ref(EX(call)->func, arg_num);
5468 must_wrap = 1;
5469 }
5470 }
5471 } else {
5472 if (Z_ISREF_P(arg) &&
5473 !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
5474 /* don't separate references for __call */
5475 arg = Z_REFVAL_P(arg);
5476 }
5477 }
5478 if (EXPECTED(!must_wrap)) {
5479 ZVAL_COPY(param, arg);
5480 } else {
5481 Z_TRY_ADDREF_P(arg);
5482 ZVAL_NEW_REF(param, arg);
5483 }
5484 ZEND_CALL_NUM_ARGS(EX(call))++;
5485 arg_num++;
5486 param++;
5487 } ZEND_HASH_FOREACH_END();
5488 }
5489 FREE_OP2();
5490 } else {
5491 zend_string *name;
5492 bool have_named_params;
5493 zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht));
5494 arg_num = 1;
5495 param = ZEND_CALL_ARG(EX(call), 1);
5496 have_named_params = 0;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,name,arg)5497 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
5498 if (name) {
5499 void *cache_slot[2] = {NULL, NULL};
5500 have_named_params = 1;
5501 param = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot);
5502 if (!param) {
5503 FREE_OP1();
5504 HANDLE_EXCEPTION();
5505 }
5506 } else if (have_named_params) {
5507 zend_throw_error(NULL,
5508 "Cannot use positional argument after named argument");
5509 FREE_OP1();
5510 HANDLE_EXCEPTION();
5511 }
5512
5513 bool must_wrap = 0;
5514 if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5515 if (UNEXPECTED(!Z_ISREF_P(arg))) {
5516 if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5517 /* By-value send is not allowed -- emit a warning,
5518 * but still perform the call. */
5519 zend_param_must_be_ref(EX(call)->func, arg_num);
5520 must_wrap = 1;
5521 }
5522 }
5523 } else {
5524 if (Z_ISREF_P(arg) &&
5525 !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
5526 /* don't separate references for __call */
5527 arg = Z_REFVAL_P(arg);
5528 }
5529 }
5530
5531 if (EXPECTED(!must_wrap)) {
5532 ZVAL_COPY(param, arg);
5533 } else {
5534 Z_TRY_ADDREF_P(arg);
5535 ZVAL_NEW_REF(param, arg);
5536 }
5537 if (!name) {
5538 ZEND_CALL_NUM_ARGS(EX(call))++;
5539 arg_num++;
5540 param++;
5541 }
5542 } ZEND_HASH_FOREACH_END();
5543 }
5544 }
5545 FREE_OP1();
5546 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5547 }
5548
5549 ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|VAR|CV, NUM)
5550 {
5551 USE_OPLINE
5552 zval *arg, *param;
5553
5554 SAVE_OPLINE();
5555
5556 arg = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
5557 param = ZEND_CALL_VAR(EX(call), opline->result.var);
5558 if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
5559 zend_param_must_be_ref(EX(call)->func, opline->op2.num);
5560 Z_TRY_ADDREF_P(arg);
5561 ZVAL_NEW_REF(param, arg);
5562 } else {
5563 ZVAL_COPY(param, arg);
5564 }
5565
5566 FREE_OP1();
5567 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5568 }
5569
5570 ZEND_VM_HOT_HANDLER(199, ZEND_CHECK_UNDEF_ARGS, UNUSED, UNUSED)
5571 {
5572 USE_OPLINE
5573
5574 zend_execute_data *call = execute_data->call;
5575 if (EXPECTED(!(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF))) {
5576 ZEND_VM_NEXT_OPCODE();
5577 }
5578
5579 SAVE_OPLINE();
5580 zend_handle_undef_args(call);
5581 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5582 }
5583
ZEND_VM_COLD_HELPER(zend_missing_arg_helper,ANY,ANY)5584 ZEND_VM_COLD_HELPER(zend_missing_arg_helper, ANY, ANY)
5585 {
5586 #ifdef ZEND_VM_IP_GLOBAL_REG
5587 USE_OPLINE
5588
5589 SAVE_OPLINE();
5590 #endif
5591 zend_missing_arg_error(execute_data);
5592 HANDLE_EXCEPTION();
5593 }
5594
ZEND_VM_HELPER(zend_verify_recv_arg_type_helper,ANY,ANY,zval * op_1)5595 ZEND_VM_HELPER(zend_verify_recv_arg_type_helper, ANY, ANY, zval *op_1)
5596 {
5597 USE_OPLINE
5598
5599 SAVE_OPLINE();
5600 if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) {
5601 HANDLE_EXCEPTION();
5602 }
5603
5604 ZEND_VM_NEXT_OPCODE();
5605 }
5606
5607 ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT)
5608 {
5609 USE_OPLINE
5610 uint32_t arg_num = opline->op1.num;
5611 zval *param;
5612
5613 if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
5614 ZEND_VM_DISPATCH_TO_HELPER(zend_missing_arg_helper);
5615 }
5616
5617 param = EX_VAR(opline->result.var);
5618
5619 if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) {
5620 ZEND_VM_DISPATCH_TO_HELPER(zend_verify_recv_arg_type_helper, op_1, param);
5621 }
5622
5623 ZEND_VM_NEXT_OPCODE();
5624 }
5625
5626 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NOTYPE, NUM, NUM, CACHE_SLOT)
5627 {
5628 USE_OPLINE
5629 uint32_t arg_num = opline->op1.num;
5630
5631 if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
5632 ZEND_VM_DISPATCH_TO_HELPER(zend_missing_arg_helper);
5633 }
5634
5635 ZEND_VM_NEXT_OPCODE();
5636 }
5637
5638 ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT)
5639 {
5640 USE_OPLINE
5641 uint32_t arg_num;
5642 zval *param;
5643
5644 ZEND_VM_REPEATABLE_OPCODE
5645
5646 arg_num = opline->op1.num;
5647 param = EX_VAR(opline->result.var);
5648 if (arg_num > EX_NUM_ARGS()) {
5649 zval *default_value = RT_CONSTANT(opline, opline->op2);
5650
5651 if (Z_OPT_TYPE_P(default_value) == IS_CONSTANT_AST) {
5652 zval *cache_val = (zval*)CACHE_ADDR(Z_CACHE_SLOT_P(default_value));
5653
5654 /* we keep in cache only not refcounted values */
5655 if (Z_TYPE_P(cache_val) != IS_UNDEF) {
5656 ZVAL_COPY_VALUE(param, cache_val);
5657 } else {
5658 SAVE_OPLINE();
5659 ZVAL_COPY(param, default_value);
5660 zend_ast_evaluate_ctx ctx = {0};
5661 if (UNEXPECTED(zval_update_constant_with_ctx(param, EX(func)->op_array.scope, &ctx) != SUCCESS)) {
5662 zval_ptr_dtor_nogc(param);
5663 ZVAL_UNDEF(param);
5664 HANDLE_EXCEPTION();
5665 }
5666 if (!Z_REFCOUNTED_P(param) && !ctx.had_side_effects) {
5667 ZVAL_COPY_VALUE(cache_val, param);
5668 }
5669 }
5670 ZEND_VM_C_GOTO(recv_init_check_type);
5671 } else {
5672 ZVAL_COPY(param, default_value);
5673 }
5674 } else {
5675 ZEND_VM_C_LABEL(recv_init_check_type):
5676 if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
5677 SAVE_OPLINE();
5678 if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5679 HANDLE_EXCEPTION();
5680 }
5681 }
5682 }
5683
5684 ZEND_VM_REPEAT_OPCODE(ZEND_RECV_INIT);
5685 ZEND_VM_NEXT_OPCODE();
5686 }
5687
5688 ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT)
5689 {
5690 USE_OPLINE
5691 uint32_t arg_num = opline->op1.num;
5692 uint32_t arg_count = EX_NUM_ARGS();
5693 zval *params;
5694
5695 SAVE_OPLINE();
5696
5697 params = EX_VAR(opline->result.var);
5698
5699 if (arg_num <= arg_count) {
5700 ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_VARIADIC);
5701 ZEND_ASSERT(EX(func)->common.num_args == arg_num - 1);
5702 zend_arg_info *arg_info = &EX(func)->common.arg_info[arg_num - 1];
5703
5704 array_init_size(params, arg_count - arg_num + 1);
5705 zend_hash_real_init_packed(Z_ARRVAL_P(params));
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P (params))5706 ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) {
5707 zval *param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
5708 if (ZEND_TYPE_IS_SET(arg_info->type)) {
5709 ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
5710 do {
5711 if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5712 ZEND_HASH_FILL_FINISH();
5713 HANDLE_EXCEPTION();
5714 }
5715
5716 if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
5717 ZEND_HASH_FILL_ADD(param);
5718 param++;
5719 } while (++arg_num <= arg_count);
5720 } else {
5721 do {
5722 if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
5723 ZEND_HASH_FILL_ADD(param);
5724 param++;
5725 } while (++arg_num <= arg_count);
5726 }
5727 } ZEND_HASH_FILL_END();
5728 } else {
5729 ZVAL_EMPTY_ARRAY(params);
5730 }
5731
5732 if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
5733 zend_string *name;
5734 zval *param;
5735 zend_arg_info *arg_info = &EX(func)->common.arg_info[EX(func)->common.num_args];
5736 if (ZEND_TYPE_IS_SET(arg_info->type)) {
5737 SEPARATE_ARRAY(params);
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX (extra_named_params),name,param)5738 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) {
5739 if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5740 HANDLE_EXCEPTION();
5741 }
5742 Z_TRY_ADDREF_P(param);
5743 zend_hash_add_new(Z_ARRVAL_P(params), name, param);
5744 } ZEND_HASH_FOREACH_END();
5745 } else if (zend_hash_num_elements(Z_ARRVAL_P(params)) == 0) {
5746 GC_ADDREF(EX(extra_named_params));
5747 ZVAL_ARR(params, EX(extra_named_params));
5748 } else {
5749 SEPARATE_ARRAY(params);
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX (extra_named_params),name,param)5750 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) {
5751 Z_TRY_ADDREF_P(param);
5752 zend_hash_add_new(Z_ARRVAL_P(params), name, param);
5753 } ZEND_HASH_FOREACH_END();
5754 }
5755 }
5756
5757 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5758 }
5759
5760 ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
5761 {
5762 USE_OPLINE
5763 zval *val;
5764
5765 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5766 if (Z_TYPE_INFO_P(val) == IS_TRUE) {
5767 ZVAL_TRUE(EX_VAR(opline->result.var));
5768 } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
5769 /* The result and op1 can be the same cv zval */
5770 const uint32_t orig_val_type = Z_TYPE_INFO_P(val);
5771 ZVAL_FALSE(EX_VAR(opline->result.var));
5772 if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) {
5773 SAVE_OPLINE();
5774 ZVAL_UNDEFINED_OP1();
5775 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5776 }
5777 } else {
5778 SAVE_OPLINE();
5779 ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val));
5780 FREE_OP1();
5781 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5782 }
5783 ZEND_VM_NEXT_OPCODE();
5784 }
5785
ZEND_VM_HELPER(zend_case_helper,ANY,ANY,zval * op_1,zval * op_2)5786 ZEND_VM_HELPER(zend_case_helper, ANY, ANY, zval *op_1, zval *op_2)
5787 {
5788 int ret;
5789 USE_OPLINE
5790
5791 SAVE_OPLINE();
5792 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
5793 op_1 = ZVAL_UNDEFINED_OP1();
5794 }
5795 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
5796 op_2 = ZVAL_UNDEFINED_OP2();
5797 }
5798 ret = zend_compare(op_1, op_2);
5799 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
5800 zval_ptr_dtor_nogc(op_2);
5801 }
5802 ZEND_VM_SMART_BRANCH(ret == 0, 1);
5803 }
5804
5805 ZEND_VM_HANDLER(48, ZEND_CASE, TMPVAR, CONST|TMPVAR|CV)
5806 {
5807 USE_OPLINE
5808 zval *op1, *op2;
5809 double d1, d2;
5810
5811 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5812 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
5813 if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
5814 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
5815 if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) {
5816 ZEND_VM_C_LABEL(case_true):
5817 ZEND_VM_SMART_BRANCH_TRUE();
5818 } else {
5819 ZEND_VM_C_LABEL(case_false):
5820 ZEND_VM_SMART_BRANCH_FALSE();
5821 }
5822 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
5823 d1 = (double)Z_LVAL_P(op1);
5824 d2 = Z_DVAL_P(op2);
5825 ZEND_VM_C_GOTO(case_double);
5826 }
5827 } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
5828 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
5829 d1 = Z_DVAL_P(op1);
5830 d2 = Z_DVAL_P(op2);
5831 ZEND_VM_C_LABEL(case_double):
5832 if (d1 == d2) {
5833 ZEND_VM_C_GOTO(case_true);
5834 } else {
5835 ZEND_VM_C_GOTO(case_false);
5836 }
5837 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
5838 d1 = Z_DVAL_P(op1);
5839 d2 = (double)Z_LVAL_P(op2);
5840 ZEND_VM_C_GOTO(case_double);
5841 }
5842 } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
5843 if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
5844 bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
5845 FREE_OP2();
5846 if (result) {
5847 ZEND_VM_C_GOTO(case_true);
5848 } else {
5849 ZEND_VM_C_GOTO(case_false);
5850 }
5851 }
5852 }
5853 ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper, op_1, op1, op_2, op2);
5854 }
5855
5856 ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, NUM)
5857 {
5858 USE_OPLINE
5859 zval *result;
5860 zend_function *constructor;
5861 zend_class_entry *ce;
5862 zend_execute_data *call;
5863
5864 SAVE_OPLINE();
5865 if (OP1_TYPE == IS_CONST) {
5866 ce = CACHED_PTR(opline->op2.num);
5867 if (UNEXPECTED(ce == NULL)) {
5868 ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
5869 if (UNEXPECTED(ce == NULL)) {
5870 ZVAL_UNDEF(EX_VAR(opline->result.var));
5871 HANDLE_EXCEPTION();
5872 }
5873 CACHE_PTR(opline->op2.num, ce);
5874 }
5875 } else if (OP1_TYPE == IS_UNUSED) {
5876 ce = zend_fetch_class(NULL, opline->op1.num);
5877 if (UNEXPECTED(ce == NULL)) {
5878 ZVAL_UNDEF(EX_VAR(opline->result.var));
5879 HANDLE_EXCEPTION();
5880 }
5881 } else {
5882 ce = Z_CE_P(EX_VAR(opline->op1.var));
5883 }
5884
5885 result = EX_VAR(opline->result.var);
5886 if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) {
5887 ZVAL_UNDEF(result);
5888 HANDLE_EXCEPTION();
5889 }
5890
5891 constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
5892 if (constructor == NULL) {
5893 if (UNEXPECTED(EG(exception))) {
5894 HANDLE_EXCEPTION();
5895 }
5896
5897 /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
5898 * opcode is DO_FCALL in case EXT instructions are used. */
5899 if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
5900 ZEND_VM_NEXT_OPCODE_EX(1, 2);
5901 }
5902
5903 /* Perform a dummy function call */
5904 call = zend_vm_stack_push_call_frame(
5905 ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
5906 opline->extended_value, NULL);
5907 } else {
5908 if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
5909 init_func_run_time_cache(&constructor->op_array);
5910 }
5911 /* We are not handling overloaded classes right now */
5912 call = zend_vm_stack_push_call_frame(
5913 ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS,
5914 constructor,
5915 opline->extended_value,
5916 Z_OBJ_P(result));
5917 Z_ADDREF_P(result);
5918 }
5919
5920 call->prev_execute_data = EX(call);
5921 EX(call) = call;
5922 ZEND_VM_NEXT_OPCODE();
5923 }
5924
5925 ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
5926 {
5927 USE_OPLINE
5928 zval *obj;
5929 zend_object *zobj;
5930 zend_class_entry *ce, *scope;
5931 zend_function *clone;
5932 zend_object_clone_obj_t clone_call;
5933
5934 SAVE_OPLINE();
5935 obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
5936
5937 do {
5938 if (OP1_TYPE == IS_CONST ||
5939 (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
5940 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
5941 obj = Z_REFVAL_P(obj);
5942 if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
5943 break;
5944 }
5945 }
5946 ZVAL_UNDEF(EX_VAR(opline->result.var));
5947 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
5948 ZVAL_UNDEFINED_OP1();
5949 if (UNEXPECTED(EG(exception) != NULL)) {
5950 HANDLE_EXCEPTION();
5951 }
5952 }
5953 zend_throw_error(NULL, "__clone method called on non-object");
5954 FREE_OP1();
5955 HANDLE_EXCEPTION();
5956 }
5957 } while (0);
5958
5959 zobj = Z_OBJ_P(obj);
5960 ce = zobj->ce;
5961 clone = ce->clone;
5962 clone_call = zobj->handlers->clone_obj;
5963 if (UNEXPECTED(clone_call == NULL)) {
5964 zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
5965 FREE_OP1();
5966 ZVAL_UNDEF(EX_VAR(opline->result.var));
5967 HANDLE_EXCEPTION();
5968 }
5969
5970 if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
5971 scope = EX(func)->op_array.scope;
5972 if (clone->common.scope != scope) {
5973 if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
5974 || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
5975 zend_wrong_clone_call(clone, scope);
5976 FREE_OP1();
5977 ZVAL_UNDEF(EX_VAR(opline->result.var));
5978 HANDLE_EXCEPTION();
5979 }
5980 }
5981 }
5982
5983 ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj));
5984
5985 FREE_OP1();
5986 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5987 }
5988
5989 ZEND_VM_HOT_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED|CONST_FETCH, CONST, CACHE_SLOT)
5990 {
5991 USE_OPLINE
5992 zend_constant *c;
5993
5994 c = CACHED_PTR(opline->extended_value);
5995 if (EXPECTED(c != NULL) && EXPECTED(!IS_SPECIAL_CACHE_VAL(c))) {
5996 ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
5997 ZEND_VM_NEXT_OPCODE();
5998 }
5999
6000 SAVE_OPLINE();
6001 zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num OPLINE_CC EXECUTE_DATA_CC);
6002 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6003 }
6004
6005 ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CONST|TMPVARCV, CACHE_SLOT)
6006 {
6007 zend_class_entry *ce, *scope;
6008 zend_class_constant *c;
6009 zval *value, *zv, *constant_zv;
6010 zend_string *constant_name;
6011 USE_OPLINE
6012
6013 SAVE_OPLINE();
6014
6015 do {
6016 if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
6017 if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) {
6018 value = CACHED_PTR(opline->extended_value + sizeof(void*));
6019 break;
6020 }
6021 }
6022 if (OP1_TYPE == IS_CONST) {
6023 if (EXPECTED(CACHED_PTR(opline->extended_value))) {
6024 ce = CACHED_PTR(opline->extended_value);
6025 } else {
6026 ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op1)), Z_STR_P(RT_CONSTANT(opline, opline->op1) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
6027 if (UNEXPECTED(ce == NULL)) {
6028 ZVAL_UNDEF(EX_VAR(opline->result.var));
6029 FREE_OP2();
6030 HANDLE_EXCEPTION();
6031 }
6032 CACHE_PTR(opline->extended_value, ce);
6033 }
6034 } else if (OP1_TYPE == IS_UNUSED) {
6035 ce = zend_fetch_class(NULL, opline->op1.num);
6036 if (UNEXPECTED(ce == NULL)) {
6037 ZVAL_UNDEF(EX_VAR(opline->result.var));
6038 FREE_OP2();
6039 HANDLE_EXCEPTION();
6040 }
6041 } else {
6042 ce = Z_CE_P(EX_VAR(opline->op1.var));
6043 }
6044 if (OP1_TYPE != IS_CONST
6045 && OP2_TYPE == IS_CONST
6046 && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) {
6047 value = CACHED_PTR(opline->extended_value + sizeof(void*));
6048 break;
6049 }
6050
6051 constant_zv = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
6052 if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) {
6053 zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv));
6054 ZVAL_UNDEF(EX_VAR(opline->result.var));
6055 FREE_OP2();
6056 HANDLE_EXCEPTION();
6057 }
6058 constant_name = Z_STR_P(constant_zv);
6059 /* Magic 'class' for constant OP2 is caught at compile-time */
6060 if (OP2_TYPE != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) {
6061 ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
6062 FREE_OP2();
6063 ZEND_VM_NEXT_OPCODE();
6064 }
6065 zv = OP2_TYPE == IS_CONST
6066 ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name)
6067 : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name);
6068
6069 if (EXPECTED(zv != NULL)) {
6070 c = Z_PTR_P(zv);
6071 scope = EX(func)->op_array.scope;
6072 if (!zend_verify_const_access(c, scope)) {
6073 zend_throw_error(NULL, "Cannot access %s constant %s::%s", zend_visibility_string(ZEND_CLASS_CONST_FLAGS(c)), ZSTR_VAL(ce->name), ZSTR_VAL(constant_name));
6074 ZVAL_UNDEF(EX_VAR(opline->result.var));
6075 FREE_OP2();
6076 HANDLE_EXCEPTION();
6077 }
6078
6079 if (ce->ce_flags & ZEND_ACC_TRAIT) {
6080 zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name));
6081 ZVAL_UNDEF(EX_VAR(opline->result.var));
6082 FREE_OP2();
6083 HANDLE_EXCEPTION();
6084 }
6085
6086 bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED;
6087 if (UNEXPECTED(is_constant_deprecated)) {
6088 zend_deprecated_class_constant(c, constant_name);
6089
6090 if (EG(exception)) {
6091 ZVAL_UNDEF(EX_VAR(opline->result.var));
6092 FREE_OP2();
6093 HANDLE_EXCEPTION();
6094 }
6095 }
6096
6097 value = &c->value;
6098 // Enums require loading of all class constants to build the backed enum table
6099 if (ce->ce_flags & ZEND_ACC_ENUM && ce->enum_backing_type != IS_UNDEF && ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
6100 if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) {
6101 ZVAL_UNDEF(EX_VAR(opline->result.var));
6102 FREE_OP2();
6103 HANDLE_EXCEPTION();
6104 }
6105 }
6106 if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
6107 if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) {
6108 ZVAL_UNDEF(EX_VAR(opline->result.var));
6109 FREE_OP2();
6110 HANDLE_EXCEPTION();
6111 }
6112 }
6113 if (OP2_TYPE == IS_CONST && !is_constant_deprecated) {
6114 CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value);
6115 }
6116 } else {
6117 zend_throw_error(NULL, "Undefined constant %s::%s",
6118 ZSTR_VAL(ce->name), ZSTR_VAL(constant_name));
6119 ZVAL_UNDEF(EX_VAR(opline->result.var));
6120 FREE_OP2();
6121 HANDLE_EXCEPTION();
6122 }
6123 } while (0);
6124
6125 ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value);
6126
6127 FREE_OP2();
6128 ZEND_VM_NEXT_OPCODE();
6129 }
6130
6131 ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, REF)
6132 {
6133 USE_OPLINE
6134 zval *expr_ptr, new_expr;
6135
6136 SAVE_OPLINE();
6137 if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) &&
6138 UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
6139 expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
6140 if (Z_ISREF_P(expr_ptr)) {
6141 Z_ADDREF_P(expr_ptr);
6142 } else {
6143 ZVAL_MAKE_REF_EX(expr_ptr, 2);
6144 }
6145 FREE_OP1();
6146 } else {
6147 expr_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
6148 if (OP1_TYPE == IS_TMP_VAR) {
6149 /* pass */
6150 } else if (OP1_TYPE == IS_CONST) {
6151 Z_TRY_ADDREF_P(expr_ptr);
6152 } else if (OP1_TYPE == IS_CV) {
6153 ZVAL_DEREF(expr_ptr);
6154 Z_TRY_ADDREF_P(expr_ptr);
6155 } else /* if (OP1_TYPE == IS_VAR) */ {
6156 if (UNEXPECTED(Z_ISREF_P(expr_ptr))) {
6157 zend_refcounted *ref = Z_COUNTED_P(expr_ptr);
6158
6159 expr_ptr = Z_REFVAL_P(expr_ptr);
6160 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
6161 ZVAL_COPY_VALUE(&new_expr, expr_ptr);
6162 expr_ptr = &new_expr;
6163 efree_size(ref, sizeof(zend_reference));
6164 } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) {
6165 Z_ADDREF_P(expr_ptr);
6166 }
6167 }
6168 }
6169 }
6170
6171 if (OP2_TYPE != IS_UNUSED) {
6172 zval *offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
6173 zend_string *str;
6174 zend_ulong hval;
6175
6176 ZEND_VM_C_LABEL(add_again):
6177 if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
6178 str = Z_STR_P(offset);
6179 if (OP2_TYPE != IS_CONST) {
6180 if (ZEND_HANDLE_NUMERIC(str, hval)) {
6181 ZEND_VM_C_GOTO(num_index);
6182 }
6183 }
6184 ZEND_VM_C_LABEL(str_index):
6185 zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
6186 } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
6187 hval = Z_LVAL_P(offset);
6188 ZEND_VM_C_LABEL(num_index):
6189 zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
6190 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
6191 offset = Z_REFVAL_P(offset);
6192 ZEND_VM_C_GOTO(add_again);
6193 } else if (Z_TYPE_P(offset) == IS_NULL) {
6194 str = ZSTR_EMPTY_ALLOC();
6195 ZEND_VM_C_GOTO(str_index);
6196 } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
6197 hval = zend_dval_to_lval_safe(Z_DVAL_P(offset));
6198 ZEND_VM_C_GOTO(num_index);
6199 } else if (Z_TYPE_P(offset) == IS_FALSE) {
6200 hval = 0;
6201 ZEND_VM_C_GOTO(num_index);
6202 } else if (Z_TYPE_P(offset) == IS_TRUE) {
6203 hval = 1;
6204 ZEND_VM_C_GOTO(num_index);
6205 } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
6206 zend_use_resource_as_offset(offset);
6207 hval = Z_RES_HANDLE_P(offset);
6208 ZEND_VM_C_GOTO(num_index);
6209 } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
6210 ZVAL_UNDEFINED_OP2();
6211 str = ZSTR_EMPTY_ALLOC();
6212 ZEND_VM_C_GOTO(str_index);
6213 } else {
6214 zend_illegal_array_offset_access(offset);
6215 zval_ptr_dtor_nogc(expr_ptr);
6216 }
6217 FREE_OP2();
6218 } else {
6219 if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) {
6220 zend_cannot_add_element();
6221 zval_ptr_dtor_nogc(expr_ptr);
6222 }
6223 }
6224 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6225 }
6226
6227 ZEND_VM_HANDLER(147, ZEND_ADD_ARRAY_UNPACK, ANY, ANY)
6228 {
6229 USE_OPLINE
6230 zval *op1;
6231 HashTable *result_ht;
6232
6233 SAVE_OPLINE();
6234 op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
6235 result_ht = Z_ARRVAL_P(EX_VAR(opline->result.var));
6236
6237 ZEND_VM_C_LABEL(add_unpack_again):
6238 if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) {
6239 HashTable *ht = Z_ARRVAL_P(op1);
6240 zval *val;
6241
6242 if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) {
6243 zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1);
ZEND_HASH_FILL_PACKED(result_ht)6244 ZEND_HASH_FILL_PACKED(result_ht) {
6245 ZEND_HASH_PACKED_FOREACH_VAL(ht, val) {
6246 if (UNEXPECTED(Z_ISREF_P(val)) &&
6247 UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
6248 val = Z_REFVAL_P(val);
6249 }
6250 Z_TRY_ADDREF_P(val);
6251 ZEND_HASH_FILL_ADD(val);
6252 } ZEND_HASH_FOREACH_END();
6253 } ZEND_HASH_FILL_END();
6254 } else {
6255 zend_string *key;
6256
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,key,val)6257 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
6258 if (UNEXPECTED(Z_ISREF_P(val)) &&
6259 UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
6260 val = Z_REFVAL_P(val);
6261 }
6262 Z_TRY_ADDREF_P(val);
6263 if (key) {
6264 zend_hash_update(result_ht, key, val);
6265 } else {
6266 if (!zend_hash_next_index_insert(result_ht, val)) {
6267 zend_cannot_add_element();
6268 zval_ptr_dtor_nogc(val);
6269 break;
6270 }
6271 }
6272 } ZEND_HASH_FOREACH_END();
6273 }
6274 } else if (EXPECTED(Z_TYPE_P(op1) == IS_OBJECT)) {
6275 zend_class_entry *ce = Z_OBJCE_P(op1);
6276 zend_object_iterator *iter;
6277
6278 if (!ce || !ce->get_iterator) {
6279 zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(op1));
6280 } else {
6281 iter = ce->get_iterator(ce, op1, 0);
6282 if (UNEXPECTED(!iter)) {
6283 FREE_OP1();
6284 if (!EG(exception)) {
6285 zend_throw_exception_ex(
6286 NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)
6287 );
6288 }
6289 HANDLE_EXCEPTION();
6290 }
6291
6292 const zend_object_iterator_funcs *funcs = iter->funcs;
6293 if (funcs->rewind) {
6294 funcs->rewind(iter);
6295 }
6296
6297 for (; funcs->valid(iter) == SUCCESS; ) {
6298 zval *val;
6299
6300 if (UNEXPECTED(EG(exception) != NULL)) {
6301 break;
6302 }
6303
6304 val = funcs->get_current_data(iter);
6305 if (UNEXPECTED(EG(exception) != NULL)) {
6306 break;
6307 }
6308
6309 zval key;
6310 if (funcs->get_current_key) {
6311 funcs->get_current_key(iter, &key);
6312 if (UNEXPECTED(EG(exception) != NULL)) {
6313 break;
6314 }
6315
6316 if (UNEXPECTED(Z_TYPE(key) != IS_LONG && Z_TYPE(key) != IS_STRING)) {
6317 zend_throw_error(NULL,
6318 "Keys must be of type int|string during array unpacking");
6319 zval_ptr_dtor(&key);
6320 break;
6321 }
6322 } else {
6323 ZVAL_UNDEF(&key);
6324 }
6325
6326 ZVAL_DEREF(val);
6327 Z_TRY_ADDREF_P(val);
6328
6329 zend_ulong num_key;
6330 if (Z_TYPE(key) == IS_STRING && !ZEND_HANDLE_NUMERIC(Z_STR(key), num_key)) {
6331 zend_hash_update(result_ht, Z_STR(key), val);
6332 zval_ptr_dtor_str(&key);
6333 } else {
6334 zval_ptr_dtor(&key);
6335 if (!zend_hash_next_index_insert(result_ht, val)) {
6336 zend_cannot_add_element();
6337 zval_ptr_dtor_nogc(val);
6338 break;
6339 }
6340 }
6341
6342 funcs->move_forward(iter);
6343 if (UNEXPECTED(EG(exception))) {
6344 break;
6345 }
6346 }
6347
6348 zend_iterator_dtor(iter);
6349 }
6350 } else if (EXPECTED(Z_ISREF_P(op1))) {
6351 op1 = Z_REFVAL_P(op1);
6352 ZEND_VM_C_GOTO(add_unpack_again);
6353 } else {
6354 zend_throw_error(NULL, "Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(op1));
6355 }
6356
6357 FREE_OP1();
6358 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6359 }
6360
6361 ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
6362 {
6363 zval *array;
6364 uint32_t size;
6365 USE_OPLINE
6366
6367 array = EX_VAR(opline->result.var);
6368 if (OP1_TYPE != IS_UNUSED) {
6369 size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
6370 ZVAL_ARR(array, zend_new_array(size));
6371 /* Explicitly initialize array as not-packed if flag is set */
6372 if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
6373 zend_hash_real_init_mixed(Z_ARRVAL_P(array));
6374 }
6375 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT);
6376 } else {
6377 ZVAL_ARR(array, zend_new_array(0));
6378 ZEND_VM_NEXT_OPCODE();
6379 }
6380 }
6381
6382 ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
6383 {
6384 USE_OPLINE
6385 zval *expr;
6386 zval *result = EX_VAR(opline->result.var);
6387 HashTable *ht;
6388
6389 SAVE_OPLINE();
6390 expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
6391
6392 switch (opline->extended_value) {
6393 case IS_LONG:
6394 ZVAL_LONG(result, zval_get_long(expr));
6395 break;
6396 case IS_DOUBLE:
6397 ZVAL_DOUBLE(result, zval_get_double(expr));
6398 break;
6399 case IS_STRING:
6400 ZVAL_STR(result, zval_get_string(expr));
6401 break;
6402 default:
6403 ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead");
6404 if (OP1_TYPE & (IS_VAR|IS_CV)) {
6405 ZVAL_DEREF(expr);
6406 }
6407 /* If value is already of correct type, return it directly */
6408 if (Z_TYPE_P(expr) == opline->extended_value) {
6409 ZVAL_COPY_VALUE(result, expr);
6410 if (OP1_TYPE == IS_CONST) {
6411 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result);
6412 } else if (OP1_TYPE != IS_TMP_VAR) {
6413 if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result);
6414 }
6415
6416 FREE_OP1_IF_VAR();
6417 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6418 }
6419
6420 if (opline->extended_value == IS_ARRAY) {
6421 if (OP1_TYPE == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
6422 if (Z_TYPE_P(expr) != IS_NULL) {
6423 ZVAL_ARR(result, zend_new_array(1));
6424 expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
6425 if (OP1_TYPE == IS_CONST) {
6426 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
6427 } else {
6428 if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
6429 }
6430 } else {
6431 ZVAL_EMPTY_ARRAY(result);
6432 }
6433 } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
6434 /* Optimized version without rebuilding properties HashTable */
6435 ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
6436 } else {
6437 HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
6438 if (obj_ht) {
6439 /* fast copy */
6440 ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
6441 (Z_OBJCE_P(expr)->default_properties_count ||
6442 Z_OBJ_P(expr)->handlers != &std_object_handlers ||
6443 GC_IS_RECURSIVE(obj_ht))));
6444 zend_release_properties(obj_ht);
6445 } else {
6446 ZVAL_EMPTY_ARRAY(result);
6447 }
6448 }
6449 } else {
6450 ZEND_ASSERT(opline->extended_value == IS_OBJECT);
6451 ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
6452 if (Z_TYPE_P(expr) == IS_ARRAY) {
6453 ht = zend_symtable_to_proptable(Z_ARR_P(expr));
6454 if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
6455 /* TODO: try not to duplicate immutable arrays as well ??? */
6456 ht = zend_array_dup(ht);
6457 }
6458 Z_OBJ_P(result)->properties = ht;
6459 } else if (Z_TYPE_P(expr) != IS_NULL) {
6460 Z_OBJ_P(result)->properties = ht = zend_new_array(1);
6461 expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
6462 if (OP1_TYPE == IS_CONST) {
6463 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
6464 } else {
6465 if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
6466 }
6467 }
6468 }
6469 }
6470
6471 FREE_OP1();
6472 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6473 }
6474
6475 ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSERVER))
6476 {
6477 USE_OPLINE
6478 zend_op_array *new_op_array;
6479 zval *inc_filename;
6480
6481 SAVE_OPLINE();
6482 inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R);
6483 new_op_array = zend_include_or_eval(inc_filename, opline->extended_value);
6484 if (UNEXPECTED(EG(exception) != NULL)) {
6485 FREE_OP1();
6486 if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) {
6487 destroy_op_array(new_op_array);
6488 efree_size(new_op_array, sizeof(zend_op_array));
6489 }
6490 UNDEF_RESULT();
6491 HANDLE_EXCEPTION();
6492 } else if (new_op_array == ZEND_FAKE_OP_ARRAY) {
6493 if (RETURN_VALUE_USED(opline)) {
6494 ZVAL_TRUE(EX_VAR(opline->result.var));
6495 }
6496 } else if (UNEXPECTED(new_op_array == NULL)) {
6497 if (RETURN_VALUE_USED(opline)) {
6498 ZVAL_FALSE(EX_VAR(opline->result.var));
6499 }
6500 } else if (new_op_array->last == 1
6501 && new_op_array->opcodes[0].opcode == ZEND_RETURN
6502 && new_op_array->opcodes[0].op1_type == IS_CONST
6503 && EXPECTED(zend_execute_ex == execute_ex)) {
6504 if (RETURN_VALUE_USED(opline)) {
6505 const zend_op *op = new_op_array->opcodes;
6506
6507 ZVAL_COPY(EX_VAR(opline->result.var), RT_CONSTANT(op, op->op1));
6508 }
6509 zend_destroy_static_vars(new_op_array);
6510 destroy_op_array(new_op_array);
6511 efree_size(new_op_array, sizeof(zend_op_array));
6512 } else {
6513 zval *return_value = NULL;
6514 zend_execute_data *call;
6515 if (RETURN_VALUE_USED(opline)) {
6516 return_value = EX_VAR(opline->result.var);
6517 }
6518
6519 new_op_array->scope = EX(func)->op_array.scope;
6520
6521 call = zend_vm_stack_push_call_frame(
6522 (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
6523 (zend_function*)new_op_array, 0,
6524 Z_PTR(EX(This)));
6525
6526 if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
6527 call->symbol_table = EX(symbol_table);
6528 } else {
6529 call->symbol_table = zend_rebuild_symbol_table();
6530 }
6531
6532 call->prev_execute_data = execute_data;
6533 i_init_code_execute_data(call, new_op_array, return_value);
6534 ZEND_OBSERVER_FCALL_BEGIN(call);
6535 if (EXPECTED(zend_execute_ex == execute_ex)) {
6536 FREE_OP1();
6537 ZEND_VM_ENTER();
6538 } else {
6539 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
6540 zend_execute_ex(call);
6541 zend_vm_stack_free_call_frame(call);
6542 }
6543
6544 zend_destroy_static_vars(new_op_array);
6545 destroy_op_array(new_op_array);
6546 efree_size(new_op_array, sizeof(zend_op_array));
6547 if (UNEXPECTED(EG(exception) != NULL)) {
6548 zend_rethrow_exception(execute_data);
6549 FREE_OP1();
6550 UNDEF_RESULT();
6551 HANDLE_EXCEPTION();
6552 }
6553 }
6554 FREE_OP1();
6555 ZEND_VM_NEXT_OPCODE();
6556 }
6557
6558 ZEND_VM_HANDLER(153, ZEND_UNSET_CV, CV, UNUSED)
6559 {
6560 USE_OPLINE
6561 zval *var = EX_VAR(opline->op1.var);
6562
6563 if (Z_REFCOUNTED_P(var)) {
6564 zend_refcounted *garbage = Z_COUNTED_P(var);
6565
6566 ZVAL_UNDEF(var);
6567 SAVE_OPLINE();
6568 GC_DTOR(garbage);
6569 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6570 } else {
6571 ZVAL_UNDEF(var);
6572 }
6573 ZEND_VM_NEXT_OPCODE();
6574 }
6575
6576 ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
6577 {
6578 USE_OPLINE
6579 zval *varname;
6580 zend_string *name, *tmp_name;
6581 HashTable *target_symbol_table;
6582
6583 SAVE_OPLINE();
6584
6585 varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
6586
6587 if (OP1_TYPE == IS_CONST) {
6588 name = Z_STR_P(varname);
6589 } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
6590 name = Z_STR_P(varname);
6591 tmp_name = NULL;
6592 } else {
6593 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
6594 varname = ZVAL_UNDEFINED_OP1();
6595 }
6596 name = zval_try_get_tmp_string(varname, &tmp_name);
6597 if (UNEXPECTED(!name)) {
6598 FREE_OP1();
6599 HANDLE_EXCEPTION();
6600 }
6601 }
6602
6603 target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
6604 zend_hash_del_ind(target_symbol_table, name);
6605
6606 if (OP1_TYPE != IS_CONST) {
6607 zend_tmp_string_release(tmp_name);
6608 }
6609 FREE_OP1();
6610 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6611 }
6612
6613 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
6614 ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT)
6615 {
6616 USE_OPLINE
6617 zval *varname;
6618 zend_string *name, *tmp_name = NULL;
6619 zend_class_entry *ce;
6620
6621 SAVE_OPLINE();
6622
6623 if (OP2_TYPE == IS_CONST) {
6624 ce = CACHED_PTR(opline->extended_value);
6625 if (UNEXPECTED(ce == NULL)) {
6626 ce = zend_fetch_class_by_name(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
6627 if (UNEXPECTED(ce == NULL)) {
6628 FREE_OP1();
6629 HANDLE_EXCEPTION();
6630 }
6631 /*CACHE_PTR(opline->extended_value, ce);*/
6632 }
6633 } else if (OP2_TYPE == IS_UNUSED) {
6634 ce = zend_fetch_class(NULL, opline->op2.num);
6635 if (UNEXPECTED(ce == NULL)) {
6636 FREE_OP1();
6637 HANDLE_EXCEPTION();
6638 }
6639 } else {
6640 ce = Z_CE_P(EX_VAR(opline->op2.var));
6641 }
6642
6643 varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
6644 if (OP1_TYPE == IS_CONST) {
6645 name = Z_STR_P(varname);
6646 } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
6647 name = Z_STR_P(varname);
6648 } else {
6649 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
6650 varname = ZVAL_UNDEFINED_OP1();
6651 }
6652 name = zval_try_get_tmp_string(varname, &tmp_name);
6653 if (UNEXPECTED(!name)) {
6654 FREE_OP1();
6655 HANDLE_EXCEPTION();
6656 }
6657 }
6658
6659 zend_std_unset_static_property(ce, name);
6660
6661 zend_tmp_string_release(tmp_name);
6662 FREE_OP1();
6663 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6664 }
6665
6666 ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|CV, CONST|TMPVAR|CV)
6667 {
6668 USE_OPLINE
6669 zval *container;
6670 zval *offset;
6671 zend_ulong hval;
6672 zend_string *key;
6673
6674 SAVE_OPLINE();
6675 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
6676 offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
6677
6678 do {
6679 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
6680 HashTable *ht;
6681
6682 ZEND_VM_C_LABEL(unset_dim_array):
6683 SEPARATE_ARRAY(container);
6684 ht = Z_ARRVAL_P(container);
6685 ZEND_VM_C_LABEL(offset_again):
6686 if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
6687 key = Z_STR_P(offset);
6688 if (OP2_TYPE != IS_CONST) {
6689 if (ZEND_HANDLE_NUMERIC(key, hval)) {
6690 ZEND_VM_C_GOTO(num_index_dim);
6691 }
6692 }
6693 ZEND_VM_C_LABEL(str_index_dim):
6694 ZEND_ASSERT(ht != &EG(symbol_table));
6695 zend_hash_del(ht, key);
6696 } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
6697 hval = Z_LVAL_P(offset);
6698 ZEND_VM_C_LABEL(num_index_dim):
6699 zend_hash_index_del(ht, hval);
6700 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
6701 offset = Z_REFVAL_P(offset);
6702 ZEND_VM_C_GOTO(offset_again);
6703 } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
6704 hval = zend_dval_to_lval_safe(Z_DVAL_P(offset));
6705 ZEND_VM_C_GOTO(num_index_dim);
6706 } else if (Z_TYPE_P(offset) == IS_NULL) {
6707 key = ZSTR_EMPTY_ALLOC();
6708 ZEND_VM_C_GOTO(str_index_dim);
6709 } else if (Z_TYPE_P(offset) == IS_FALSE) {
6710 hval = 0;
6711 ZEND_VM_C_GOTO(num_index_dim);
6712 } else if (Z_TYPE_P(offset) == IS_TRUE) {
6713 hval = 1;
6714 ZEND_VM_C_GOTO(num_index_dim);
6715 } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
6716 zend_use_resource_as_offset(offset);
6717 hval = Z_RES_HANDLE_P(offset);
6718 ZEND_VM_C_GOTO(num_index_dim);
6719 } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
6720 ZVAL_UNDEFINED_OP2();
6721 key = ZSTR_EMPTY_ALLOC();
6722 ZEND_VM_C_GOTO(str_index_dim);
6723 } else {
6724 zend_illegal_array_offset_unset(offset);
6725 }
6726 break;
6727 } else if (Z_ISREF_P(container)) {
6728 container = Z_REFVAL_P(container);
6729 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
6730 ZEND_VM_C_GOTO(unset_dim_array);
6731 }
6732 }
6733 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
6734 container = ZVAL_UNDEFINED_OP1();
6735 }
6736 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
6737 offset = ZVAL_UNDEFINED_OP2();
6738 }
6739 if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
6740 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
6741 offset++;
6742 }
6743 Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset);
6744 } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
6745 zend_throw_error(NULL, "Cannot unset string offsets");
6746 } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) {
6747 zend_throw_error(NULL, "Cannot unset offset in a non-array variable");
6748 } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) {
6749 zend_false_to_array_deprecated();
6750 }
6751 } while (0);
6752
6753 FREE_OP2();
6754 FREE_OP1();
6755 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6756 }
6757
6758 ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
6759 {
6760 USE_OPLINE
6761 zval *container;
6762 zval *offset;
6763 zend_string *name, *tmp_name;
6764
6765 SAVE_OPLINE();
6766 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
6767 offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
6768
6769 do {
6770 if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
6771 if (Z_ISREF_P(container)) {
6772 container = Z_REFVAL_P(container);
6773 if (Z_TYPE_P(container) != IS_OBJECT) {
6774 if (OP1_TYPE == IS_CV
6775 && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
6776 ZVAL_UNDEFINED_OP1();
6777 }
6778 break;
6779 }
6780 } else {
6781 break;
6782 }
6783 }
6784 if (OP2_TYPE == IS_CONST) {
6785 name = Z_STR_P(offset);
6786 } else {
6787 name = zval_try_get_tmp_string(offset, &tmp_name);
6788 if (UNEXPECTED(!name)) {
6789 break;
6790 }
6791 }
6792 Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
6793 if (OP2_TYPE != IS_CONST) {
6794 zend_tmp_string_release(tmp_name);
6795 }
6796 } while (0);
6797
6798 FREE_OP2();
6799 FREE_OP1();
6800 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6801 }
6802
6803 ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
6804 {
6805 USE_OPLINE
6806 zval *array_ptr, *result;
6807
6808 SAVE_OPLINE();
6809
6810 array_ptr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
6811 if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) {
6812 result = EX_VAR(opline->result.var);
6813 ZVAL_COPY_VALUE(result, array_ptr);
6814 if (OP1_TYPE != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) {
6815 Z_ADDREF_P(array_ptr);
6816 }
6817 Z_FE_POS_P(result) = 0;
6818
6819 FREE_OP1_IF_VAR();
6820 ZEND_VM_NEXT_OPCODE();
6821 } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
6822 zend_object *zobj = Z_OBJ_P(array_ptr);
6823 if (!zobj->ce->get_iterator) {
6824 if (UNEXPECTED(zend_object_is_lazy(zobj))) {
6825 zobj = zend_lazy_object_init(zobj);
6826 if (UNEXPECTED(EG(exception))) {
6827 UNDEF_RESULT();
6828 FREE_OP1_IF_VAR();
6829 HANDLE_EXCEPTION();
6830 }
6831 }
6832 HashTable *properties = zobj->properties;
6833 if (properties) {
6834 if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
6835 if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
6836 GC_DELREF(properties);
6837 }
6838 properties = zobj->properties = zend_array_dup(properties);
6839 }
6840 } else {
6841 properties = zobj->handlers->get_properties(zobj);
6842 }
6843
6844 result = EX_VAR(opline->result.var);
6845 ZVAL_COPY_VALUE(result, array_ptr);
6846 if (OP1_TYPE != IS_TMP_VAR) {
6847 Z_ADDREF_P(array_ptr);
6848 }
6849
6850 if (zend_hash_num_elements(properties) == 0) {
6851 Z_FE_ITER_P(result) = (uint32_t) -1;
6852 FREE_OP1_IF_VAR();
6853 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6854 }
6855
6856 Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
6857 FREE_OP1_IF_VAR();
6858 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6859 } else {
6860 bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC);
6861
6862 FREE_OP1();
6863 if (UNEXPECTED(EG(exception))) {
6864 HANDLE_EXCEPTION();
6865 } else if (is_empty) {
6866 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
6867 } else {
6868 ZEND_VM_NEXT_OPCODE();
6869 }
6870 }
6871 } else {
6872 zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr));
6873 ZVAL_UNDEF(EX_VAR(opline->result.var));
6874 Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
6875 FREE_OP1();
6876 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6877 }
6878 }
6879
6880 ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
6881 {
6882 USE_OPLINE
6883 zval *array_ptr, *array_ref;
6884
6885 SAVE_OPLINE();
6886
6887 if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
6888 array_ref = array_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
6889 if (Z_ISREF_P(array_ref)) {
6890 array_ptr = Z_REFVAL_P(array_ref);
6891 }
6892 } else {
6893 array_ref = array_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
6894 }
6895
6896 if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) {
6897 if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
6898 if (array_ptr == array_ref) {
6899 ZVAL_NEW_REF(array_ref, array_ref);
6900 array_ptr = Z_REFVAL_P(array_ref);
6901 }
6902 Z_ADDREF_P(array_ref);
6903 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
6904 } else {
6905 array_ref = EX_VAR(opline->result.var);
6906 ZVAL_NEW_REF(array_ref, array_ptr);
6907 array_ptr = Z_REFVAL_P(array_ref);
6908 }
6909 if (OP1_TYPE == IS_CONST) {
6910 ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr)));
6911 } else {
6912 SEPARATE_ARRAY(array_ptr);
6913 }
6914 Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0);
6915
6916 FREE_OP1_IF_VAR();
6917 ZEND_VM_NEXT_OPCODE();
6918 } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
6919 if (!Z_OBJCE_P(array_ptr)->get_iterator) {
6920 zend_object *zobj = Z_OBJ_P(array_ptr);
6921 HashTable *properties;
6922 if (UNEXPECTED(zend_object_is_lazy(zobj))) {
6923 zobj = zend_lazy_object_init(zobj);
6924 if (UNEXPECTED(EG(exception))) {
6925 UNDEF_RESULT();
6926 FREE_OP1_IF_VAR();
6927 HANDLE_EXCEPTION();
6928 }
6929 }
6930 if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
6931 if (array_ptr == array_ref) {
6932 ZVAL_NEW_REF(array_ref, array_ref);
6933 array_ptr = Z_REFVAL_P(array_ref);
6934 }
6935 Z_ADDREF_P(array_ref);
6936 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
6937 } else {
6938 array_ptr = EX_VAR(opline->result.var);
6939 ZVAL_COPY_VALUE(array_ptr, array_ref);
6940 }
6941 if (Z_OBJ_P(array_ptr)->properties
6942 && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
6943 if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
6944 GC_DELREF(Z_OBJ_P(array_ptr)->properties);
6945 }
6946 Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
6947 }
6948
6949 properties = Z_OBJPROP_P(array_ptr);
6950 if (zend_hash_num_elements(properties) == 0) {
6951 Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
6952 FREE_OP1_IF_VAR();
6953 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6954 }
6955
6956 Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
6957 FREE_OP1_IF_VAR();
6958 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6959 } else {
6960 bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC);
6961 FREE_OP1();
6962 if (UNEXPECTED(EG(exception))) {
6963 HANDLE_EXCEPTION();
6964 } else if (is_empty) {
6965 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
6966 } else {
6967 ZEND_VM_NEXT_OPCODE();
6968 }
6969 }
6970 } else {
6971 zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr));
6972 ZVAL_UNDEF(EX_VAR(opline->result.var));
6973 Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
6974 FREE_OP1();
6975 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6976 }
6977 }
6978
ZEND_VM_HELPER(zend_fe_fetch_object_helper,ANY,ANY)6979 ZEND_VM_HELPER(zend_fe_fetch_object_helper, ANY, ANY)
6980 {
6981 USE_OPLINE
6982 zval *array;
6983 zval *value;
6984 uint32_t value_type;
6985 HashTable *fe_ht;
6986 HashPosition pos;
6987 Bucket *p;
6988 zend_object_iterator *iter;
6989
6990 array = EX_VAR(opline->op1.var);
6991 SAVE_OPLINE();
6992
6993 ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT);
6994 if ((iter = zend_iterator_unwrap(array)) == NULL) {
6995 /* plain object */
6996
6997 fe_ht = Z_OBJPROP_P(array);
6998 pos = zend_hash_iterator_pos(Z_FE_ITER_P(array), fe_ht);
6999 p = fe_ht->arData + pos;
7000 while (1) {
7001 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7002 /* reached end of iteration */
7003 ZEND_VM_C_GOTO(fe_fetch_r_exit);
7004 }
7005 pos++;
7006 value = &p->val;
7007 value_type = Z_TYPE_INFO_P(value);
7008 if (EXPECTED(value_type != IS_UNDEF)) {
7009 if (UNEXPECTED(value_type == IS_INDIRECT)) {
7010 value = Z_INDIRECT_P(value);
7011 value_type = Z_TYPE_INFO_P(value);
7012 if (EXPECTED(value_type != IS_UNDEF)
7013 && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
7014 break;
7015 }
7016 } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
7017 || !p->key
7018 || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
7019 break;
7020 }
7021 }
7022 p++;
7023 }
7024 EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos;
7025 if (RETURN_VALUE_USED(opline)) {
7026 if (UNEXPECTED(!p->key)) {
7027 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7028 } else if (ZSTR_VAL(p->key)[0]) {
7029 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7030 } else {
7031 const char *class_name, *prop_name;
7032 size_t prop_name_len;
7033 zend_unmangle_property_name_ex(
7034 p->key, &class_name, &prop_name, &prop_name_len);
7035 ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len);
7036 }
7037 }
7038 } else {
7039 const zend_object_iterator_funcs *funcs = iter->funcs;
7040 if (EXPECTED(++iter->index > 0)) {
7041 /* This could cause an endless loop if index becomes zero again.
7042 * In case that ever happens we need an additional flag. */
7043 funcs->move_forward(iter);
7044 if (UNEXPECTED(EG(exception) != NULL)) {
7045 UNDEF_RESULT();
7046 HANDLE_EXCEPTION();
7047 }
7048 if (UNEXPECTED(funcs->valid(iter) == FAILURE)) {
7049 /* reached end of iteration */
7050 if (UNEXPECTED(EG(exception) != NULL)) {
7051 UNDEF_RESULT();
7052 HANDLE_EXCEPTION();
7053 }
7054 ZEND_VM_C_LABEL(fe_fetch_r_exit):
7055 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7056 ZEND_VM_CONTINUE();
7057 }
7058 }
7059 value = funcs->get_current_data(iter);
7060 if (UNEXPECTED(EG(exception) != NULL)) {
7061 UNDEF_RESULT();
7062 HANDLE_EXCEPTION();
7063 }
7064 if (!value) {
7065 /* failure in get_current_data */
7066 ZEND_VM_C_GOTO(fe_fetch_r_exit);
7067 }
7068 if (RETURN_VALUE_USED(opline)) {
7069 if (funcs->get_current_key) {
7070 funcs->get_current_key(iter, EX_VAR(opline->result.var));
7071 if (UNEXPECTED(EG(exception) != NULL)) {
7072 UNDEF_RESULT();
7073 HANDLE_EXCEPTION();
7074 }
7075 } else {
7076 ZVAL_LONG(EX_VAR(opline->result.var), iter->index);
7077 }
7078 }
7079 value_type = Z_TYPE_INFO_P(value);
7080 }
7081
7082 if (EXPECTED(OP2_TYPE == IS_CV)) {
7083 zval *variable_ptr = EX_VAR(opline->op2.var);
7084 zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
7085 } else {
7086 zval *res = EX_VAR(opline->op2.var);
7087 zend_refcounted *gc = Z_COUNTED_P(value);
7088
7089 ZVAL_COPY_VALUE_EX(res, value, gc, value_type);
7090 if (Z_TYPE_INFO_REFCOUNTED(value_type)) {
7091 GC_ADDREF(gc);
7092 }
7093 }
7094 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7095 }
7096
7097 ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
7098 {
7099 USE_OPLINE
7100 zval *array;
7101 zval *value;
7102 uint32_t value_type;
7103 HashTable *fe_ht;
7104 HashPosition pos;
7105
7106 array = EX_VAR(opline->op1.var);
7107 if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) {
7108 ZEND_VM_DISPATCH_TO_HELPER(zend_fe_fetch_object_helper);
7109 }
7110 fe_ht = Z_ARRVAL_P(array);
7111 pos = Z_FE_POS_P(array);
7112 if (HT_IS_PACKED(fe_ht)) {
7113 value = fe_ht->arPacked + pos;
7114 while (1) {
7115 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7116 /* reached end of iteration */
7117 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7118 ZEND_VM_CONTINUE();
7119 }
7120 value_type = Z_TYPE_INFO_P(value);
7121 ZEND_ASSERT(value_type != IS_INDIRECT);
7122 if (EXPECTED(value_type != IS_UNDEF)) {
7123 break;
7124 }
7125 pos++;
7126 value++;
7127 }
7128 Z_FE_POS_P(array) = pos + 1;
7129 if (RETURN_VALUE_USED(opline)) {
7130 ZVAL_LONG(EX_VAR(opline->result.var), pos);
7131 }
7132 } else {
7133 Bucket *p;
7134
7135 p = fe_ht->arData + pos;
7136 while (1) {
7137 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7138 /* reached end of iteration */
7139 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7140 ZEND_VM_CONTINUE();
7141 }
7142 pos++;
7143 value = &p->val;
7144 value_type = Z_TYPE_INFO_P(value);
7145 ZEND_ASSERT(value_type != IS_INDIRECT);
7146 if (EXPECTED(value_type != IS_UNDEF)) {
7147 break;
7148 }
7149 p++;
7150 }
7151 Z_FE_POS_P(array) = pos;
7152 if (RETURN_VALUE_USED(opline)) {
7153 if (!p->key) {
7154 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7155 } else {
7156 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7157 }
7158 }
7159 }
7160 if (EXPECTED(OP2_TYPE == IS_CV)) {
7161 zval *variable_ptr = EX_VAR(opline->op2.var);
7162 SAVE_OPLINE();
7163 zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
7164 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7165 } else {
7166 zval *res = EX_VAR(opline->op2.var);
7167 zend_refcounted *gc = Z_COUNTED_P(value);
7168
7169 ZVAL_COPY_VALUE_EX(res, value, gc, value_type);
7170 if (Z_TYPE_INFO_REFCOUNTED(value_type)) {
7171 GC_ADDREF(gc);
7172 }
7173 ZEND_VM_NEXT_OPCODE();
7174 }
7175 }
7176
7177 ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR)
7178 {
7179 USE_OPLINE
7180 zval *array;
7181 zval *value;
7182 uint32_t value_type;
7183 HashTable *fe_ht;
7184 HashPosition pos;
7185 Bucket *p;
7186
7187 array = EX_VAR(opline->op1.var);
7188 SAVE_OPLINE();
7189
7190 ZVAL_DEREF(array);
7191 if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
7192 pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array);
7193 fe_ht = Z_ARRVAL_P(array);
7194 if (HT_IS_PACKED(fe_ht)) {
7195 value = fe_ht->arPacked + pos;
7196 while (1) {
7197 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7198 /* reached end of iteration */
7199 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7200 }
7201 value_type = Z_TYPE_INFO_P(value);
7202 ZEND_ASSERT(value_type != IS_INDIRECT);
7203 if (EXPECTED(value_type != IS_UNDEF)) {
7204 break;
7205 }
7206 pos++;
7207 value++;
7208 }
7209 EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1;
7210 if (RETURN_VALUE_USED(opline)) {
7211 ZVAL_LONG(EX_VAR(opline->result.var), pos);
7212 }
7213 } else {
7214 p = fe_ht->arData + pos;
7215 while (1) {
7216 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7217 /* reached end of iteration */
7218 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7219 }
7220 pos++;
7221 value = &p->val;
7222 value_type = Z_TYPE_INFO_P(value);
7223 ZEND_ASSERT(value_type != IS_INDIRECT);
7224 if (EXPECTED(value_type != IS_UNDEF)) {
7225 break;
7226 }
7227 p++;
7228 }
7229 EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos;
7230 if (RETURN_VALUE_USED(opline)) {
7231 if (!p->key) {
7232 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7233 } else {
7234 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7235 }
7236 }
7237 }
7238 } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
7239 zend_object_iterator *iter;
7240
7241 if ((iter = zend_iterator_unwrap(array)) == NULL) {
7242 /* plain object */
7243
7244 fe_ht = Z_OBJPROP_P(array);
7245 pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht);
7246 p = fe_ht->arData + pos;
7247 while (1) {
7248 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7249 /* reached end of iteration */
7250 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7251 }
7252 pos++;
7253 value = &p->val;
7254 value_type = Z_TYPE_INFO_P(value);
7255 if (EXPECTED(value_type != IS_UNDEF)) {
7256 if (UNEXPECTED(value_type == IS_INDIRECT)) {
7257 value = Z_INDIRECT_P(value);
7258 value_type = Z_TYPE_INFO_P(value);
7259 if (EXPECTED(value_type != IS_UNDEF)
7260 && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
7261 if ((value_type & Z_TYPE_MASK) != IS_REFERENCE) {
7262 zend_property_info *prop_info =
7263 zend_get_property_info_for_slot(Z_OBJ_P(array), value);
7264 if (prop_info) {
7265 if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) {
7266 zend_throw_error(NULL,
7267 "Cannot acquire reference to readonly property %s::$%s",
7268 ZSTR_VAL(prop_info->ce->name), ZSTR_VAL(p->key));
7269 UNDEF_RESULT();
7270 HANDLE_EXCEPTION();
7271 }
7272 if (ZEND_TYPE_IS_SET(prop_info->type)) {
7273 ZVAL_NEW_REF(value, value);
7274 ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(value), prop_info);
7275 value_type = IS_REFERENCE_EX;
7276 }
7277 }
7278 }
7279 break;
7280 }
7281 } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
7282 || !p->key
7283 || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
7284 break;
7285 }
7286 }
7287 p++;
7288 }
7289 EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos;
7290 if (RETURN_VALUE_USED(opline)) {
7291 if (UNEXPECTED(!p->key)) {
7292 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7293 } else if (ZSTR_VAL(p->key)[0]) {
7294 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7295 } else {
7296 const char *class_name, *prop_name;
7297 size_t prop_name_len;
7298 zend_unmangle_property_name_ex(
7299 p->key, &class_name, &prop_name, &prop_name_len);
7300 ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len);
7301 }
7302 }
7303 } else {
7304 const zend_object_iterator_funcs *funcs = iter->funcs;
7305 if (++iter->index > 0) {
7306 /* This could cause an endless loop if index becomes zero again.
7307 * In case that ever happens we need an additional flag. */
7308 funcs->move_forward(iter);
7309 if (UNEXPECTED(EG(exception) != NULL)) {
7310 UNDEF_RESULT();
7311 HANDLE_EXCEPTION();
7312 }
7313 if (UNEXPECTED(funcs->valid(iter) == FAILURE)) {
7314 /* reached end of iteration */
7315 if (UNEXPECTED(EG(exception) != NULL)) {
7316 UNDEF_RESULT();
7317 HANDLE_EXCEPTION();
7318 }
7319 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7320 }
7321 }
7322 value = funcs->get_current_data(iter);
7323 if (UNEXPECTED(EG(exception) != NULL)) {
7324 UNDEF_RESULT();
7325 HANDLE_EXCEPTION();
7326 }
7327 if (!value) {
7328 /* failure in get_current_data */
7329 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7330 }
7331 if (RETURN_VALUE_USED(opline)) {
7332 if (funcs->get_current_key) {
7333 funcs->get_current_key(iter, EX_VAR(opline->result.var));
7334 if (UNEXPECTED(EG(exception) != NULL)) {
7335 UNDEF_RESULT();
7336 HANDLE_EXCEPTION();
7337 }
7338 } else {
7339 ZVAL_LONG(EX_VAR(opline->result.var), iter->index);
7340 }
7341 }
7342 value_type = Z_TYPE_INFO_P(value);
7343 }
7344 } else {
7345 zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array));
7346 if (UNEXPECTED(EG(exception))) {
7347 UNDEF_RESULT();
7348 HANDLE_EXCEPTION();
7349 }
7350 ZEND_VM_C_LABEL(fe_fetch_w_exit):
7351 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7352 ZEND_VM_CONTINUE();
7353 }
7354
7355 if (EXPECTED((value_type & Z_TYPE_MASK) != IS_REFERENCE)) {
7356 zend_refcounted *gc = Z_COUNTED_P(value);
7357 zval *ref;
7358 ZVAL_NEW_EMPTY_REF(value);
7359 ref = Z_REFVAL_P(value);
7360 ZVAL_COPY_VALUE_EX(ref, value, gc, value_type);
7361 }
7362 if (EXPECTED(OP2_TYPE == IS_CV)) {
7363 zval *variable_ptr = EX_VAR(opline->op2.var);
7364 if (EXPECTED(variable_ptr != value)) {
7365 zend_reference *ref;
7366
7367 ref = Z_REF_P(value);
7368 GC_ADDREF(ref);
7369 i_zval_ptr_dtor(variable_ptr);
7370 ZVAL_REF(variable_ptr, ref);
7371 }
7372 } else {
7373 Z_ADDREF_P(value);
7374 ZVAL_REF(EX_VAR(opline->op2.var), Z_REF_P(value));
7375 }
7376 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7377 }
7378
7379 ZEND_VM_HOT_HANDLER(154, ZEND_ISSET_ISEMPTY_CV, CV, UNUSED, ISSET, SPEC(ISSET))
7380 {
7381 USE_OPLINE
7382 zval *value;
7383
7384 value = EX_VAR(opline->op1.var);
7385 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7386 if (Z_TYPE_P(value) > IS_NULL &&
7387 (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
7388 ZEND_VM_SMART_BRANCH_TRUE();
7389 } else {
7390 ZEND_VM_SMART_BRANCH_FALSE();
7391 }
7392 } else {
7393 bool result;
7394
7395 SAVE_OPLINE();
7396 result = !i_zend_is_true(value);
7397 ZEND_VM_SMART_BRANCH(result, 1);
7398 }
7399 }
7400
7401 ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ISSET)
7402 {
7403 USE_OPLINE
7404 zval *value;
7405 bool result;
7406 zval *varname;
7407 zend_string *name, *tmp_name;
7408 HashTable *target_symbol_table;
7409
7410 SAVE_OPLINE();
7411 varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
7412 if (OP1_TYPE == IS_CONST) {
7413 name = Z_STR_P(varname);
7414 } else {
7415 name = zval_get_tmp_string(varname, &tmp_name);
7416 }
7417
7418 target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
7419 value = zend_hash_find_ex(target_symbol_table, name, OP1_TYPE == IS_CONST);
7420
7421 if (OP1_TYPE != IS_CONST) {
7422 zend_tmp_string_release(tmp_name);
7423 }
7424 FREE_OP1();
7425
7426 if (!value) {
7427 result = (opline->extended_value & ZEND_ISEMPTY);
7428 } else {
7429 if (Z_TYPE_P(value) == IS_INDIRECT) {
7430 value = Z_INDIRECT_P(value);
7431 }
7432 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7433 if (Z_ISREF_P(value)) {
7434 value = Z_REFVAL_P(value);
7435 }
7436 result = Z_TYPE_P(value) > IS_NULL;
7437 } else {
7438 result = !i_zend_is_true(value);
7439 }
7440 }
7441
7442 ZEND_VM_SMART_BRANCH(result, true);
7443 }
7444
7445 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
7446 ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, ANY, CLASS_FETCH, ISSET|CACHE_SLOT)
7447 {
7448 USE_OPLINE
7449 zval *value;
7450 zend_result fetch_result;
7451 bool result;
7452
7453 SAVE_OPLINE();
7454
7455 fetch_result = zend_fetch_static_property_address(&value, NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC);
7456
7457 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7458 result = fetch_result == SUCCESS && Z_TYPE_P(value) > IS_NULL &&
7459 (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
7460 } else {
7461 result = fetch_result != SUCCESS || !i_zend_is_true(value);
7462 }
7463
7464 ZEND_VM_SMART_BRANCH(result, 1);
7465 }
7466
7467 ZEND_VM_COLD_CONSTCONST_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|CV, CONST|TMPVAR|CV, ISSET)
7468 {
7469 USE_OPLINE
7470 zval *container;
7471 bool result;
7472 zend_ulong hval;
7473 zval *offset;
7474
7475 SAVE_OPLINE();
7476 container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_IS);
7477 offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
7478
7479 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
7480 HashTable *ht;
7481 zval *value;
7482 zend_string *str;
7483
7484 ZEND_VM_C_LABEL(isset_dim_obj_array):
7485 ht = Z_ARRVAL_P(container);
7486 ZEND_VM_C_LABEL(isset_again):
7487 if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
7488 str = Z_STR_P(offset);
7489 if (OP2_TYPE != IS_CONST) {
7490 if (ZEND_HANDLE_NUMERIC(str, hval)) {
7491 ZEND_VM_C_GOTO(num_index_prop);
7492 }
7493 }
7494 value = zend_hash_find_ex(ht, str, OP2_TYPE == IS_CONST);
7495 } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
7496 hval = Z_LVAL_P(offset);
7497 ZEND_VM_C_LABEL(num_index_prop):
7498 value = zend_hash_index_find(ht, hval);
7499 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
7500 offset = Z_REFVAL_P(offset);
7501 ZEND_VM_C_GOTO(isset_again);
7502 } else {
7503 value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
7504 if (UNEXPECTED(EG(exception))) {
7505 result = 0;
7506 ZEND_VM_C_GOTO(isset_dim_obj_exit);
7507 }
7508 }
7509
7510 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7511 /* > IS_NULL means not IS_UNDEF and not IS_NULL */
7512 result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
7513 (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
7514
7515 if (OP1_TYPE & (IS_CONST|IS_CV)) {
7516 /* avoid exception check */
7517 FREE_OP2();
7518 ZEND_VM_SMART_BRANCH(result, 0);
7519 }
7520 } else {
7521 result = (value == NULL || !i_zend_is_true(value));
7522 }
7523 ZEND_VM_C_GOTO(isset_dim_obj_exit);
7524 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) {
7525 container = Z_REFVAL_P(container);
7526 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
7527 ZEND_VM_C_GOTO(isset_dim_obj_array);
7528 }
7529 }
7530
7531 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
7532 offset++;
7533 }
7534 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7535 result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC);
7536 } else {
7537 result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC);
7538 }
7539
7540 ZEND_VM_C_LABEL(isset_dim_obj_exit):
7541 FREE_OP2();
7542 FREE_OP1();
7543 ZEND_VM_SMART_BRANCH(result, 1);
7544 }
7545
7546 ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, ISSET|CACHE_SLOT)
7547 {
7548 USE_OPLINE
7549 zval *container;
7550 int result;
7551 zval *offset;
7552 zend_string *name, *tmp_name;
7553
7554 SAVE_OPLINE();
7555 container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
7556 offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
7557
7558 if (OP1_TYPE == IS_CONST ||
7559 (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
7560 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
7561 container = Z_REFVAL_P(container);
7562 if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
7563 result = (opline->extended_value & ZEND_ISEMPTY);
7564 ZEND_VM_C_GOTO(isset_object_finish);
7565 }
7566 } else {
7567 result = (opline->extended_value & ZEND_ISEMPTY);
7568 ZEND_VM_C_GOTO(isset_object_finish);
7569 }
7570 }
7571
7572 if (OP2_TYPE == IS_CONST) {
7573 name = Z_STR_P(offset);
7574 } else {
7575 name = zval_try_get_tmp_string(offset, &tmp_name);
7576 if (UNEXPECTED(!name)) {
7577 result = 0;
7578 ZEND_VM_C_GOTO(isset_object_finish);
7579 }
7580 }
7581
7582 result =
7583 (opline->extended_value & ZEND_ISEMPTY) ^
7584 Z_OBJ_HT_P(container)->has_property(Z_OBJ_P(container), name, (opline->extended_value & ZEND_ISEMPTY), ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_ISEMPTY) : NULL));
7585
7586 if (OP2_TYPE != IS_CONST) {
7587 zend_tmp_string_release(tmp_name);
7588 }
7589
7590 ZEND_VM_C_LABEL(isset_object_finish):
7591 FREE_OP2();
7592 FREE_OP1();
7593 ZEND_VM_SMART_BRANCH(result, 1);
7594 }
7595
7596 ZEND_VM_HANDLER(194, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST)
7597 {
7598 USE_OPLINE
7599
7600 zval *key, *subject;
7601 HashTable *ht;
7602 bool result;
7603
7604 SAVE_OPLINE();
7605
7606 key = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7607 subject = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
7608
7609 if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
7610 ZEND_VM_C_LABEL(array_key_exists_array):
7611 ht = Z_ARRVAL_P(subject);
7612 result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC);
7613 } else {
7614 if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) {
7615 subject = Z_REFVAL_P(subject);
7616 if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
7617 ZEND_VM_C_GOTO(array_key_exists_array);
7618 }
7619 }
7620 zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
7621 result = 0;
7622 }
7623
7624 FREE_OP2();
7625 FREE_OP1();
7626 ZEND_VM_SMART_BRANCH(result, 1);
7627 }
7628
7629 ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
7630 {
7631 USE_OPLINE
7632
7633 ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
7634
7635 if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) {
7636 do {
7637 /* Do not silence fatal errors */
7638 EG(error_reporting) &= E_FATAL_ERRORS;
7639 if (!EG(error_reporting_ini_entry)) {
7640 zval *zv = zend_hash_find_known_hash(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING));
7641 if (zv) {
7642 EG(error_reporting_ini_entry) = (zend_ini_entry *)Z_PTR_P(zv);
7643 } else {
7644 break;
7645 }
7646 }
7647 if (!EG(error_reporting_ini_entry)->modified) {
7648 if (!EG(modified_ini_directives)) {
7649 ALLOC_HASHTABLE(EG(modified_ini_directives));
7650 zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
7651 }
7652 if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), EG(error_reporting_ini_entry)) != NULL)) {
7653 EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
7654 EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
7655 EG(error_reporting_ini_entry)->modified = 1;
7656 }
7657 }
7658 } while (0);
7659 }
7660 ZEND_VM_NEXT_OPCODE();
7661 }
7662
7663 ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
7664 {
7665 USE_OPLINE
7666
7667 if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))
7668 && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) {
7669 EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var));
7670 }
7671 ZEND_VM_NEXT_OPCODE();
7672 }
7673
7674 ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR)
7675 {
7676 USE_OPLINE
7677 zval *value;
7678 zend_reference *ref = NULL;
7679 bool ret;
7680
7681 SAVE_OPLINE();
7682 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
7683
7684 if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && Z_ISREF_P(value)) {
7685 if (OP1_TYPE == IS_VAR) {
7686 ref = Z_REF_P(value);
7687 }
7688 value = Z_REFVAL_P(value);
7689 }
7690
7691 ret = i_zend_is_true(value);
7692
7693 if (UNEXPECTED(EG(exception))) {
7694 FREE_OP1();
7695 ZVAL_UNDEF(EX_VAR(opline->result.var));
7696 HANDLE_EXCEPTION();
7697 }
7698
7699 if (ret) {
7700 zval *result = EX_VAR(opline->result.var);
7701
7702 ZVAL_COPY_VALUE(result, value);
7703 if (OP1_TYPE == IS_CONST) {
7704 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result);
7705 } else if (OP1_TYPE == IS_CV) {
7706 if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result);
7707 } else if (OP1_TYPE == IS_VAR && ref) {
7708 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
7709 efree_size(ref, sizeof(zend_reference));
7710 } else if (Z_OPT_REFCOUNTED_P(result)) {
7711 Z_ADDREF_P(result);
7712 }
7713 }
7714 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
7715 }
7716
7717 FREE_OP1();
7718 ZEND_VM_NEXT_OPCODE();
7719 }
7720
7721 ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
7722 {
7723 USE_OPLINE
7724 zval *value;
7725 zend_reference *ref = NULL;
7726
7727 SAVE_OPLINE();
7728 value = GET_OP1_ZVAL_PTR(BP_VAR_IS);
7729
7730 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
7731 if (OP1_TYPE & IS_VAR) {
7732 ref = Z_REF_P(value);
7733 }
7734 value = Z_REFVAL_P(value);
7735 }
7736
7737 if (Z_TYPE_P(value) > IS_NULL) {
7738 zval *result = EX_VAR(opline->result.var);
7739 ZVAL_COPY_VALUE(result, value);
7740 if (OP1_TYPE == IS_CONST) {
7741 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result);
7742 } else if (OP1_TYPE == IS_CV) {
7743 if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result);
7744 } else if ((OP1_TYPE & IS_VAR) && ref) {
7745 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
7746 efree_size(ref, sizeof(zend_reference));
7747 } else if (Z_OPT_REFCOUNTED_P(result)) {
7748 Z_ADDREF_P(result);
7749 }
7750 }
7751 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
7752 }
7753
7754 if ((OP1_TYPE & IS_VAR) && ref) {
7755 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
7756 efree_size(ref, sizeof(zend_reference));
7757 }
7758 }
7759 ZEND_VM_NEXT_OPCODE();
7760 }
7761
7762 ZEND_VM_HOT_NOCONST_HANDLER(198, ZEND_JMP_NULL, CONST|TMP|VAR|CV, JMP_ADDR)
7763 {
7764 USE_OPLINE
7765 zval *val, *result;
7766
7767 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7768
7769 if (Z_TYPE_P(val) > IS_NULL) {
7770 do {
7771 if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) {
7772 val = Z_REFVAL_P(val);
7773 if (Z_TYPE_P(val) <= IS_NULL) {
7774 FREE_OP1();
7775 break;
7776 }
7777 }
7778 ZEND_VM_NEXT_OPCODE();
7779 } while (0);
7780 }
7781
7782 result = EX_VAR(opline->result.var);
7783 uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK;
7784 if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) {
7785 ZVAL_NULL(result);
7786 if (OP1_TYPE == IS_CV
7787 && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF)
7788 && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0
7789 ) {
7790 SAVE_OPLINE();
7791 ZVAL_UNDEFINED_OP1();
7792 if (UNEXPECTED(EG(exception) != NULL)) {
7793 HANDLE_EXCEPTION();
7794 }
7795 }
7796 } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) {
7797 ZVAL_FALSE(result);
7798 } else {
7799 ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY);
7800 ZVAL_TRUE(result);
7801 }
7802
7803 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
7804 }
7805
7806 ZEND_VM_HOT_HANDLER(31, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
7807 {
7808 USE_OPLINE
7809 zval *value;
7810 zval *result = EX_VAR(opline->result.var);
7811
7812 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7813 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
7814 SAVE_OPLINE();
7815 ZVAL_UNDEFINED_OP1();
7816 ZVAL_NULL(result);
7817 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7818 }
7819
7820 if (OP1_TYPE == IS_CV) {
7821 ZVAL_COPY_DEREF(result, value);
7822 } else if (OP1_TYPE == IS_VAR) {
7823 if (UNEXPECTED(Z_ISREF_P(value))) {
7824 ZVAL_COPY_VALUE(result, Z_REFVAL_P(value));
7825 if (UNEXPECTED(Z_DELREF_P(value) == 0)) {
7826 efree_size(Z_REF_P(value), sizeof(zend_reference));
7827 } else if (Z_OPT_REFCOUNTED_P(result)) {
7828 Z_ADDREF_P(result);
7829 }
7830 } else {
7831 ZVAL_COPY_VALUE(result, value);
7832 }
7833 } else {
7834 ZVAL_COPY_VALUE(result, value);
7835 if (OP1_TYPE == IS_CONST) {
7836 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) {
7837 Z_ADDREF_P(result);
7838 }
7839 }
7840 }
7841 ZEND_VM_NEXT_OPCODE();
7842 }
7843
7844 ZEND_VM_COLD_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
7845 {
7846 USE_OPLINE
7847
7848 if (!EG(no_extensions)) {
7849 SAVE_OPLINE();
7850 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, execute_data);
7851 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7852 }
7853 ZEND_VM_NEXT_OPCODE();
7854 }
7855
7856 ZEND_VM_COLD_HANDLER(102, ZEND_EXT_FCALL_BEGIN, ANY, ANY)
7857 {
7858 USE_OPLINE
7859
7860 if (!EG(no_extensions)) {
7861 SAVE_OPLINE();
7862 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, execute_data);
7863 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7864 }
7865 ZEND_VM_NEXT_OPCODE();
7866 }
7867
7868 ZEND_VM_COLD_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY)
7869 {
7870 USE_OPLINE
7871
7872 if (!EG(no_extensions)) {
7873 SAVE_OPLINE();
7874 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, execute_data);
7875 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7876 }
7877 ZEND_VM_NEXT_OPCODE();
7878 }
7879
7880 ZEND_VM_HANDLER(144, ZEND_DECLARE_CLASS, CONST, ANY)
7881 {
7882 USE_OPLINE
7883
7884 SAVE_OPLINE();
7885 do_bind_class(RT_CONSTANT(opline, opline->op1), (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
7886 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7887 }
7888
7889 ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
7890 {
7891 USE_OPLINE
7892
7893 zend_class_entry *ce = CACHED_PTR(opline->extended_value);
7894 if (ce == NULL) {
7895 zval *lcname = RT_CONSTANT(opline, opline->op1);
7896 zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
7897 if (zv) {
7898 SAVE_OPLINE();
7899 ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
7900 if (!ce) {
7901 HANDLE_EXCEPTION();
7902 }
7903 }
7904 CACHE_PTR(opline->extended_value, ce);
7905 }
7906 ZEND_VM_NEXT_OPCODE();
7907 }
7908
7909 ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
7910 {
7911 zval *zv;
7912 zend_class_entry *ce;
7913 USE_OPLINE
7914
7915 ce = CACHED_PTR(opline->extended_value);
7916 if (UNEXPECTED(ce == NULL)) {
7917 zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
7918 zv = zend_hash_find_known_hash(EG(class_table), rtd_key);
7919 ZEND_ASSERT(zv != NULL);
7920 ce = Z_CE_P(zv);
7921 if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
7922 SAVE_OPLINE();
7923 ce = zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL, rtd_key);
7924 if (!ce) {
7925 HANDLE_EXCEPTION();
7926 }
7927 }
7928 CACHE_PTR(opline->extended_value, ce);
7929 }
7930 Z_CE_P(EX_VAR(opline->result.var)) = ce;
7931 ZEND_VM_NEXT_OPCODE();
7932 }
7933
7934 ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, NUM)
7935 {
7936 zend_function *func;
7937 USE_OPLINE
7938
7939 SAVE_OPLINE();
7940 func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num];
7941 do_bind_function(func, RT_CONSTANT(opline, opline->op1));
7942 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7943 }
7944
7945 ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM)
7946 {
7947 USE_OPLINE
7948
7949 if ((uint32_t)++EG(ticks_count) >= opline->extended_value) {
7950 EG(ticks_count) = 0;
7951 if (zend_ticks_function) {
7952 SAVE_OPLINE();
7953 zend_fiber_switch_block();
7954 zend_ticks_function(opline->extended_value);
7955 zend_fiber_switch_unblock();
7956 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7957 }
7958 }
7959 ZEND_VM_NEXT_OPCODE();
7960 }
7961
7962 ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
7963 {
7964 USE_OPLINE
7965 zval *expr;
7966 bool result;
7967
7968 SAVE_OPLINE();
7969 expr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7970
7971 ZEND_VM_C_LABEL(try_instanceof):
7972 if (Z_TYPE_P(expr) == IS_OBJECT) {
7973 zend_class_entry *ce;
7974
7975 if (OP2_TYPE == IS_CONST) {
7976 ce = CACHED_PTR(opline->extended_value);
7977 if (UNEXPECTED(ce == NULL)) {
7978 ce = zend_lookup_class_ex(Z_STR_P(RT_CONSTANT(opline, opline->op2)), Z_STR_P(RT_CONSTANT(opline, opline->op2) + 1), ZEND_FETCH_CLASS_NO_AUTOLOAD);
7979 if (EXPECTED(ce)) {
7980 CACHE_PTR(opline->extended_value, ce);
7981 }
7982 }
7983 } else if (OP2_TYPE == IS_UNUSED) {
7984 ce = zend_fetch_class(NULL, opline->op2.num);
7985 if (UNEXPECTED(ce == NULL)) {
7986 FREE_OP1();
7987 ZVAL_UNDEF(EX_VAR(opline->result.var));
7988 HANDLE_EXCEPTION();
7989 }
7990 } else {
7991 ce = Z_CE_P(EX_VAR(opline->op2.var));
7992 }
7993 result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
7994 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
7995 expr = Z_REFVAL_P(expr);
7996 ZEND_VM_C_GOTO(try_instanceof);
7997 } else {
7998 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) {
7999 ZVAL_UNDEFINED_OP1();
8000 }
8001 result = 0;
8002 }
8003 FREE_OP1();
8004 ZEND_VM_SMART_BRANCH(result, 1);
8005 }
8006
8007 ZEND_VM_HOT_HANDLER(104, ZEND_EXT_NOP, ANY, ANY)
8008 {
8009 USE_OPLINE
8010
8011 ZEND_VM_NEXT_OPCODE();
8012 }
8013
8014 ZEND_VM_HOT_HANDLER(0, ZEND_NOP, ANY, ANY)
8015 {
8016 USE_OPLINE
8017
8018 ZEND_VM_NEXT_OPCODE();
8019 }
8020
ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper,ANY,ANY,uint32_t try_catch_offset,uint32_t op_num)8021 ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_catch_offset, uint32_t op_num)
8022 {
8023 /* May be NULL during generator closing (only finally blocks are executed) */
8024 zend_object *ex = EG(exception);
8025
8026 /* Walk try/catch/finally structures upwards, performing the necessary actions */
8027 for (; try_catch_offset != (uint32_t) -1; try_catch_offset--) {
8028 zend_try_catch_element *try_catch =
8029 &EX(func)->op_array.try_catch_array[try_catch_offset];
8030
8031 if (op_num < try_catch->catch_op && ex) {
8032 /* Go to catch block */
8033 cleanup_live_vars(execute_data, op_num, try_catch->catch_op);
8034 ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0);
8035
8036 } else if (op_num < try_catch->finally_op) {
8037 if (ex && zend_is_unwind_exit(ex)) {
8038 /* Don't execute finally blocks on exit (for now) */
8039 continue;
8040 }
8041
8042 /* Go to finally block */
8043 zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var);
8044 cleanup_live_vars(execute_data, op_num, try_catch->finally_op);
8045 Z_OBJ_P(fast_call) = EG(exception);
8046 EG(exception) = NULL;
8047 Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1;
8048 ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0);
8049
8050 } else if (op_num < try_catch->finally_end) {
8051 zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var);
8052
8053 /* cleanup incomplete RETURN statement */
8054 if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1
8055 && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) {
8056 zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var);
8057
8058 zval_ptr_dtor(return_value);
8059 }
8060
8061 /* Chain potential exception from wrapping finally block */
8062 if (Z_OBJ_P(fast_call)) {
8063 if (ex) {
8064 if (zend_is_unwind_exit(ex) || zend_is_graceful_exit(ex)) {
8065 /* discard the previously thrown exception */
8066 OBJ_RELEASE(Z_OBJ_P(fast_call));
8067 } else {
8068 zend_exception_set_previous(ex, Z_OBJ_P(fast_call));
8069 }
8070 } else {
8071 ex = EG(exception) = Z_OBJ_P(fast_call);
8072 }
8073 }
8074 }
8075 }
8076
8077 /* Uncaught exception */
8078
8079 /* Don't use ZEND_OBSERVER_ENABLED because it gets replaced by zend_vm_gen.php. */
8080 if (zend_observer_fcall_op_array_extension != -1) {
8081 zend_observer_fcall_end(execute_data, NULL);
8082 }
8083 cleanup_live_vars(execute_data, op_num, 0);
8084 if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) {
8085 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8086 EG(current_execute_data) = EX(prev_execute_data);
8087 zend_generator_close(generator, 1);
8088 ZEND_VM_RETURN();
8089 } else {
8090 /* We didn't execute RETURN, and have to initialize return_value */
8091 if (EX(return_value)) {
8092 ZVAL_UNDEF(EX(return_value));
8093 }
8094 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
8095 }
8096 }
8097
8098 ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
8099 {
8100 const zend_op *throw_op = EG(opline_before_exception);
8101
8102 /* Exception was thrown before executing any op */
8103 if (UNEXPECTED(!throw_op)) {
8104 ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, op_num, 0);
8105 }
8106
8107 uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes;
8108 int i, current_try_catch_offset = -1;
8109
8110 if ((throw_op->opcode == ZEND_FREE || throw_op->opcode == ZEND_FE_FREE)
8111 && throw_op->extended_value & ZEND_FREE_ON_RETURN) {
8112 /* exceptions thrown because of loop var destruction on return/break/...
8113 * are logically thrown at the end of the foreach loop, so adjust the
8114 * throw_op_num.
8115 */
8116 const zend_live_range *range = find_live_range(
8117 &EX(func)->op_array, throw_op_num, throw_op->op1.var);
8118 /* free op1 of the corresponding RETURN */
8119 for (i = throw_op_num; i < range->end; i++) {
8120 if (EX(func)->op_array.opcodes[i].opcode == ZEND_FREE
8121 || EX(func)->op_array.opcodes[i].opcode == ZEND_FE_FREE) {
8122 /* pass */
8123 } else {
8124 if (EX(func)->op_array.opcodes[i].opcode == ZEND_RETURN
8125 && (EX(func)->op_array.opcodes[i].op1_type & (IS_VAR|IS_TMP_VAR))) {
8126 zval_ptr_dtor(EX_VAR(EX(func)->op_array.opcodes[i].op1.var));
8127 }
8128 break;
8129 }
8130 }
8131 throw_op_num = range->end;
8132 }
8133
8134 /* Find the innermost try/catch/finally the exception was thrown in */
8135 for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
8136 zend_try_catch_element *try_catch = &EX(func)->op_array.try_catch_array[i];
8137 if (try_catch->try_op > throw_op_num) {
8138 /* further blocks will not be relevant... */
8139 break;
8140 }
8141 if (throw_op_num < try_catch->catch_op || throw_op_num < try_catch->finally_end) {
8142 current_try_catch_offset = i;
8143 }
8144 }
8145
8146 cleanup_unfinished_calls(execute_data, throw_op_num);
8147
8148 if (throw_op->result_type & (IS_VAR | IS_TMP_VAR)) {
8149 switch (throw_op->opcode) {
8150 case ZEND_ADD_ARRAY_ELEMENT:
8151 case ZEND_ADD_ARRAY_UNPACK:
8152 case ZEND_ROPE_INIT:
8153 case ZEND_ROPE_ADD:
8154 break; /* exception while building structures, live range handling will free those */
8155
8156 case ZEND_FETCH_CLASS:
8157 case ZEND_DECLARE_ANON_CLASS:
8158 break; /* return value is zend_class_entry pointer */
8159
8160 default:
8161 /* smart branch opcodes may not initialize result */
8162 if (!zend_is_smart_branch(throw_op)) {
8163 zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var));
8164 }
8165 }
8166 }
8167
8168 ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, current_try_catch_offset, op_num, throw_op_num);
8169 }
8170
8171 ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
8172 {
8173 USE_OPLINE
8174 int ret;
8175
8176 SAVE_OPLINE();
8177 ret = zend_user_opcode_handlers[opline->opcode](execute_data);
8178 opline = EX(opline);
8179
8180 switch (ret) {
8181 case ZEND_USER_OPCODE_CONTINUE:
8182 ZEND_VM_CONTINUE();
8183 case ZEND_USER_OPCODE_RETURN:
8184 if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) {
8185 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8186 EG(current_execute_data) = EX(prev_execute_data);
8187 zend_generator_close(generator, 1);
8188 ZEND_VM_RETURN();
8189 } else {
8190 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
8191 }
8192 case ZEND_USER_OPCODE_ENTER:
8193 ZEND_VM_ENTER();
8194 case ZEND_USER_OPCODE_LEAVE:
8195 ZEND_VM_LEAVE();
8196 case ZEND_USER_OPCODE_DISPATCH:
8197 ZEND_VM_DISPATCH(opline->opcode, opline);
8198 default:
8199 ZEND_VM_DISPATCH((uint8_t)(ret & 0xff), opline);
8200 }
8201 }
8202
8203 ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
8204 {
8205 USE_OPLINE
8206 zval *name;
8207 zval *val;
8208 zend_constant c;
8209
8210 SAVE_OPLINE();
8211 name = GET_OP1_ZVAL_PTR(BP_VAR_R);
8212 val = GET_OP2_ZVAL_PTR(BP_VAR_R);
8213
8214 ZVAL_COPY(&c.value, val);
8215 if (Z_OPT_CONSTANT(c.value)) {
8216 if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) {
8217 zval_ptr_dtor_nogc(&c.value);
8218 FREE_OP1();
8219 FREE_OP2();
8220 HANDLE_EXCEPTION();
8221 }
8222 }
8223 /* non persistent, case sensitive */
8224 ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
8225 c.name = zend_string_copy(Z_STR_P(name));
8226
8227 if (zend_register_constant(&c) == FAILURE) {
8228 }
8229
8230 FREE_OP1();
8231 FREE_OP2();
8232 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8233 }
8234
8235 ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, NUM)
8236 {
8237 USE_OPLINE
8238 zend_function *func;
8239 zval *object;
8240 zend_class_entry *called_scope;
8241
8242 func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num];
8243 if (Z_TYPE(EX(This)) == IS_OBJECT) {
8244 called_scope = Z_OBJCE(EX(This));
8245 if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) ||
8246 (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) {
8247 object = NULL;
8248 } else {
8249 object = &EX(This);
8250 }
8251 } else {
8252 called_scope = Z_CE(EX(This));
8253 object = NULL;
8254 }
8255 SAVE_OPLINE();
8256 zend_create_closure(EX_VAR(opline->result.var), func,
8257 EX(func)->op_array.scope, called_scope, object);
8258
8259 ZEND_VM_NEXT_OPCODE();
8260 }
8261
8262 ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
8263 {
8264 USE_OPLINE
8265 zval *var_ptr;
8266
8267 var_ptr = EX_VAR(opline->op1.var);
8268 if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
8269 if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) {
8270 ZVAL_UNREF(var_ptr);
8271 }
8272 }
8273
8274 ZEND_VM_NEXT_OPCODE();
8275 }
8276
ZEND_VM_COLD_HELPER(zend_yield_in_closed_generator_helper,ANY,ANY)8277 ZEND_VM_COLD_HELPER(zend_yield_in_closed_generator_helper, ANY, ANY)
8278 {
8279 USE_OPLINE
8280
8281 SAVE_OPLINE();
8282 zend_throw_error(NULL, "Cannot yield from finally in a force-closed generator");
8283 FREE_OP2();
8284 FREE_OP1();
8285 UNDEF_RESULT();
8286 HANDLE_EXCEPTION();
8287 }
8288
8289 ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED, SRC)
8290 {
8291 USE_OPLINE
8292
8293 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8294
8295 SAVE_OPLINE();
8296 if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
8297 ZEND_VM_DISPATCH_TO_HELPER(zend_yield_in_closed_generator_helper);
8298 }
8299
8300 /* Destroy the previously yielded value */
8301 zval_ptr_dtor(&generator->value);
8302
8303 /* Destroy the previously yielded key */
8304 zval_ptr_dtor(&generator->key);
8305
8306 /* Set the new yielded value */
8307 if (OP1_TYPE != IS_UNUSED) {
8308 if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
8309 /* Constants and temporary variables aren't yieldable by reference,
8310 * but we still allow them with a notice. */
8311 if (OP1_TYPE & (IS_CONST|IS_TMP_VAR)) {
8312 zval *value;
8313
8314 zend_error(E_NOTICE, "Only variable references should be yielded by reference");
8315
8316 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
8317 ZVAL_COPY_VALUE(&generator->value, value);
8318 if (OP1_TYPE == IS_CONST) {
8319 if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) {
8320 Z_ADDREF(generator->value);
8321 }
8322 }
8323 } else {
8324 zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
8325
8326 /* If a function call result is yielded and the function did
8327 * not return by reference we throw a notice. */
8328 do {
8329 if (OP1_TYPE == IS_VAR) {
8330 ZEND_ASSERT(value_ptr != &EG(uninitialized_zval));
8331 if (opline->extended_value == ZEND_RETURNS_FUNCTION
8332 && !Z_ISREF_P(value_ptr)) {
8333 zend_error(E_NOTICE, "Only variable references should be yielded by reference");
8334 ZVAL_COPY(&generator->value, value_ptr);
8335 break;
8336 }
8337 }
8338 if (Z_ISREF_P(value_ptr)) {
8339 Z_ADDREF_P(value_ptr);
8340 } else {
8341 ZVAL_MAKE_REF_EX(value_ptr, 2);
8342 }
8343 ZVAL_REF(&generator->value, Z_REF_P(value_ptr));
8344 } while (0);
8345
8346 FREE_OP1();
8347 }
8348 } else {
8349 zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
8350
8351 /* Consts, temporary variables and references need copying */
8352 if (OP1_TYPE == IS_CONST) {
8353 ZVAL_COPY_VALUE(&generator->value, value);
8354 if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) {
8355 Z_ADDREF(generator->value);
8356 }
8357 } else if (OP1_TYPE == IS_TMP_VAR) {
8358 ZVAL_COPY_VALUE(&generator->value, value);
8359 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
8360 ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
8361 FREE_OP1_IF_VAR();
8362 } else {
8363 ZVAL_COPY_VALUE(&generator->value, value);
8364 if (OP1_TYPE == IS_CV) {
8365 if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
8366 }
8367 }
8368 }
8369 } else {
8370 /* If no value was specified yield null */
8371 ZVAL_NULL(&generator->value);
8372 }
8373
8374 /* Set the new yielded key */
8375 if (OP2_TYPE != IS_UNUSED) {
8376 zval *key = GET_OP2_ZVAL_PTR(BP_VAR_R);
8377 if ((OP2_TYPE & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) {
8378 key = Z_REFVAL_P(key);
8379 }
8380 ZVAL_COPY(&generator->key, key);
8381 FREE_OP2();
8382
8383 if (Z_TYPE(generator->key) == IS_LONG
8384 && Z_LVAL(generator->key) > generator->largest_used_integer_key
8385 ) {
8386 generator->largest_used_integer_key = Z_LVAL(generator->key);
8387 }
8388 } else {
8389 /* If no key was specified we use auto-increment keys */
8390 generator->largest_used_integer_key++;
8391 ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
8392 }
8393
8394 if (RETURN_VALUE_USED(opline)) {
8395 /* If the return value of yield is used set the send
8396 * target and initialize it to NULL */
8397 generator->send_target = EX_VAR(opline->result.var);
8398 ZVAL_NULL(generator->send_target);
8399 } else {
8400 generator->send_target = NULL;
8401 }
8402
8403 /* The GOTO VM uses a local opline variable. We need to set the opline
8404 * variable in execute_data so we don't resume at an old position. */
8405 SAVE_OPLINE();
8406
8407 ZEND_VM_RETURN();
8408 }
8409
8410 ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMPVAR|CV, ANY)
8411 {
8412 USE_OPLINE
8413 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8414 zval *val;
8415
8416 SAVE_OPLINE();
8417 val = GET_OP1_ZVAL_PTR(BP_VAR_R);
8418
8419 if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
8420 zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator");
8421 FREE_OP1();
8422 UNDEF_RESULT();
8423 HANDLE_EXCEPTION();
8424 }
8425
8426 ZEND_VM_C_LABEL(yield_from_try_again):
8427 if (Z_TYPE_P(val) == IS_ARRAY) {
8428 ZVAL_COPY_VALUE(&generator->values, val);
8429 if (Z_OPT_REFCOUNTED_P(val)) {
8430 Z_ADDREF_P(val);
8431 }
8432 Z_FE_POS(generator->values) = 0;
8433 FREE_OP1();
8434 } else if (OP1_TYPE != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) {
8435 zend_class_entry *ce = Z_OBJCE_P(val);
8436 if (ce == zend_ce_generator) {
8437 zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val);
8438
8439 Z_ADDREF_P(val);
8440 FREE_OP1();
8441
8442 if (UNEXPECTED(new_gen->execute_data == NULL)) {
8443 zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
8444 zval_ptr_dtor(val);
8445 UNDEF_RESULT();
8446 HANDLE_EXCEPTION();
8447 } else if (Z_ISUNDEF(new_gen->retval)) {
8448 if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
8449 zend_throw_error(NULL, "Impossible to yield from the Generator being currently run");
8450 zval_ptr_dtor(val);
8451 UNDEF_RESULT();
8452 HANDLE_EXCEPTION();
8453 } else {
8454 zend_generator_yield_from(generator, new_gen);
8455 }
8456 } else {
8457 if (RETURN_VALUE_USED(opline)) {
8458 ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval);
8459 }
8460 ZEND_VM_NEXT_OPCODE();
8461 }
8462 } else {
8463 zend_object_iterator *iter = ce->get_iterator(ce, val, 0);
8464 FREE_OP1();
8465
8466 if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) {
8467 if (!EG(exception)) {
8468 zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name));
8469 }
8470 UNDEF_RESULT();
8471 HANDLE_EXCEPTION();
8472 }
8473
8474 iter->index = 0;
8475 if (iter->funcs->rewind) {
8476 iter->funcs->rewind(iter);
8477 if (UNEXPECTED(EG(exception) != NULL)) {
8478 OBJ_RELEASE(&iter->std);
8479 UNDEF_RESULT();
8480 HANDLE_EXCEPTION();
8481 }
8482 }
8483
8484 ZVAL_OBJ(&generator->values, &iter->std);
8485 }
8486 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) {
8487 val = Z_REFVAL_P(val);
8488 ZEND_VM_C_GOTO(yield_from_try_again);
8489 } else {
8490 zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables");
8491 FREE_OP1();
8492 UNDEF_RESULT();
8493 HANDLE_EXCEPTION();
8494 }
8495
8496 /* This is the default return value
8497 * when the expression is a Generator, it will be overwritten in zend_generator_resume() */
8498 if (RETURN_VALUE_USED(opline)) {
8499 ZVAL_NULL(EX_VAR(opline->result.var));
8500 }
8501
8502 /* This generator has no send target (though the generator we delegate to might have one) */
8503 generator->send_target = NULL;
8504
8505 /* The GOTO VM uses a local opline variable. We need to set the opline
8506 * variable in execute_data so we don't resume at an old position. */
8507 SAVE_OPLINE();
8508
8509 ZEND_VM_RETURN();
8510 }
8511
8512 ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
8513 {
8514 USE_OPLINE
8515 zval *fast_call = EX_VAR(opline->op1.var);
8516 SAVE_OPLINE();
8517
8518 /* cleanup incomplete RETURN statement */
8519 if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1
8520 && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) {
8521 zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var);
8522
8523 zval_ptr_dtor(return_value);
8524 }
8525
8526 /* cleanup delayed exception */
8527 if (Z_OBJ_P(fast_call) != NULL) {
8528 /* discard the previously thrown exception */
8529 OBJ_RELEASE(Z_OBJ_P(fast_call));
8530 Z_OBJ_P(fast_call) = NULL;
8531 }
8532
8533 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8534 }
8535
8536 ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, ANY)
8537 {
8538 USE_OPLINE
8539 zval *fast_call = EX_VAR(opline->result.var);
8540
8541 Z_OBJ_P(fast_call) = NULL;
8542 /* set return address */
8543 Z_OPLINE_NUM_P(fast_call) = opline - EX(func)->op_array.opcodes;
8544 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0);
8545 }
8546
8547 ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH)
8548 {
8549 USE_OPLINE
8550 zval *fast_call = EX_VAR(opline->op1.var);
8551 uint32_t current_try_catch_offset, current_op_num;
8552
8553 if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1) {
8554 const zend_op *fast_ret = EX(func)->op_array.opcodes + Z_OPLINE_NUM_P(fast_call);
8555
8556 ZEND_VM_JMP_EX(fast_ret + 1, 0);
8557 }
8558
8559 /* special case for unhandled exceptions */
8560 EG(exception) = Z_OBJ_P(fast_call);
8561 Z_OBJ_P(fast_call) = NULL;
8562 current_try_catch_offset = opline->op2.num;
8563 current_op_num = opline - EX(func)->op_array.opcodes;
8564 ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, current_try_catch_offset, op_num, current_op_num);
8565 }
8566
8567 ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT)
8568 {
8569 USE_OPLINE
8570 zend_string *varname;
8571 zval *value;
8572 zval *variable_ptr;
8573 uintptr_t idx;
8574 zend_reference *ref;
8575
8576 ZEND_VM_REPEATABLE_OPCODE
8577
8578 varname = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
8579
8580 /* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
8581 idx = (uintptr_t)CACHED_PTR(opline->extended_value) - 1;
8582 if (EXPECTED(idx < EG(symbol_table).nNumUsed * sizeof(Bucket))) {
8583 Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx);
8584
8585 if (EXPECTED(p->key == varname) ||
8586 (EXPECTED(p->h == ZSTR_H(varname)) &&
8587 EXPECTED(p->key != NULL) &&
8588 EXPECTED(zend_string_equal_content(p->key, varname)))) {
8589
8590 value = (zval*)p; /* value = &p->val; */
8591 ZEND_VM_C_GOTO(check_indirect);
8592 }
8593 }
8594
8595 value = zend_hash_find_known_hash(&EG(symbol_table), varname);
8596 if (UNEXPECTED(value == NULL)) {
8597 value = zend_hash_add_new(&EG(symbol_table), varname, &EG(uninitialized_zval));
8598 idx = (char*)value - (char*)EG(symbol_table).arData;
8599 /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
8600 CACHE_PTR(opline->extended_value, (void*)(idx + 1));
8601 } else {
8602 idx = (char*)value - (char*)EG(symbol_table).arData;
8603 /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
8604 CACHE_PTR(opline->extended_value, (void*)(idx + 1));
8605 ZEND_VM_C_LABEL(check_indirect):
8606 /* GLOBAL variable may be an INDIRECT pointer to CV */
8607 if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
8608 value = Z_INDIRECT_P(value);
8609 if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
8610 ZVAL_NULL(value);
8611 }
8612 }
8613 }
8614
8615 if (UNEXPECTED(!Z_ISREF_P(value))) {
8616 ZVAL_MAKE_REF_EX(value, 2);
8617 ref = Z_REF_P(value);
8618 } else {
8619 ref = Z_REF_P(value);
8620 GC_ADDREF(ref);
8621 }
8622
8623 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
8624
8625 if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
8626 zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
8627
8628 ZVAL_REF(variable_ptr, ref);
8629 SAVE_OPLINE();
8630 if (GC_DELREF(garbage) == 0) {
8631 rc_dtor_func(garbage);
8632 if (UNEXPECTED(EG(exception))) {
8633 ZVAL_NULL(variable_ptr);
8634 HANDLE_EXCEPTION();
8635 }
8636 } else {
8637 gc_check_possible_root(garbage);
8638 }
8639 } else {
8640 ZVAL_REF(variable_ptr, ref);
8641 }
8642
8643 ZEND_VM_REPEAT_OPCODE(ZEND_BIND_GLOBAL);
8644 ZEND_VM_NEXT_OPCODE();
8645 }
8646
8647 ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
8648 {
8649 USE_OPLINE
8650 zval *value;
8651
8652 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
8653 if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
8654 ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
8655 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
8656 zval_ptr_dtor_str(value);
8657 }
8658 ZEND_VM_NEXT_OPCODE();
8659 } else {
8660 bool strict;
8661
8662 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
8663 value = Z_REFVAL_P(value);
8664 if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
8665 ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
8666 FREE_OP1();
8667 ZEND_VM_NEXT_OPCODE();
8668 }
8669 }
8670
8671 SAVE_OPLINE();
8672 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
8673 value = ZVAL_UNDEFINED_OP1();
8674 }
8675 strict = EX_USES_STRICT_TYPES();
8676 do {
8677 if (EXPECTED(!strict)) {
8678 zend_string *str;
8679 zval tmp;
8680
8681 if (UNEXPECTED(Z_TYPE_P(value) == IS_NULL)) {
8682 zend_error(E_DEPRECATED,
8683 "strlen(): Passing null to parameter #1 ($string) of type string is deprecated");
8684 ZVAL_LONG(EX_VAR(opline->result.var), 0);
8685 if (UNEXPECTED(EG(exception))) {
8686 HANDLE_EXCEPTION();
8687 }
8688 break;
8689 }
8690
8691 ZVAL_COPY(&tmp, value);
8692 if (zend_parse_arg_str_weak(&tmp, &str, 1)) {
8693 ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str));
8694 zval_ptr_dtor(&tmp);
8695 break;
8696 }
8697 zval_ptr_dtor(&tmp);
8698 }
8699 if (!EG(exception)) {
8700 zend_type_error("strlen(): Argument #1 ($string) must be of type string, %s given", zend_zval_value_name(value));
8701 }
8702 ZVAL_UNDEF(EX_VAR(opline->result.var));
8703 } while (0);
8704 }
8705 FREE_OP1();
8706 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8707 }
8708
8709 ZEND_VM_HOT_NOCONST_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMPVAR|CV, ANY, TYPE_MASK)
8710 {
8711 USE_OPLINE
8712 zval *value;
8713 int result = 0;
8714
8715 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
8716 if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
8717 ZEND_VM_C_LABEL(type_check_resource):
8718 if (opline->extended_value != MAY_BE_RESOURCE
8719 || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) {
8720 result = 1;
8721 }
8722 } else if ((OP1_TYPE & (IS_CV|IS_VAR)) && Z_ISREF_P(value)) {
8723 value = Z_REFVAL_P(value);
8724 if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
8725 ZEND_VM_C_GOTO(type_check_resource);
8726 }
8727 } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
8728 result = ((1 << IS_NULL) & opline->extended_value) != 0;
8729 SAVE_OPLINE();
8730 ZVAL_UNDEFINED_OP1();
8731 if (UNEXPECTED(EG(exception))) {
8732 ZVAL_UNDEF(EX_VAR(opline->result.var));
8733 HANDLE_EXCEPTION();
8734 }
8735 }
8736 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
8737 SAVE_OPLINE();
8738 FREE_OP1();
8739 ZEND_VM_SMART_BRANCH(result, 1);
8740 } else {
8741 ZEND_VM_SMART_BRANCH(result, 0);
8742 }
8743 }
8744
8745 ZEND_VM_HOT_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT)
8746 {
8747 USE_OPLINE
8748 zend_constant *c;
8749
8750 c = CACHED_PTR(opline->extended_value);
8751 if (EXPECTED(c != NULL)) {
8752 if (!IS_SPECIAL_CACHE_VAL(c)) {
8753 ZEND_VM_C_LABEL(defined_true):
8754 ZEND_VM_SMART_BRANCH_TRUE();
8755 } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) {
8756 ZEND_VM_C_LABEL(defined_false):
8757 ZEND_VM_SMART_BRANCH_FALSE();
8758 }
8759 }
8760 if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
8761 CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants))));
8762 ZEND_VM_C_GOTO(defined_false);
8763 } else {
8764 ZEND_VM_C_GOTO(defined_true);
8765 }
8766 }
8767
8768 ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
8769 {
8770 USE_OPLINE
8771
8772 if (EG(assertions) <= 0) {
8773 zend_op *target = OP_JMP_ADDR(opline, opline->op2);
8774 if (RETURN_VALUE_USED(opline)) {
8775 ZVAL_TRUE(EX_VAR(opline->result.var));
8776 }
8777 ZEND_VM_JMP_EX(target, 0);
8778 } else {
8779 ZEND_VM_NEXT_OPCODE();
8780 }
8781 }
8782
8783 ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, CV|TMPVAR|UNUSED|CLASS_FETCH, ANY)
8784 {
8785 uint32_t fetch_type;
8786 zend_class_entry *called_scope, *scope;
8787 USE_OPLINE
8788
8789 if (OP1_TYPE != IS_UNUSED) {
8790 SAVE_OPLINE();
8791 zval *op = GET_OP1_ZVAL_PTR(BP_VAR_R);
8792 if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) {
8793 ZVAL_DEREF(op);
8794 if (Z_TYPE_P(op) != IS_OBJECT) {
8795 zend_type_error("Cannot use \"::class\" on %s", zend_zval_value_name(op));
8796 ZVAL_UNDEF(EX_VAR(opline->result.var));
8797 FREE_OP1();
8798 HANDLE_EXCEPTION();
8799 }
8800 }
8801
8802 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name);
8803 FREE_OP1();
8804 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8805 }
8806
8807 fetch_type = opline->op1.num;
8808 scope = EX(func)->op_array.scope;
8809 if (UNEXPECTED(scope == NULL)) {
8810 SAVE_OPLINE();
8811 zend_throw_error(NULL, "Cannot use \"%s\" in the global scope",
8812 fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
8813 fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
8814 ZVAL_UNDEF(EX_VAR(opline->result.var));
8815 HANDLE_EXCEPTION();
8816 }
8817
8818 switch (fetch_type) {
8819 case ZEND_FETCH_CLASS_SELF:
8820 ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name);
8821 break;
8822 case ZEND_FETCH_CLASS_PARENT:
8823 if (UNEXPECTED(scope->parent == NULL)) {
8824 SAVE_OPLINE();
8825 zend_throw_error(NULL,
8826 "Cannot use \"parent\" when current class scope has no parent");
8827 ZVAL_UNDEF(EX_VAR(opline->result.var));
8828 HANDLE_EXCEPTION();
8829 }
8830 ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name);
8831 break;
8832 case ZEND_FETCH_CLASS_STATIC:
8833 if (Z_TYPE(EX(This)) == IS_OBJECT) {
8834 called_scope = Z_OBJCE(EX(This));
8835 } else {
8836 called_scope = Z_CE(EX(This));
8837 }
8838 ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name);
8839 break;
8840 EMPTY_SWITCH_DEFAULT_CASE()
8841 }
8842 ZEND_VM_NEXT_OPCODE();
8843 }
8844
8845 ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
8846 {
8847 zend_array *args = NULL;
8848 zend_function *fbc = EX(func);
8849 zval *ret = EX(return_value);
8850 uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS);
8851 uint32_t num_args = EX_NUM_ARGS();
8852 zend_execute_data *call;
8853
8854 SAVE_OPLINE();
8855
8856 if (num_args) {
8857 zval *p = ZEND_CALL_ARG(execute_data, 1);
8858 zval *end = p + num_args;
8859
8860 args = zend_new_array(num_args);
8861 zend_hash_real_init_packed(args);
ZEND_HASH_FILL_PACKED(args)8862 ZEND_HASH_FILL_PACKED(args) {
8863 do {
8864 ZEND_HASH_FILL_ADD(p);
8865 p++;
8866 } while (p != end);
8867 } ZEND_HASH_FILL_END();
8868 }
8869
8870 call = execute_data;
8871 execute_data = EG(current_execute_data) = EX(prev_execute_data);
8872
8873 call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call;
8874 ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call));
8875 ZEND_CALL_NUM_ARGS(call) = 2;
8876
8877 ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name);
8878
8879 zval *call_args = ZEND_CALL_ARG(call, 2);
8880 if (args) {
8881 ZVAL_ARR(call_args, args);
8882 } else {
8883 ZVAL_EMPTY_ARRAY(call_args);
8884 }
8885 if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
8886 if (zend_hash_num_elements(Z_ARRVAL_P(call_args)) == 0) {
8887 GC_ADDREF(call->extra_named_params);
8888 ZVAL_ARR(call_args, call->extra_named_params);
8889 } else {
8890 SEPARATE_ARRAY(call_args);
8891 zend_hash_copy(Z_ARRVAL_P(call_args), call->extra_named_params, zval_add_ref);
8892 }
8893 }
8894 zend_free_trampoline(fbc);
8895 fbc = call->func;
8896
8897 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
8898 if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
8899 init_func_run_time_cache(&fbc->op_array);
8900 }
8901 execute_data = call;
8902 i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
8903 if (EXPECTED(zend_execute_ex == execute_ex)) {
8904 LOAD_OPLINE_EX();
8905 ZEND_OBSERVER_SAVE_OPLINE();
8906 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
8907 ZEND_VM_ENTER_EX();
8908 } else {
8909 SAVE_OPLINE_EX();
8910 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
8911 execute_data = EX(prev_execute_data);
8912 if (execute_data) {
8913 LOAD_OPLINE();
8914 }
8915 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
8916 zend_execute_ex(call);
8917 }
8918 } else {
8919 zval retval;
8920
8921 ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
8922
8923 EG(current_execute_data) = call;
8924
8925 #if ZEND_DEBUG
8926 bool should_throw = zend_internal_call_should_throw(fbc, call);
8927 #endif
8928
8929 if (ret == NULL) {
8930 ret = &retval;
8931 }
8932
8933 ZVAL_NULL(ret);
8934 ZEND_OBSERVER_FCALL_BEGIN(call);
8935 if (!zend_execute_internal) {
8936 /* saves one function call if zend_execute_internal is not used */
8937 fbc->internal_function.handler(call, ret);
8938 } else {
8939 zend_execute_internal(call, ret);
8940 }
8941
8942 #if ZEND_DEBUG
8943 if (!EG(exception) && call->func) {
8944 if (should_throw) {
8945 zend_internal_call_arginfo_violation(call->func);
8946 }
8947 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
8948 zend_verify_internal_return_type(call->func, ret));
8949 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
8950 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
8951 zend_verify_internal_func_info(call->func, ret);
8952 }
8953 #endif
8954 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
8955
8956 EG(current_execute_data) = call->prev_execute_data;
8957
8958 zend_vm_stack_free_args(call);
8959 if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
8960 zend_free_extra_named_params(call->extra_named_params);
8961 }
8962 if (ret == &retval) {
8963 zval_ptr_dtor(ret);
8964 }
8965 }
8966
8967 execute_data = EG(current_execute_data);
8968
8969 if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
8970 ZEND_VM_RETURN();
8971 }
8972
8973 if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
8974 zend_object *object = Z_OBJ(call->This);
8975 OBJ_RELEASE(object);
8976 }
8977 zend_vm_stack_free_call_frame(call);
8978
8979 if (UNEXPECTED(EG(exception) != NULL)) {
8980 zend_rethrow_exception(execute_data);
8981 HANDLE_EXCEPTION_LEAVE();
8982 }
8983
8984 LOAD_OPLINE();
8985 ZEND_VM_INC_OPCODE();
8986 ZEND_VM_LEAVE();
8987 }
8988
8989 ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF)
8990 {
8991 USE_OPLINE
8992 zval *closure, *var;
8993
8994 closure = GET_OP1_ZVAL_PTR(BP_VAR_R);
8995 if (opline->extended_value & ZEND_BIND_REF) {
8996 /* By-ref binding */
8997 var = GET_OP2_ZVAL_PTR(BP_VAR_W);
8998 if (Z_ISREF_P(var)) {
8999 Z_ADDREF_P(var);
9000 } else {
9001 ZVAL_MAKE_REF_EX(var, 2);
9002 }
9003 } else {
9004 var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9005 if (UNEXPECTED(Z_ISUNDEF_P(var)) && !(opline->extended_value & ZEND_BIND_IMPLICIT)) {
9006 SAVE_OPLINE();
9007 var = ZVAL_UNDEFINED_OP2();
9008 if (UNEXPECTED(EG(exception))) {
9009 HANDLE_EXCEPTION();
9010 }
9011 }
9012 ZVAL_DEREF(var);
9013 Z_TRY_ADDREF_P(var);
9014 }
9015
9016 zend_closure_bind_var_ex(closure,
9017 (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var);
9018 ZEND_VM_NEXT_OPCODE();
9019 }
9020
9021 ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, ANY, REF)
9022 {
9023 USE_OPLINE
9024 HashTable *ht;
9025 zval *value;
9026 zval *variable_ptr;
9027
9028 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
9029
9030 SAVE_OPLINE();
9031
9032 ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
9033 if (!ht) {
9034 ht = zend_array_dup(EX(func)->op_array.static_variables);
9035 ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
9036 }
9037 ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
9038
9039 value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT)));
9040
9041 if (opline->extended_value & ZEND_BIND_REF) {
9042 i_zval_ptr_dtor(variable_ptr);
9043 if (UNEXPECTED(!Z_ISREF_P(value))) {
9044 zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference));
9045 GC_SET_REFCOUNT(ref, 2);
9046 GC_TYPE_INFO(ref) = GC_REFERENCE;
9047 if (OP2_TYPE == IS_UNUSED) {
9048 ZVAL_COPY_VALUE(&ref->val, value);
9049 } else {
9050 ZEND_ASSERT(!Z_REFCOUNTED_P(value));
9051 ZVAL_COPY(&ref->val, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R));
9052 FREE_OP2();
9053 }
9054 ref->sources.ptr = NULL;
9055 Z_REF_P(value) = ref;
9056 Z_TYPE_INFO_P(value) = IS_REFERENCE_EX;
9057 ZVAL_REF(variable_ptr, ref);
9058 } else {
9059 Z_ADDREF_P(value);
9060 ZVAL_REF(variable_ptr, Z_REF_P(value));
9061 if (OP2_TYPE != IS_UNUSED) {
9062 FREE_OP2();
9063 }
9064 }
9065 } else {
9066 i_zval_ptr_dtor(variable_ptr);
9067 ZVAL_COPY(variable_ptr, value);
9068 }
9069
9070 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9071 }
9072
9073 ZEND_VM_HANDLER(203, ZEND_BIND_INIT_STATIC_OR_JMP, CV, JMP_ADDR)
9074 {
9075 USE_OPLINE
9076 HashTable *ht;
9077 zval *value;
9078 zval *variable_ptr;
9079
9080 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
9081
9082 ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
9083 if (!ht) {
9084 ZEND_VM_NEXT_OPCODE();
9085 }
9086 ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
9087
9088 value = (zval*)((char*)ht->arData + opline->extended_value);
9089 if (Z_TYPE_P(value) == IS_NULL) {
9090 ZEND_VM_NEXT_OPCODE();
9091 } else {
9092 SAVE_OPLINE();
9093 zval_ptr_dtor(variable_ptr);
9094 ZEND_ASSERT(Z_TYPE_P(value) == IS_REFERENCE);
9095 Z_ADDREF_P(value);
9096 ZVAL_REF(variable_ptr, Z_REF_P(value));
9097 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 1);
9098 }
9099 }
9100
9101 ZEND_VM_HOT_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED)
9102 {
9103 USE_OPLINE
9104
9105 if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
9106 zval *result = EX_VAR(opline->result.var);
9107
9108 ZVAL_OBJ(result, Z_OBJ(EX(This)));
9109 Z_ADDREF_P(result);
9110 ZEND_VM_NEXT_OPCODE();
9111 } else {
9112 ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
9113 }
9114 }
9115
9116 ZEND_VM_HANDLER(200, ZEND_FETCH_GLOBALS, UNUSED, UNUSED)
9117 {
9118 USE_OPLINE
9119
9120 /* For symbol tables we need to deal with exactly the same problems as for property tables. */
9121 ZVAL_ARR(EX_VAR(opline->result.var),
9122 zend_proptable_to_symtable(&EG(symbol_table), /* always_duplicate */ 1));
9123 ZEND_VM_NEXT_OPCODE();
9124 }
9125
9126 ZEND_VM_HANDLER(186, ZEND_ISSET_ISEMPTY_THIS, UNUSED, UNUSED)
9127 {
9128 USE_OPLINE
9129
9130 ZVAL_BOOL(EX_VAR(opline->result.var),
9131 (opline->extended_value & ZEND_ISEMPTY) ^
9132 (Z_TYPE(EX(This)) == IS_OBJECT));
9133 ZEND_VM_NEXT_OPCODE();
9134 }
9135
9136 ZEND_VM_HANDLER(49, ZEND_CHECK_VAR, CV, UNUSED)
9137 {
9138 USE_OPLINE
9139 zval *op1 = EX_VAR(opline->op1.var);
9140
9141 if (UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
9142 SAVE_OPLINE();
9143 ZVAL_UNDEFINED_OP1();
9144 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9145 }
9146 ZEND_VM_NEXT_OPCODE();
9147 }
9148
9149 ZEND_VM_HANDLER(140, ZEND_MAKE_REF, VAR|CV, UNUSED)
9150 {
9151 USE_OPLINE
9152 zval *op1 = EX_VAR(opline->op1.var);
9153
9154 if (OP1_TYPE == IS_CV) {
9155 if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9156 ZVAL_NEW_EMPTY_REF(op1);
9157 Z_SET_REFCOUNT_P(op1, 2);
9158 ZVAL_NULL(Z_REFVAL_P(op1));
9159 ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1));
9160 } else {
9161 if (Z_ISREF_P(op1)) {
9162 Z_ADDREF_P(op1);
9163 } else {
9164 ZVAL_MAKE_REF_EX(op1, 2);
9165 }
9166 ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1));
9167 }
9168 } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) {
9169 op1 = Z_INDIRECT_P(op1);
9170 if (EXPECTED(!Z_ISREF_P(op1))) {
9171 ZVAL_MAKE_REF_EX(op1, 2);
9172 } else {
9173 GC_ADDREF(Z_REF_P(op1));
9174 }
9175 ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1));
9176 } else {
9177 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1);
9178 }
9179 ZEND_VM_NEXT_OPCODE();
9180 }
9181
9182 ZEND_VM_COLD_CONSTCONST_HANDLER(187, ZEND_SWITCH_LONG, CONST|TMPVARCV, CONST, JMP_ADDR)
9183 {
9184 USE_OPLINE
9185 zval *op, *jump_zv;
9186 HashTable *jumptable;
9187
9188 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9189
9190 if (Z_TYPE_P(op) != IS_LONG) {
9191 ZVAL_DEREF(op);
9192 if (Z_TYPE_P(op) != IS_LONG) {
9193 /* Wrong type, fall back to ZEND_CASE chain */
9194 ZEND_VM_NEXT_OPCODE();
9195 }
9196 }
9197
9198 jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
9199 jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
9200 if (jump_zv != NULL) {
9201 ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
9202 ZEND_VM_CONTINUE();
9203 } else {
9204 /* default */
9205 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
9206 ZEND_VM_CONTINUE();
9207 }
9208 }
9209
9210 ZEND_VM_COLD_CONSTCONST_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVARCV, CONST, JMP_ADDR)
9211 {
9212 USE_OPLINE
9213 zval *op, *jump_zv;
9214 HashTable *jumptable;
9215
9216 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9217
9218 if (Z_TYPE_P(op) != IS_STRING) {
9219 if (OP1_TYPE == IS_CONST) {
9220 /* Wrong type, fall back to ZEND_CASE chain */
9221 ZEND_VM_NEXT_OPCODE();
9222 } else {
9223 ZVAL_DEREF(op);
9224 if (Z_TYPE_P(op) != IS_STRING) {
9225 /* Wrong type, fall back to ZEND_CASE chain */
9226 ZEND_VM_NEXT_OPCODE();
9227 }
9228 }
9229 }
9230
9231 jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
9232 jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), OP1_TYPE == IS_CONST);
9233 if (jump_zv != NULL) {
9234 ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
9235 ZEND_VM_CONTINUE();
9236 } else {
9237 /* default */
9238 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
9239 ZEND_VM_CONTINUE();
9240 }
9241 }
9242
9243 ZEND_VM_COLD_CONSTCONST_HANDLER(195, ZEND_MATCH, CONST|TMPVARCV, CONST, JMP_ADDR)
9244 {
9245 USE_OPLINE
9246 zval *op, *jump_zv;
9247 HashTable *jumptable;
9248
9249 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9250 jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
9251
9252 ZEND_VM_C_LABEL(match_try_again):
9253 if (Z_TYPE_P(op) == IS_LONG) {
9254 jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
9255 } else if (Z_TYPE_P(op) == IS_STRING) {
9256 jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), OP1_TYPE == IS_CONST);
9257 } else if (Z_TYPE_P(op) == IS_REFERENCE) {
9258 op = Z_REFVAL_P(op);
9259 ZEND_VM_C_GOTO(match_try_again);
9260 } else {
9261 if (UNEXPECTED((OP1_TYPE & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) {
9262 SAVE_OPLINE();
9263 op = ZVAL_UNDEFINED_OP1();
9264 if (UNEXPECTED(EG(exception))) {
9265 HANDLE_EXCEPTION();
9266 }
9267 ZEND_VM_C_GOTO(match_try_again);
9268 }
9269
9270 ZEND_VM_C_GOTO(default_branch);
9271 }
9272
9273 if (jump_zv != NULL) {
9274 ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
9275 ZEND_VM_CONTINUE();
9276 } else {
9277 ZEND_VM_C_LABEL(default_branch):
9278 /* default */
9279 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
9280 ZEND_VM_CONTINUE();
9281 }
9282 }
9283
9284 ZEND_VM_COLD_CONST_HANDLER(197, ZEND_MATCH_ERROR, CONST|TMPVARCV, UNUSED)
9285 {
9286 USE_OPLINE
9287 zval *op;
9288
9289 SAVE_OPLINE();
9290 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9291 zend_match_unhandled_error(op);
9292 HANDLE_EXCEPTION();
9293 }
9294
9295 ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM)
9296 {
9297 USE_OPLINE
9298 zval *op1;
9299 HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
9300 zval *result;
9301
9302 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9303 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
9304 result = zend_hash_find_ex(ht, Z_STR_P(op1), OP1_TYPE == IS_CONST);
9305 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
9306 zval_ptr_dtor_str(op1);
9307 }
9308 ZEND_VM_SMART_BRANCH(result, 0);
9309 }
9310
9311 if (opline->extended_value) {
9312 if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
9313 result = zend_hash_index_find(ht, Z_LVAL_P(op1));
9314 ZEND_VM_SMART_BRANCH(result, 0);
9315 }
9316 SAVE_OPLINE();
9317 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) {
9318 op1 = Z_REFVAL_P(op1);
9319 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
9320 result = zend_hash_find(ht, Z_STR_P(op1));
9321 FREE_OP1();
9322 ZEND_VM_SMART_BRANCH(result, 0);
9323 } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
9324 result = zend_hash_index_find(ht, Z_LVAL_P(op1));
9325 FREE_OP1();
9326 ZEND_VM_SMART_BRANCH(result, 0);
9327 }
9328 } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9329 ZVAL_UNDEFINED_OP1();
9330 }
9331 } else if (Z_TYPE_P(op1) <= IS_FALSE) {
9332 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9333 SAVE_OPLINE();
9334 ZVAL_UNDEFINED_OP1();
9335 if (UNEXPECTED(EG(exception) != NULL)) {
9336 HANDLE_EXCEPTION();
9337 }
9338 }
9339 result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC());
9340 ZEND_VM_SMART_BRANCH(result, 0);
9341 } else {
9342 zend_string *key;
9343 zval key_tmp;
9344
9345 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) {
9346 op1 = Z_REFVAL_P(op1);
9347 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
9348 result = zend_hash_find(ht, Z_STR_P(op1));
9349 FREE_OP1();
9350 ZEND_VM_SMART_BRANCH(result, 0);
9351 }
9352 }
9353
9354 SAVE_OPLINE();
ZEND_HASH_MAP_FOREACH_STR_KEY(ht,key)9355 ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) {
9356 ZVAL_STR(&key_tmp, key);
9357 if (zend_compare(op1, &key_tmp) == 0) {
9358 FREE_OP1();
9359 ZEND_VM_SMART_BRANCH(1, 1);
9360 }
9361 } ZEND_HASH_FOREACH_END();
9362 }
9363 FREE_OP1();
9364 ZEND_VM_SMART_BRANCH(0, 1);
9365 }
9366
9367 ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
9368 {
9369 USE_OPLINE
9370 zval *op1;
9371 zend_long count;
9372
9373 SAVE_OPLINE();
9374 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9375
9376 while (1) {
9377 if (Z_TYPE_P(op1) == IS_ARRAY) {
9378 count = zend_hash_num_elements(Z_ARRVAL_P(op1));
9379 break;
9380 } else if (Z_TYPE_P(op1) == IS_OBJECT) {
9381 zend_object *zobj = Z_OBJ_P(op1);
9382
9383 /* first, we check if the handler is defined */
9384 if (zobj->handlers->count_elements) {
9385 if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) {
9386 break;
9387 }
9388 if (UNEXPECTED(EG(exception))) {
9389 count = 0;
9390 break;
9391 }
9392 }
9393
9394 /* if not and the object implements Countable we call its count() method */
9395 if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) {
9396 zval retval;
9397
9398 zend_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT));
9399 zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval);
9400 count = zval_get_long(&retval);
9401 zval_ptr_dtor(&retval);
9402 break;
9403 }
9404
9405 /* If There's no handler and it doesn't implement Countable then emit a TypeError */
9406 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
9407 op1 = Z_REFVAL_P(op1);
9408 continue;
9409 } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9410 ZVAL_UNDEFINED_OP1();
9411 }
9412 count = 0;
9413 zend_type_error("%s(): Argument #1 ($value) must be of type Countable|array, %s given", opline->extended_value ? "sizeof" : "count", zend_zval_value_name(op1));
9414 break;
9415 }
9416
9417 ZVAL_LONG(EX_VAR(opline->result.var), count);
9418 FREE_OP1();
9419 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9420 }
9421
9422 ZEND_VM_TYPE_SPEC_HANDLER(ZEND_COUNT, (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_ARRAY, ZEND_COUNT_ARRAY, CV|TMPVAR, UNUSED)
9423 {
9424 USE_OPLINE
9425 zend_array *ht = Z_ARRVAL_P(GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R));
9426 ZVAL_LONG(EX_VAR(opline->result.var), zend_hash_num_elements(ht));
9427 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR) && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
9428 SAVE_OPLINE();
9429 zend_array_destroy(ht);
9430 if (EG(exception)) {
9431 HANDLE_EXCEPTION();
9432 }
9433 }
9434 ZEND_VM_NEXT_OPCODE();
9435 }
9436
9437 ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMPVAR|CV, UNUSED)
9438 {
9439 USE_OPLINE
9440
9441 if (OP1_TYPE == IS_UNUSED) {
9442 SAVE_OPLINE();
9443 if (UNEXPECTED(!EX(func)->common.scope)) {
9444 zend_throw_error(NULL, "get_class() without arguments must be called from within a class");
9445 ZVAL_UNDEF(EX_VAR(opline->result.var));
9446 HANDLE_EXCEPTION();
9447 } else {
9448 zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated");
9449 ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
9450 if (UNEXPECTED(EG(exception))) {
9451 HANDLE_EXCEPTION();
9452 }
9453 ZEND_VM_NEXT_OPCODE();
9454 }
9455 } else {
9456 zval *op1;
9457
9458 SAVE_OPLINE();
9459 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9460 while (1) {
9461 if (Z_TYPE_P(op1) == IS_OBJECT) {
9462 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
9463 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
9464 op1 = Z_REFVAL_P(op1);
9465 continue;
9466 } else {
9467 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9468 ZVAL_UNDEFINED_OP1();
9469 }
9470 zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(op1));
9471 ZVAL_UNDEF(EX_VAR(opline->result.var));
9472 }
9473 break;
9474 }
9475 FREE_OP1();
9476 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9477 }
9478 }
9479
9480 ZEND_VM_HANDLER(192, ZEND_GET_CALLED_CLASS, UNUSED, UNUSED)
9481 {
9482 USE_OPLINE
9483
9484 if (Z_TYPE(EX(This)) == IS_OBJECT) {
9485 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE(EX(This))->name);
9486 } else if (Z_CE(EX(This))) {
9487 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name);
9488 } else {
9489 ZEND_ASSERT(!EX(func)->common.scope);
9490 SAVE_OPLINE();
9491 zend_throw_error(NULL, "get_called_class() must be called from within a class");
9492 ZVAL_UNDEF(EX_VAR(opline->result.var));
9493 HANDLE_EXCEPTION();
9494 }
9495 ZEND_VM_NEXT_OPCODE();
9496 }
9497
9498 ZEND_VM_COLD_CONST_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
9499 {
9500 USE_OPLINE
9501 zval *op1;
9502 zend_string *type;
9503
9504 SAVE_OPLINE();
9505 op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9506 type = zend_zval_get_legacy_type(op1);
9507 if (EXPECTED(type)) {
9508 ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
9509 } else {
9510 ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
9511 }
9512 FREE_OP1();
9513 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9514 }
9515
9516 ZEND_VM_HANDLER(171, ZEND_FUNC_NUM_ARGS, UNUSED, UNUSED)
9517 {
9518 USE_OPLINE
9519
9520 ZVAL_LONG(EX_VAR(opline->result.var), EX_NUM_ARGS());
9521 ZEND_VM_NEXT_OPCODE();
9522 }
9523
9524 ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
9525 {
9526 USE_OPLINE
9527 zend_array *ht;
9528 uint32_t arg_count, result_size, skip;
9529
9530 arg_count = EX_NUM_ARGS();
9531 if (OP1_TYPE == IS_CONST) {
9532 skip = Z_LVAL_P(RT_CONSTANT(opline, opline->op1));
9533 if (arg_count < skip) {
9534 result_size = 0;
9535 } else {
9536 result_size = arg_count - skip;
9537 }
9538 } else {
9539 skip = 0;
9540 result_size = arg_count;
9541 }
9542
9543 if (result_size) {
9544 SAVE_OPLINE();
9545 uint32_t first_extra_arg = EX(func)->op_array.num_args;
9546
9547 ht = zend_new_array(result_size);
9548 ZVAL_ARR(EX_VAR(opline->result.var), ht);
9549 zend_hash_real_init_packed(ht);
ZEND_HASH_FILL_PACKED(ht)9550 ZEND_HASH_FILL_PACKED(ht) {
9551 zval *p, *q;
9552 uint32_t i = skip;
9553 p = EX_VAR_NUM(i);
9554 if (arg_count > first_extra_arg) {
9555 while (i < first_extra_arg) {
9556 q = p;
9557 if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
9558 ZVAL_DEREF(q);
9559 if (Z_OPT_REFCOUNTED_P(q)) {
9560 Z_ADDREF_P(q);
9561 }
9562 ZEND_HASH_FILL_SET(q);
9563 } else {
9564 ZEND_HASH_FILL_SET_NULL();
9565 }
9566 ZEND_HASH_FILL_NEXT();
9567 p++;
9568 i++;
9569 }
9570 if (skip < first_extra_arg) {
9571 skip = 0;
9572 } else {
9573 skip -= first_extra_arg;
9574 }
9575 p = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T + skip);
9576 }
9577 while (i < arg_count) {
9578 q = p;
9579 if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
9580 ZVAL_DEREF(q);
9581 if (Z_OPT_REFCOUNTED_P(q)) {
9582 Z_ADDREF_P(q);
9583 }
9584 ZEND_HASH_FILL_SET(q);
9585 } else {
9586 ZEND_HASH_FILL_SET_NULL();
9587 }
9588 ZEND_HASH_FILL_NEXT();
9589 p++;
9590 i++;
9591 }
9592 } ZEND_HASH_FILL_END();
9593 ht->nNumOfElements = result_size;
9594 } else {
9595 ZVAL_EMPTY_ARRAY(EX_VAR(opline->result.var));
9596 }
9597 ZEND_VM_NEXT_OPCODE();
9598 }
9599
9600 /* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */
9601 ZEND_VM_HANDLER(167, ZEND_COPY_TMP, TMPVAR, UNUSED)
9602 {
9603 USE_OPLINE
9604 zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
9605 zval *result = EX_VAR(opline->result.var);
9606 ZVAL_COPY(result, value);
9607 ZEND_VM_NEXT_OPCODE();
9608 }
9609
9610 ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED)
9611 {
9612 USE_OPLINE
9613 zend_execute_data *call = EX(call);
9614
9615 zend_closure_from_frame(EX_VAR(opline->result.var), call);
9616
9617 if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
9618 OBJ_RELEASE(Z_OBJ(call->This));
9619 }
9620
9621 EX(call) = call->prev_execute_data;
9622
9623 zend_vm_stack_free_call_frame(call);
9624
9625 ZEND_VM_NEXT_OPCODE();
9626 }
9627
9628 ZEND_VM_HANDLER(208, ZEND_JMP_FRAMELESS, CONST, JMP_ADDR, NUM|CACHE_SLOT)
9629 {
9630 USE_OPLINE
9631 zend_jmp_fl_result result = (uintptr_t)CACHED_PTR(opline->extended_value);
9632 ZEND_VM_C_LABEL(try_again):
9633 if (EXPECTED(result == ZEND_JMP_FL_HIT)) {
9634 OPLINE = OP_JMP_ADDR(opline, opline->op2);
9635 ZEND_VM_CONTINUE();
9636 } else if (EXPECTED(result == ZEND_JMP_FL_MISS)) {
9637 ZEND_VM_NEXT_OPCODE();
9638 } else {
9639 ZEND_ASSERT(result == ZEND_JMP_FL_UNPRIMED);
9640 /* func_name refers to the function in the local namespace, e.g. foo\substr. */
9641 zval *func_name = (zval *)RT_CONSTANT(opline, opline->op1);
9642 /* If it cannot be found locally, we must be referring to the global function. */
9643 zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name));
9644 /* ZEND_JMP_FL_MISS = 1, ZEND_JMP_FL_HIT = 2 */
9645 result = (func == NULL) + 1;
9646 CACHE_PTR(opline->extended_value, (void *)result);
9647 ZEND_VM_C_GOTO(try_again);
9648 }
9649 }
9650
9651 ZEND_VM_HANDLER(204, ZEND_FRAMELESS_ICALL_0, UNUSED, UNUSED, SPEC(OBSERVER))
9652 {
9653 USE_OPLINE
9654 SAVE_OPLINE();
9655
9656 zval *result = EX_VAR(opline->result.var);
9657 ZVAL_NULL(result);
9658
9659 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9660 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9661 zend_frameless_observed_call(execute_data);
9662 } else
9663 #endif
9664 {
9665 zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline);
9666 function(EX_VAR(opline->result.var));
9667 }
9668 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9669 }
9670
9671 ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
9672 {
9673 USE_OPLINE
9674 SAVE_OPLINE();
9675
9676 zval *result = EX_VAR(opline->result.var);
9677 ZVAL_NULL(result);
9678 zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9679 if (EG(exception)) {
9680 FREE_OP1();
9681 HANDLE_EXCEPTION();
9682 }
9683
9684 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9685 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9686 zend_frameless_observed_call(execute_data);
9687 } else
9688 #endif
9689 {
9690 zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline);
9691 function(result, arg1);
9692 }
9693 FREE_OP1();
9694 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9695 }
9696
9697 ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
9698 {
9699 USE_OPLINE
9700 SAVE_OPLINE();
9701
9702 zval *result = EX_VAR(opline->result.var);
9703 ZVAL_NULL(result);
9704 zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9705 zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
9706 if (EG(exception)) {
9707 FREE_OP1();
9708 FREE_OP2();
9709 HANDLE_EXCEPTION();
9710 }
9711
9712 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9713 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9714 zend_frameless_observed_call(execute_data);
9715 } else
9716 #endif
9717 {
9718 zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline);
9719 function(result, arg1, arg2);
9720 }
9721
9722 FREE_OP1();
9723 /* Set OP1 to UNDEF in case FREE_OP2() throws. */
9724 if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
9725 ZVAL_UNDEF(EX_VAR(opline->op1.var));
9726 }
9727 FREE_OP2();
9728 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9729 }
9730
9731 ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
9732 {
9733 USE_OPLINE
9734 SAVE_OPLINE();
9735
9736 zval *result = EX_VAR(opline->result.var);
9737 ZVAL_NULL(result);
9738 zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9739 zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
9740 zval *arg3 = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);
9741 if (EG(exception)) {
9742 FREE_OP1();
9743 FREE_OP2();
9744 FREE_OP_DATA();
9745 HANDLE_EXCEPTION();
9746 }
9747
9748 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9749 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9750 zend_frameless_observed_call(execute_data);
9751 } else
9752 #endif
9753 {
9754 zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline);
9755 function(result, arg1, arg2, arg3);
9756 }
9757
9758 FREE_OP1();
9759 /* Set to UNDEF in case FREE_OP2() throws. */
9760 if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
9761 ZVAL_UNDEF(EX_VAR(opline->op1.var));
9762 }
9763 FREE_OP2();
9764 if (OP2_TYPE & (IS_VAR|IS_TMP_VAR)) {
9765 ZVAL_UNDEF(EX_VAR(opline->op2.var));
9766 }
9767 FREE_OP_DATA();
9768 ZEND_VM_NEXT_OPCODE_EX(1, 2);
9769 }
9770
9771 ZEND_VM_HANDLER(209, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL, CONST, UNUSED|NUM, NUM)
9772 {
9773 USE_OPLINE
9774 SAVE_OPLINE();
9775
9776 zend_class_entry *ce = EX(func)->common.scope;
9777 ZEND_ASSERT(ce);
9778
9779 zend_class_entry *parent_ce = ce->parent;
9780 if (!parent_ce) {
9781 zend_throw_error(NULL, "Cannot use \"parent\" when current class scope has no parent");
9782 UNDEF_RESULT();
9783 HANDLE_EXCEPTION();
9784 }
9785
9786 zend_string *property_name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
9787 zend_property_hook_kind hook_kind = opline->op2.num;
9788
9789 zend_property_info *prop_info = zend_hash_find_ptr(&parent_ce->properties_info, property_name);
9790 if (!prop_info) {
9791 zend_throw_error(NULL, "Undefined property %s::$%s", ZSTR_VAL(parent_ce->name), ZSTR_VAL(property_name));
9792 UNDEF_RESULT();
9793 HANDLE_EXCEPTION();
9794 }
9795 if (prop_info->flags & ZEND_ACC_PRIVATE) {
9796 zend_throw_error(NULL, "Cannot access private property %s::$%s", ZSTR_VAL(parent_ce->name), ZSTR_VAL(property_name));
9797 UNDEF_RESULT();
9798 HANDLE_EXCEPTION();
9799 }
9800
9801 zend_function **hooks = prop_info->hooks;
9802 zend_function *hook = hooks ? hooks[hook_kind] : NULL;
9803
9804 zend_execute_data *call;
9805 if (hook) {
9806 call = zend_vm_stack_push_call_frame(
9807 ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS,
9808 hook, opline->extended_value, Z_OBJ_P(ZEND_THIS));
9809 if (EXPECTED(hook->type == ZEND_USER_FUNCTION)) {
9810 if (UNEXPECTED(!RUN_TIME_CACHE(&hook->op_array))) {
9811 init_func_run_time_cache(&hook->op_array);
9812 }
9813 call->run_time_cache = RUN_TIME_CACHE(&hook->op_array);
9814 }
9815 } else {
9816 zend_function *fbc = zend_get_property_hook_trampoline(prop_info, hook_kind, property_name);
9817 call = zend_vm_stack_push_call_frame(
9818 ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS,
9819 fbc, opline->extended_value, Z_OBJ_P(ZEND_THIS));
9820 }
9821
9822 call->prev_execute_data = EX(call);
9823 EX(call) = call;
9824 ZEND_VM_NEXT_OPCODE();
9825 }
9826
9827 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_JMP, (OP_JMP_ADDR(op, op->op1) > op), ZEND_JMP_FORWARD, JMP_ADDR, ANY)
9828 {
9829 USE_OPLINE
9830
9831 OPLINE = OP_JMP_ADDR(opline, opline->op1);
9832 ZEND_VM_CONTINUE();
9833 }
9834
9835 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
9836 {
9837 USE_OPLINE
9838 zval *op1, *op2, *result;
9839
9840 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9841 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9842 result = EX_VAR(opline->result.var);
9843 ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2));
9844 ZEND_VM_NEXT_OPCODE();
9845 }
9846
9847 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
9848 {
9849 USE_OPLINE
9850 zval *op1, *op2, *result;
9851
9852 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9853 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9854 result = EX_VAR(opline->result.var);
9855 fast_long_add_function(result, op1, op2);
9856 ZEND_VM_NEXT_OPCODE();
9857 }
9858
9859 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_ADD, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_ADD_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
9860 {
9861 USE_OPLINE
9862 zval *op1, *op2, *result;
9863
9864 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9865 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9866 result = EX_VAR(opline->result.var);
9867 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
9868 ZEND_VM_NEXT_OPCODE();
9869 }
9870
9871 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
9872 {
9873 USE_OPLINE
9874 zval *op1, *op2, *result;
9875
9876 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9877 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9878 result = EX_VAR(opline->result.var);
9879 ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));
9880 ZEND_VM_NEXT_OPCODE();
9881 }
9882
9883 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_SUB_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
9884 {
9885 USE_OPLINE
9886 zval *op1, *op2, *result;
9887
9888 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9889 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9890 result = EX_VAR(opline->result.var);
9891 fast_long_sub_function(result, op1, op2);
9892 ZEND_VM_NEXT_OPCODE();
9893 }
9894
9895 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SUB, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_SUB_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
9896 {
9897 USE_OPLINE
9898 zval *op1, *op2, *result;
9899
9900 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9901 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9902 result = EX_VAR(opline->result.var);
9903 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
9904 ZEND_VM_NEXT_OPCODE();
9905 }
9906
9907 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
9908 {
9909 USE_OPLINE
9910 zval *op1, *op2, *result;
9911
9912 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9913 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9914 result = EX_VAR(opline->result.var);
9915 ZVAL_LONG(result, Z_LVAL_P(op1) * Z_LVAL_P(op2));
9916 ZEND_VM_NEXT_OPCODE();
9917 }
9918
9919 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_MUL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
9920 {
9921 USE_OPLINE
9922 zval *op1, *op2, *result;
9923 zend_long overflow;
9924
9925 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9926 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9927 result = EX_VAR(opline->result.var);
9928 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
9929 Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
9930 ZEND_VM_NEXT_OPCODE();
9931 }
9932
9933 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_MUL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_MUL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
9934 {
9935 USE_OPLINE
9936 zval *op1, *op2, *result;
9937
9938 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9939 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9940 result = EX_VAR(opline->result.var);
9941 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
9942 ZEND_VM_NEXT_OPCODE();
9943 }
9944
9945 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL|ZEND_IS_IDENTICAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
9946 {
9947 USE_OPLINE
9948 zval *op1, *op2;
9949 bool result;
9950
9951 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9952 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9953 result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
9954 ZEND_VM_SMART_BRANCH(result, 0);
9955 }
9956
9957 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_EQUAL|ZEND_IS_IDENTICAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
9958 {
9959 USE_OPLINE
9960 zval *op1, *op2;
9961 bool result;
9962
9963 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9964 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9965 result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
9966 ZEND_VM_SMART_BRANCH(result, 0);
9967 }
9968
9969 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_NOT_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
9970 {
9971 USE_OPLINE
9972 zval *op1, *op2;
9973 bool result;
9974
9975 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9976 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9977 result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
9978 ZEND_VM_SMART_BRANCH(result, 0);
9979 }
9980
9981 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_NOT_EQUAL|ZEND_IS_NOT_IDENTICAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_NOT_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST,COMMUTATIVE))
9982 {
9983 USE_OPLINE
9984 zval *op1, *op2;
9985 bool result;
9986
9987 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9988 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9989 result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
9990 ZEND_VM_SMART_BRANCH(result, 0);
9991 }
9992
9993 ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)), ZEND_IS_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
9994 {
9995 /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */
9996 /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */
9997 /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */
9998 USE_OPLINE
9999 zval *op1, *op2;
10000 bool result;
10001
10002 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10003 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10004 result = fast_is_identical_function(op1, op2);
10005 /* Free is a no-op for const/cv */
10006 ZEND_VM_SMART_BRANCH(result, 0);
10007 }
10008
10009 ZEND_VM_TYPE_SPEC_HANDLER(ZEND_IS_NOT_IDENTICAL, op->op1_type == IS_CV && (op->op2_type & (IS_CONST|IS_CV)) && !(op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) && !(op2_info & (MAY_BE_UNDEF|MAY_BE_REF)), ZEND_IS_NOT_IDENTICAL_NOTHROW, CV, CONST|CV, SPEC(COMMUTATIVE))
10010 {
10011 USE_OPLINE
10012 zval *op1, *op2;
10013 bool result;
10014
10015 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10016 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10017 result = fast_is_identical_function(op1, op2);
10018 /* Free is a no-op for const/cv */
10019 ZEND_VM_SMART_BRANCH(!result, 0);
10020 }
10021
10022 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
10023 {
10024 USE_OPLINE
10025 zval *op1, *op2;
10026 bool result;
10027
10028 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10029 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10030 result = (Z_LVAL_P(op1) < Z_LVAL_P(op2));
10031 ZEND_VM_SMART_BRANCH(result, 0);
10032 }
10033
10034 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
10035 {
10036 USE_OPLINE
10037 zval *op1, *op2;
10038 bool result;
10039
10040 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10041 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10042 result = (Z_DVAL_P(op1) < Z_DVAL_P(op2));
10043 ZEND_VM_SMART_BRANCH(result, 0);
10044 }
10045
10046 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_IS_SMALLER_OR_EQUAL_LONG, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
10047 {
10048 USE_OPLINE
10049 zval *op1, *op2;
10050 bool result;
10051
10052 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10053 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10054 result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2));
10055 ZEND_VM_SMART_BRANCH(result, 0);
10056 }
10057
10058 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_IS_SMALLER_OR_EQUAL, (op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE), ZEND_IS_SMALLER_OR_EQUAL_DOUBLE, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(SMART_BRANCH,NO_CONST_CONST))
10059 {
10060 USE_OPLINE
10061 zval *op1, *op2;
10062 bool result;
10063
10064 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10065 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10066 result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2));
10067 ZEND_VM_SMART_BRANCH(result, 0);
10068 }
10069
10070 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG_NO_OVERFLOW, CV, ANY, SPEC(RETVAL))
10071 {
10072 USE_OPLINE
10073 zval *var_ptr;
10074
10075 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10076 Z_LVAL_P(var_ptr)++;
10077 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10078 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10079 }
10080 ZEND_VM_NEXT_OPCODE();
10081 }
10082
10083 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG, CV, ANY, SPEC(RETVAL))
10084 {
10085 USE_OPLINE
10086 zval *var_ptr;
10087
10088 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10089 fast_long_increment_function(var_ptr);
10090 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10091 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
10092 }
10093 ZEND_VM_NEXT_OPCODE();
10094 }
10095
10096 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG_NO_OVERFLOW, CV, ANY, SPEC(RETVAL))
10097 {
10098 USE_OPLINE
10099 zval *var_ptr;
10100
10101 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10102 Z_LVAL_P(var_ptr)--;
10103 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10104 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10105 }
10106 ZEND_VM_NEXT_OPCODE();
10107 }
10108
10109 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG, CV, ANY, SPEC(RETVAL))
10110 {
10111 USE_OPLINE
10112 zval *var_ptr;
10113
10114 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10115 fast_long_decrement_function(var_ptr);
10116 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10117 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
10118 }
10119 ZEND_VM_NEXT_OPCODE();
10120 }
10121
10122 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG_NO_OVERFLOW, CV, ANY)
10123 {
10124 USE_OPLINE
10125 zval *var_ptr;
10126
10127 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10128 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10129 Z_LVAL_P(var_ptr)++;
10130 ZEND_VM_NEXT_OPCODE();
10131 }
10132
10133 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG, CV, ANY)
10134 {
10135 USE_OPLINE
10136 zval *var_ptr;
10137
10138 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10139 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10140 fast_long_increment_function(var_ptr);
10141 ZEND_VM_NEXT_OPCODE();
10142 }
10143
10144 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG_NO_OVERFLOW, CV, ANY)
10145 {
10146 USE_OPLINE
10147 zval *var_ptr;
10148
10149 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10150 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10151 Z_LVAL_P(var_ptr)--;
10152 ZEND_VM_NEXT_OPCODE();
10153 }
10154
10155 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG, CV, ANY)
10156 {
10157 USE_OPLINE
10158 zval *var_ptr;
10159
10160 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10161 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10162 fast_long_decrement_function(var_ptr);
10163 ZEND_VM_NEXT_OPCODE();
10164 }
10165
10166 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_LONG), ZEND_QM_ASSIGN_LONG, CONST|TMPVARCV, ANY)
10167 {
10168 USE_OPLINE
10169 zval *value;
10170
10171 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10172 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(value));
10173 ZEND_VM_NEXT_OPCODE();
10174 }
10175
10176 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_ASSIGN_DOUBLE, CONST|TMPVARCV, ANY)
10177 {
10178 USE_OPLINE
10179 zval *value;
10180
10181 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10182 ZVAL_DOUBLE(EX_VAR(opline->result.var), Z_DVAL_P(value));
10183 ZEND_VM_NEXT_OPCODE();
10184 }
10185
10186 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, ((op->op1_type == IS_CONST) ? !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)) : (!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))), ZEND_QM_ASSIGN_NOREF, CONST|TMPVARCV, ANY)
10187 {
10188 USE_OPLINE
10189 zval *value;
10190
10191 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10192 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
10193 ZEND_VM_NEXT_OPCODE();
10194 }
10195
10196 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FETCH_DIM_R, (!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))), ZEND_FETCH_DIM_R_INDEX, CONST|TMPVAR|CV, CONST|TMPVARCV, SPEC(NO_CONST_CONST))
10197 {
10198 USE_OPLINE
10199 zval *container, *dim, *value;
10200 zend_long offset;
10201 HashTable *ht;
10202
10203 container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10204 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10205 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
10206 ZEND_VM_C_LABEL(fetch_dim_r_index_array):
10207 if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
10208 offset = Z_LVAL_P(dim);
10209 } else {
10210 SAVE_OPLINE();
10211 zend_fetch_dimension_address_read_R(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
10212 FREE_OP1();
10213 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10214 }
10215 ht = Z_ARRVAL_P(container);
10216 ZEND_HASH_INDEX_FIND(ht, offset, value, ZEND_VM_C_LABEL(fetch_dim_r_index_undef));
10217 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value);
10218 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
10219 SAVE_OPLINE();
10220 FREE_OP1();
10221 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10222 } else {
10223 ZEND_VM_NEXT_OPCODE();
10224 }
10225 } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
10226 container = Z_REFVAL_P(container);
10227 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
10228 ZEND_VM_C_GOTO(fetch_dim_r_index_array);
10229 } else {
10230 ZEND_VM_C_GOTO(fetch_dim_r_index_slow);
10231 }
10232 } else {
10233 ZEND_VM_C_LABEL(fetch_dim_r_index_slow):
10234 SAVE_OPLINE();
10235 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
10236 dim++;
10237 }
10238 zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
10239 FREE_OP1();
10240 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10241 }
10242
10243 ZEND_VM_C_LABEL(fetch_dim_r_index_undef):
10244 ZVAL_NULL(EX_VAR(opline->result.var));
10245 SAVE_OPLINE();
10246 zend_undefined_offset(offset);
10247 FREE_OP1();
10248 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10249 }
10250
10251 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR, op->op2_type == IS_UNUSED && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_SIMPLE, CV|VAR, NUM)
10252 {
10253 USE_OPLINE
10254 zval *varptr, *arg;
10255
10256 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10257 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10258
10259 if (OP1_TYPE == IS_CV) {
10260 ZVAL_COPY(arg, varptr);
10261 } else /* if (OP1_TYPE == IS_VAR) */ {
10262 ZVAL_COPY_VALUE(arg, varptr);
10263 }
10264
10265 ZEND_VM_NEXT_OPCODE();
10266 }
10267
10268 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAR_EX, op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && (op1_info & (MAY_BE_UNDEF|MAY_BE_REF)) == 0, ZEND_SEND_VAR_EX_SIMPLE, CV|VAR, UNUSED|NUM)
10269 {
10270 USE_OPLINE
10271 zval *varptr, *arg;
10272 uint32_t arg_num = opline->op2.num;
10273
10274 if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
10275 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
10276 }
10277
10278 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10279 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10280
10281 if (OP1_TYPE == IS_CV) {
10282 ZVAL_COPY(arg, varptr);
10283 } else /* if (OP1_TYPE == IS_VAR) */ {
10284 ZVAL_COPY_VALUE(arg, varptr);
10285 }
10286
10287 ZEND_VM_NEXT_OPCODE();
10288 }
10289
10290 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAL, op->op1_type == IS_CONST && op->op2_type == IS_UNUSED && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)), ZEND_SEND_VAL_SIMPLE, CONST, NUM)
10291 {
10292 USE_OPLINE
10293 zval *value, *arg;
10294
10295 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
10296 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10297 ZVAL_COPY_VALUE(arg, value);
10298 ZEND_VM_NEXT_OPCODE();
10299 }
10300
10301 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_SEND_VAL_EX, op->op2_type == IS_UNUSED && op->op2.num <= MAX_ARG_FLAG_NUM && op->op1_type == IS_CONST && !Z_REFCOUNTED_P(RT_CONSTANT(op, op->op1)), ZEND_SEND_VAL_EX_SIMPLE, CONST, NUM)
10302 {
10303 USE_OPLINE
10304 zval *value, *arg;
10305 uint32_t arg_num = opline->op2.num;
10306
10307 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10308 if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
10309 ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper, _arg_num, arg_num, _arg, arg);
10310 }
10311 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
10312 ZVAL_COPY_VALUE(arg, value);
10313 ZEND_VM_NEXT_OPCODE();
10314 }
10315
10316 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_FE_FETCH_R, op->op2_type == IS_CV && (op1_info & (MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY, ZEND_FE_FETCH_R_SIMPLE, VAR, CV, JMP_ADDR, SPEC(RETVAL))
10317 {
10318 USE_OPLINE
10319 zval *array;
10320 zval *value, *variable_ptr;
10321 uint32_t value_type;
10322 HashTable *fe_ht;
10323 HashPosition pos;
10324
10325 array = EX_VAR(opline->op1.var);
10326 SAVE_OPLINE();
10327 fe_ht = Z_ARRVAL_P(array);
10328 pos = Z_FE_POS_P(array);
10329 if (HT_IS_PACKED(fe_ht)) {
10330 value = fe_ht->arPacked + pos;
10331 while (1) {
10332 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
10333 /* reached end of iteration */
10334 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
10335 ZEND_VM_CONTINUE();
10336 }
10337 value_type = Z_TYPE_INFO_P(value);
10338 ZEND_ASSERT(value_type != IS_INDIRECT);
10339 if (EXPECTED(value_type != IS_UNDEF)) {
10340 break;
10341 }
10342 pos++;
10343 value++;
10344 }
10345 Z_FE_POS_P(array) = pos + 1;
10346 if (RETURN_VALUE_USED(opline)) {
10347 ZVAL_LONG(EX_VAR(opline->result.var), pos);
10348 }
10349 } else {
10350 Bucket *p;
10351
10352 p = fe_ht->arData + pos;
10353 while (1) {
10354 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
10355 /* reached end of iteration */
10356 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
10357 ZEND_VM_CONTINUE();
10358 }
10359 pos++;
10360 value = &p->val;
10361 value_type = Z_TYPE_INFO_P(value);
10362 ZEND_ASSERT(value_type != IS_INDIRECT);
10363 if (EXPECTED(value_type != IS_UNDEF)) {
10364 break;
10365 }
10366 p++;
10367 }
10368 Z_FE_POS_P(array) = pos;
10369 if (RETURN_VALUE_USED(opline)) {
10370 if (!p->key) {
10371 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
10372 } else {
10373 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
10374 }
10375 }
10376 }
10377
10378 variable_ptr = EX_VAR(opline->op2.var);
10379 zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
10380 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10381 }
10382
10383 ZEND_VM_DEFINE_OP(137, ZEND_OP_DATA);
10384
ZEND_VM_HELPER(zend_interrupt_helper,ANY,ANY)10385 ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY)
10386 {
10387 zend_atomic_bool_store_ex(&EG(vm_interrupt), false);
10388 SAVE_OPLINE();
10389 if (zend_atomic_bool_load_ex(&EG(timed_out))) {
10390 zend_timeout();
10391 } else if (zend_interrupt_function) {
10392 zend_interrupt_function(execute_data);
10393 if (EG(exception)) {
10394 /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
10395 const zend_op *throw_op = EG(opline_before_exception);
10396
10397 if (throw_op
10398 && throw_op->result_type & (IS_TMP_VAR|IS_VAR)
10399 && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
10400 && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
10401 && throw_op->opcode != ZEND_ROPE_INIT
10402 && throw_op->opcode != ZEND_ROPE_ADD) {
10403 ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
10404
10405 }
10406 }
10407 ZEND_VM_ENTER();
10408 }
10409 ZEND_VM_CONTINUE();
10410 }
10411