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(orig_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
3913 /* Deprecation can be emitted from zend_is_callable_ex(), which can
3914 * invoke a user error handler and throw an exception.
3915 * For the CONST and CV case we reuse the same exception block below
3916 * to make sure we don't increase VM size too much. */
3917 if (!(OP2_TYPE & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
3918 FREE_OP2();
3919 HANDLE_EXCEPTION();
3920 }
3921
3922 func = fcc.function_handler;
3923 object_or_called_scope = fcc.called_scope;
3924 if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
3925 /* Delay closure destruction until its invocation */
3926 GC_ADDREF(ZEND_CLOSURE_OBJECT(func));
3927 call_info |= ZEND_CALL_CLOSURE;
3928 if (func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
3929 call_info |= ZEND_CALL_FAKE_CLOSURE;
3930 }
3931 if (fcc.object) {
3932 object_or_called_scope = fcc.object;
3933 call_info |= ZEND_CALL_HAS_THIS;
3934 }
3935 } else if (fcc.object) {
3936 GC_ADDREF(fcc.object); /* For $this pointer */
3937 object_or_called_scope = fcc.object;
3938 call_info |= ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS;
3939 }
3940
3941 FREE_OP2();
3942 if ((OP2_TYPE & (IS_TMP_VAR|IS_VAR)) && UNEXPECTED(EG(exception))) {
3943 if (call_info & ZEND_CALL_CLOSURE) {
3944 zend_object_release(ZEND_CLOSURE_OBJECT(func));
3945 } else if (call_info & ZEND_CALL_RELEASE_THIS) {
3946 zend_object_release(fcc.object);
3947 }
3948 HANDLE_EXCEPTION();
3949 }
3950
3951 if (EXPECTED(func->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&func->op_array))) {
3952 init_func_run_time_cache(&func->op_array);
3953 }
3954 } else {
3955 zend_type_error("%s(): Argument #1 ($callback) must be a valid callback, %s", Z_STRVAL_P(RT_CONSTANT(opline, opline->op1)), error);
3956 efree(error);
3957 FREE_OP2();
3958 HANDLE_EXCEPTION();
3959 }
3960
3961 call = zend_vm_stack_push_call_frame(call_info,
3962 func, opline->extended_value, object_or_called_scope);
3963 call->prev_execute_data = EX(call);
3964 EX(call) = call;
3965
3966 ZEND_VM_NEXT_OPCODE();
3967 }
3968
3969 ZEND_VM_HOT_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM|CACHE_SLOT)
3970 {
3971 USE_OPLINE
3972 zval *func_name;
3973 zval *func;
3974 zend_function *fbc;
3975 zend_execute_data *call;
3976
3977 fbc = CACHED_PTR(opline->result.num);
3978 if (UNEXPECTED(fbc == NULL)) {
3979 func_name = (zval *)RT_CONSTANT(opline, opline->op2);
3980 func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 1));
3981 if (func == NULL) {
3982 func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name + 2));
3983 if (UNEXPECTED(func == NULL)) {
3984 ZEND_VM_DISPATCH_TO_HELPER(zend_undefined_function_helper);
3985 }
3986 }
3987 fbc = Z_FUNC_P(func);
3988 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
3989 init_func_run_time_cache(&fbc->op_array);
3990 }
3991 CACHE_PTR(opline->result.num, fbc);
3992 }
3993
3994 call = _zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
3995 fbc, opline->extended_value, NULL);
3996 call->prev_execute_data = EX(call);
3997 EX(call) = call;
3998
3999 ZEND_VM_NEXT_OPCODE();
4000 }
4001
4002 ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
4003 {
4004 USE_OPLINE
4005 zval *fname;
4006 zval *func;
4007 zend_function *fbc;
4008 zend_execute_data *call;
4009
4010 fbc = CACHED_PTR(opline->result.num);
4011 if (UNEXPECTED(fbc == NULL)) {
4012 fname = (zval*)RT_CONSTANT(opline, opline->op2);
4013 func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(fname));
4014 ZEND_ASSERT(func != NULL && "Function existence must be checked at compile time");
4015 fbc = Z_FUNC_P(func);
4016 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4017 init_func_run_time_cache(&fbc->op_array);
4018 }
4019 CACHE_PTR(opline->result.num, fbc);
4020 }
4021
4022 call = _zend_vm_stack_push_call_frame_ex(
4023 opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
4024 fbc, opline->extended_value, NULL);
4025 call->prev_execute_data = EX(call);
4026 EX(call) = call;
4027
4028 ZEND_VM_NEXT_OPCODE();
4029 }
4030
4031 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)
4032 {
4033 USE_OPLINE
4034 zend_function *fbc;
4035 zend_execute_data *call;
4036 fbc = CACHED_PTR(opline->result.num);
4037 if (UNEXPECTED(fbc == NULL)) {
4038 fbc = Z_PTR(EG(function_table)->arData[Z_EXTRA_P(RT_CONSTANT(opline, opline->op2))].val);
4039 CACHE_PTR(opline->result.num, fbc);
4040 }
4041 call = _zend_vm_stack_push_call_frame_ex(
4042 opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
4043 fbc, opline->extended_value, NULL);
4044 call->prev_execute_data = EX(call);
4045 EX(call) = call;
4046 ZEND_VM_NEXT_OPCODE();
4047 }
4048
4049 ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
4050 {
4051 USE_OPLINE
4052 zend_execute_data *call = EX(call);
4053 zend_function *fbc = call->func;
4054 zval *ret;
4055 zval retval;
4056
4057 SAVE_OPLINE();
4058 EX(call) = call->prev_execute_data;
4059
4060 call->prev_execute_data = execute_data;
4061 EG(current_execute_data) = call;
4062
4063 #if ZEND_DEBUG
4064 bool should_throw = zend_internal_call_should_throw(fbc, call);
4065 #endif
4066
4067 ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
4068 ZVAL_NULL(ret);
4069
4070 ZEND_OBSERVER_FCALL_BEGIN(call);
4071 fbc->internal_function.handler(call, ret);
4072
4073 #if ZEND_DEBUG
4074 if (!EG(exception) && call->func) {
4075 if (should_throw) {
4076 zend_internal_call_arginfo_violation(call->func);
4077 }
4078 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
4079 zend_verify_internal_return_type(call->func, ret));
4080 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
4081 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
4082 zend_verify_internal_func_info(call->func, ret);
4083 }
4084 #endif
4085 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
4086 ZEND_VM_FCALL_INTERRUPT_CHECK(call);
4087
4088 EG(current_execute_data) = execute_data;
4089 zend_vm_stack_free_args(call);
4090
4091 uint32_t call_info = ZEND_CALL_INFO(call);
4092 if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) {
4093 if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
4094 zend_free_extra_named_params(call->extra_named_params);
4095 }
4096 zend_vm_stack_free_call_frame_ex(call_info, call);
4097 } else {
4098 EG(vm_stack_top) = (zval*)call;
4099 }
4100
4101 if (!RETURN_VALUE_USED(opline)) {
4102 i_zval_ptr_dtor(ret);
4103 }
4104
4105 if (UNEXPECTED(EG(exception) != NULL)) {
4106 zend_rethrow_exception(execute_data);
4107 HANDLE_EXCEPTION();
4108 }
4109
4110 ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1);
4111 ZEND_VM_CONTINUE();
4112 }
4113
4114 ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
4115 {
4116 USE_OPLINE
4117 zend_execute_data *call = EX(call);
4118 zend_function *fbc = call->func;
4119 zval *ret;
4120
4121 SAVE_OPLINE();
4122 EX(call) = call->prev_execute_data;
4123
4124 ret = NULL;
4125 if (RETURN_VALUE_USED(opline)) {
4126 ret = EX_VAR(opline->result.var);
4127 }
4128
4129 call->prev_execute_data = execute_data;
4130 execute_data = call;
4131 i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
4132 LOAD_OPLINE_EX();
4133 ZEND_OBSERVER_SAVE_OPLINE();
4134 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4135
4136 ZEND_VM_ENTER_EX();
4137 }
4138
4139 ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
4140 {
4141 USE_OPLINE
4142 zend_execute_data *call = EX(call);
4143 zend_function *fbc = call->func;
4144 zval *ret;
4145 zval retval;
4146
4147 SAVE_OPLINE();
4148 EX(call) = call->prev_execute_data;
4149
4150 if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
4151 zend_deprecated_function(fbc);
4152 if (UNEXPECTED(EG(exception) != NULL)) {
4153 UNDEF_RESULT();
4154 if (!RETURN_VALUE_USED(opline)) {
4155 ret = &retval;
4156 ZVAL_UNDEF(ret);
4157 }
4158 ZEND_VM_C_GOTO(fcall_by_name_end);
4159 }
4160 }
4161
4162 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
4163 ret = NULL;
4164 if (RETURN_VALUE_USED(opline)) {
4165 ret = EX_VAR(opline->result.var);
4166 }
4167
4168 call->prev_execute_data = execute_data;
4169 execute_data = call;
4170 i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
4171 LOAD_OPLINE_EX();
4172 ZEND_OBSERVER_SAVE_OPLINE();
4173 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4174
4175 ZEND_VM_ENTER_EX();
4176 } else {
4177 ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
4178 if (ZEND_OBSERVER_ENABLED) {
4179 ret = NULL;
4180 }
4181
4182 call->prev_execute_data = execute_data;
4183 EG(current_execute_data) = call;
4184
4185 #if ZEND_DEBUG
4186 bool should_throw = zend_internal_call_should_throw(fbc, call);
4187 #endif
4188
4189 ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
4190 ZVAL_NULL(ret);
4191
4192 ZEND_OBSERVER_FCALL_BEGIN(call);
4193 fbc->internal_function.handler(call, ret);
4194
4195 #if ZEND_DEBUG
4196 if (!EG(exception) && call->func) {
4197 if (should_throw) {
4198 zend_internal_call_arginfo_violation(call->func);
4199 }
4200 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
4201 zend_verify_internal_return_type(call->func, ret));
4202 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
4203 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
4204 zend_verify_internal_func_info(call->func, ret);
4205 }
4206 #endif
4207 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
4208 ZEND_VM_FCALL_INTERRUPT_CHECK(call);
4209
4210 EG(current_execute_data) = execute_data;
4211
4212 ZEND_VM_C_GOTO(fcall_by_name_end);
4213 }
4214
4215 if (0) {
4216 ZEND_VM_C_LABEL(fcall_by_name_end):
4217
4218 zend_vm_stack_free_args(call);
4219
4220 uint32_t call_info = ZEND_CALL_INFO(call);
4221 if (UNEXPECTED(call_info & (ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_ALLOCATED))) {
4222 if (call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
4223 zend_free_extra_named_params(call->extra_named_params);
4224 }
4225 zend_vm_stack_free_call_frame_ex(call_info, call);
4226 } else {
4227 EG(vm_stack_top) = (zval*)call;
4228 }
4229
4230 if (!RETURN_VALUE_USED(opline)) {
4231 i_zval_ptr_dtor(ret);
4232 }
4233 }
4234
4235 if (UNEXPECTED(EG(exception) != NULL)) {
4236 zend_rethrow_exception(execute_data);
4237 HANDLE_EXCEPTION();
4238 }
4239 ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1);
4240 ZEND_VM_CONTINUE();
4241 }
4242
4243 ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
4244 {
4245 USE_OPLINE
4246 zend_execute_data *call = EX(call);
4247 zend_function *fbc = call->func;
4248 zval *ret;
4249 zval retval;
4250
4251 SAVE_OPLINE();
4252 EX(call) = call->prev_execute_data;
4253
4254 if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
4255 zend_deprecated_function(fbc);
4256 if (UNEXPECTED(EG(exception) != NULL)) {
4257 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) {
4258 OBJ_RELEASE(ZEND_CLOSURE_OBJECT(call->func));
4259 }
4260 UNDEF_RESULT();
4261 if (!RETURN_VALUE_USED(opline)) {
4262 ret = &retval;
4263 ZVAL_UNDEF(ret);
4264 }
4265 ZEND_VM_C_GOTO(fcall_end);
4266 }
4267 }
4268
4269 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
4270 ret = NULL;
4271 if (RETURN_VALUE_USED(opline)) {
4272 ret = EX_VAR(opline->result.var);
4273 }
4274
4275 call->prev_execute_data = execute_data;
4276 execute_data = call;
4277 i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC);
4278
4279 if (EXPECTED(zend_execute_ex == execute_ex)) {
4280 LOAD_OPLINE_EX();
4281 ZEND_OBSERVER_SAVE_OPLINE();
4282 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4283 ZEND_VM_ENTER_EX();
4284 } else {
4285 SAVE_OPLINE_EX();
4286 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
4287 execute_data = EX(prev_execute_data);
4288 LOAD_OPLINE();
4289 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
4290 zend_execute_ex(call);
4291 }
4292 } else {
4293 ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
4294 if (ZEND_OBSERVER_ENABLED) {
4295 ret = NULL;
4296 }
4297
4298 call->prev_execute_data = execute_data;
4299 EG(current_execute_data) = call;
4300
4301 #if ZEND_DEBUG
4302 bool should_throw = zend_internal_call_should_throw(fbc, call);
4303 #endif
4304
4305 ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
4306 ZVAL_NULL(ret);
4307
4308 ZEND_OBSERVER_FCALL_BEGIN(call);
4309 if (!zend_execute_internal) {
4310 /* saves one function call if zend_execute_internal is not used */
4311 fbc->internal_function.handler(call, ret);
4312 } else {
4313 zend_execute_internal(call, ret);
4314 }
4315
4316 #if ZEND_DEBUG
4317 if (!EG(exception) && call->func && !(call->func->common.fn_flags & ZEND_ACC_FAKE_CLOSURE)) {
4318 if (should_throw) {
4319 zend_internal_call_arginfo_violation(call->func);
4320 }
4321 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
4322 zend_verify_internal_return_type(call->func, ret));
4323 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
4324 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
4325 zend_verify_internal_func_info(call->func, ret);
4326 }
4327 #endif
4328 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
4329 ZEND_VM_FCALL_INTERRUPT_CHECK(call);
4330
4331 EG(current_execute_data) = execute_data;
4332
4333 ZEND_VM_C_GOTO(fcall_end);
4334 }
4335
4336 if (0) {
4337 ZEND_VM_C_LABEL(fcall_end):
4338
4339 zend_vm_stack_free_args(call);
4340 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
4341 zend_free_extra_named_params(call->extra_named_params);
4342 }
4343
4344 if (!RETURN_VALUE_USED(opline)) {
4345 i_zval_ptr_dtor(ret);
4346 }
4347 }
4348
4349 if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) {
4350 OBJ_RELEASE(Z_OBJ(call->This));
4351 }
4352
4353 zend_vm_stack_free_call_frame(call);
4354 if (UNEXPECTED(EG(exception) != NULL)) {
4355 zend_rethrow_exception(execute_data);
4356 HANDLE_EXCEPTION();
4357 }
4358 ZEND_VM_SET_OPCODE_NO_INTERRUPT(opline + 1);
4359 ZEND_VM_CONTINUE();
4360 }
4361
4362 ZEND_VM_COLD_CONST_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED|CACHE_SLOT)
4363 {
4364 if (OP1_TYPE == IS_UNUSED) {
4365 SAVE_OPLINE();
4366 zend_verify_missing_return_type(EX(func));
4367 HANDLE_EXCEPTION();
4368 } else {
4369 /* prevents "undefined variable opline" errors */
4370 #if !ZEND_VM_SPEC || (OP1_TYPE != IS_UNUSED)
4371 USE_OPLINE
4372 zval *retval_ref, *retval_ptr;
4373 zend_arg_info *ret_info = EX(func)->common.arg_info - 1;
4374 retval_ref = retval_ptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4375
4376 if (OP1_TYPE == IS_CONST) {
4377 ZVAL_COPY(EX_VAR(opline->result.var), retval_ptr);
4378 retval_ref = retval_ptr = EX_VAR(opline->result.var);
4379 } else if (OP1_TYPE == IS_VAR) {
4380 if (UNEXPECTED(Z_TYPE_P(retval_ptr) == IS_INDIRECT)) {
4381 retval_ref = retval_ptr = Z_INDIRECT_P(retval_ptr);
4382 }
4383 ZVAL_DEREF(retval_ptr);
4384 } else if (OP1_TYPE == IS_CV) {
4385 ZVAL_DEREF(retval_ptr);
4386 }
4387
4388 if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(ret_info->type, Z_TYPE_P(retval_ptr)))) {
4389 ZEND_VM_NEXT_OPCODE();
4390 }
4391
4392 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_ISUNDEF_P(retval_ptr))) {
4393 SAVE_OPLINE();
4394 retval_ref = retval_ptr = ZVAL_UNDEFINED_OP1();
4395 if (UNEXPECTED(EG(exception))) {
4396 HANDLE_EXCEPTION();
4397 }
4398 if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_NULL) {
4399 ZEND_VM_NEXT_OPCODE();
4400 }
4401 }
4402
4403 zend_reference *ref = NULL;
4404 void *cache_slot = CACHE_ADDR(opline->op2.num);
4405 if (UNEXPECTED(retval_ref != retval_ptr)) {
4406 if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
4407 ref = Z_REF_P(retval_ref);
4408 } else {
4409 /* A cast might happen - unwrap the reference if this is a by-value return */
4410 if (Z_REFCOUNT_P(retval_ref) == 1) {
4411 ZVAL_UNREF(retval_ref);
4412 } else {
4413 Z_DELREF_P(retval_ref);
4414 ZVAL_COPY(retval_ref, retval_ptr);
4415 }
4416 retval_ptr = retval_ref;
4417 }
4418 }
4419
4420 SAVE_OPLINE();
4421 if (UNEXPECTED(!zend_check_type_slow(&ret_info->type, retval_ptr, ref, cache_slot, 1, 0))) {
4422 zend_verify_return_error(EX(func), retval_ptr);
4423 HANDLE_EXCEPTION();
4424 }
4425 ZEND_VM_NEXT_OPCODE();
4426 #endif
4427 }
4428 }
4429
4430 ZEND_VM_COLD_HANDLER(201, ZEND_VERIFY_NEVER_TYPE, UNUSED, UNUSED)
4431 {
4432 SAVE_OPLINE();
4433 zend_verify_never_error(EX(func));
4434 HANDLE_EXCEPTION();
4435 }
4436
4437 ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER))
4438 {
4439 USE_OPLINE
4440 zval *retval_ptr;
4441 zval *return_value;
4442 ZEND_OBSERVER_USE_RETVAL;
4443
4444 retval_ptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4445 return_value = EX(return_value);
4446 ZEND_OBSERVER_SET_RETVAL();
4447 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
4448 SAVE_OPLINE();
4449 retval_ptr = ZVAL_UNDEFINED_OP1();
4450 if (return_value) {
4451 ZVAL_NULL(return_value);
4452 }
4453 } else if (!return_value) {
4454 if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
4455 if (Z_REFCOUNTED_P(retval_ptr) && !Z_DELREF_P(retval_ptr)) {
4456 SAVE_OPLINE();
4457 rc_dtor_func(Z_COUNTED_P(retval_ptr));
4458 }
4459 }
4460 } else {
4461 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
4462 ZVAL_COPY_VALUE(return_value, retval_ptr);
4463 if (OP1_TYPE == IS_CONST) {
4464 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(return_value))) {
4465 Z_ADDREF_P(return_value);
4466 }
4467 }
4468 } else if (OP1_TYPE == IS_CV) {
4469 do {
4470 if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
4471 if (EXPECTED(!Z_OPT_ISREF_P(retval_ptr))) {
4472 if (EXPECTED(!(EX_CALL_INFO() & (ZEND_CALL_CODE|ZEND_CALL_OBSERVED)))) {
4473 zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
4474 ZVAL_COPY_VALUE(return_value, retval_ptr);
4475 if (GC_MAY_LEAK(ref)) {
4476 SAVE_OPLINE();
4477 gc_possible_root(ref);
4478 }
4479 ZVAL_NULL(retval_ptr);
4480 break;
4481 } else {
4482 Z_ADDREF_P(retval_ptr);
4483 }
4484 } else {
4485 retval_ptr = Z_REFVAL_P(retval_ptr);
4486 if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
4487 Z_ADDREF_P(retval_ptr);
4488 }
4489 }
4490 }
4491 ZVAL_COPY_VALUE(return_value, retval_ptr);
4492 } while (0);
4493 } else /* if (OP1_TYPE == IS_VAR) */ {
4494 if (UNEXPECTED(Z_ISREF_P(retval_ptr))) {
4495 zend_refcounted *ref = Z_COUNTED_P(retval_ptr);
4496
4497 retval_ptr = Z_REFVAL_P(retval_ptr);
4498 ZVAL_COPY_VALUE(return_value, retval_ptr);
4499 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4500 efree_size(ref, sizeof(zend_reference));
4501 } else if (Z_OPT_REFCOUNTED_P(retval_ptr)) {
4502 Z_ADDREF_P(retval_ptr);
4503 }
4504 } else {
4505 ZVAL_COPY_VALUE(return_value, retval_ptr);
4506 }
4507 }
4508 }
4509 ZEND_OBSERVER_SAVE_OPLINE();
4510 ZEND_OBSERVER_FCALL_END(execute_data, return_value);
4511 ZEND_OBSERVER_FREE_RETVAL();
4512 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
4513 }
4514
4515 ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, SPEC(OBSERVER))
4516 {
4517 USE_OPLINE
4518 zval *retval_ptr;
4519 zval *return_value;
4520 ZEND_OBSERVER_USE_RETVAL;
4521
4522 SAVE_OPLINE();
4523
4524 return_value = EX(return_value);
4525 ZEND_OBSERVER_SET_RETVAL();
4526 do {
4527 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR)) ||
4528 (OP1_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) {
4529 /* Not supposed to happen, but we'll allow it */
4530 zend_error(E_NOTICE, "Only variable references should be returned by reference");
4531
4532 retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4533 if (!return_value) {
4534 FREE_OP1();
4535 } else {
4536 if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) {
4537 ZVAL_COPY_VALUE(return_value, retval_ptr);
4538 break;
4539 }
4540
4541 ZVAL_NEW_REF(return_value, retval_ptr);
4542 if (OP1_TYPE == IS_CONST) {
4543 Z_TRY_ADDREF_P(retval_ptr);
4544 }
4545 }
4546 break;
4547 }
4548
4549 retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
4550
4551 if (OP1_TYPE == IS_VAR) {
4552 ZEND_ASSERT(retval_ptr != &EG(uninitialized_zval));
4553 if (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr)) {
4554 zend_error(E_NOTICE, "Only variable references should be returned by reference");
4555 if (return_value) {
4556 ZVAL_NEW_REF(return_value, retval_ptr);
4557 } else {
4558 FREE_OP1();
4559 }
4560 break;
4561 }
4562 }
4563
4564 if (return_value) {
4565 if (Z_ISREF_P(retval_ptr)) {
4566 Z_ADDREF_P(retval_ptr);
4567 } else {
4568 ZVAL_MAKE_REF_EX(retval_ptr, 2);
4569 }
4570 ZVAL_REF(return_value, Z_REF_P(retval_ptr));
4571 }
4572
4573 FREE_OP1();
4574 } while (0);
4575
4576 ZEND_OBSERVER_FCALL_END(execute_data, return_value);
4577 ZEND_OBSERVER_FREE_RETVAL();
4578 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
4579 }
4580
4581 ZEND_VM_HANDLER(139, ZEND_GENERATOR_CREATE, ANY, ANY)
4582 {
4583 zval *return_value = EX(return_value);
4584
4585 if (EXPECTED(return_value)) {
4586 USE_OPLINE
4587 zend_generator *generator;
4588 zend_execute_data *gen_execute_data;
4589 uint32_t num_args, used_stack, call_info;
4590
4591 SAVE_OPLINE();
4592 object_init_ex(return_value, zend_ce_generator);
4593
4594 /*
4595 * Normally the execute_data is allocated on the VM stack (because it does
4596 * not actually do any allocation and thus is faster). For generators
4597 * though this behavior would be suboptimal, because the (rather large)
4598 * structure would have to be copied back and forth every time execution is
4599 * suspended or resumed. That's why for generators the execution context
4600 * is allocated on heap.
4601 */
4602 num_args = EX_NUM_ARGS();
4603 if (EXPECTED(num_args <= EX(func)->op_array.num_args)) {
4604 used_stack = (ZEND_CALL_FRAME_SLOT + EX(func)->op_array.last_var + EX(func)->op_array.T) * sizeof(zval);
4605 gen_execute_data = (zend_execute_data*)emalloc(used_stack);
4606 used_stack = (ZEND_CALL_FRAME_SLOT + EX(func)->op_array.last_var) * sizeof(zval);
4607 } else {
4608 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);
4609 gen_execute_data = (zend_execute_data*)emalloc(used_stack);
4610 }
4611 memcpy(gen_execute_data, execute_data, used_stack);
4612
4613 /* Save execution context in generator object. */
4614 generator = (zend_generator *) Z_OBJ_P(EX(return_value));
4615 generator->func = gen_execute_data->func;
4616 generator->execute_data = gen_execute_data;
4617 generator->frozen_call_stack = NULL;
4618 generator->execute_fake.opline = NULL;
4619 generator->execute_fake.func = NULL;
4620 generator->execute_fake.prev_execute_data = NULL;
4621 ZVAL_OBJ(&generator->execute_fake.This, (zend_object *) generator);
4622
4623 gen_execute_data->opline = opline;
4624 /* EX(return_value) keeps pointer to zend_object (not a real zval) */
4625 gen_execute_data->return_value = (zval*)generator;
4626 call_info = Z_TYPE_INFO(EX(This));
4627 if ((call_info & Z_TYPE_MASK) == IS_OBJECT
4628 && (!(call_info & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS))
4629 /* Bug #72523 */
4630 || UNEXPECTED(zend_execute_ex != execute_ex))) {
4631 ZEND_ADD_CALL_FLAG_EX(call_info, ZEND_CALL_RELEASE_THIS);
4632 Z_ADDREF(gen_execute_data->This);
4633 }
4634 ZEND_ADD_CALL_FLAG_EX(call_info, (ZEND_CALL_TOP_FUNCTION | ZEND_CALL_ALLOCATED | ZEND_CALL_GENERATOR));
4635 Z_TYPE_INFO(gen_execute_data->This) = call_info;
4636 gen_execute_data->prev_execute_data = NULL;
4637
4638 call_info = EX_CALL_INFO();
4639 EG(current_execute_data) = EX(prev_execute_data);
4640 if (EXPECTED(!(call_info & (ZEND_CALL_TOP|ZEND_CALL_ALLOCATED)))) {
4641 EG(vm_stack_top) = (zval*)execute_data;
4642 execute_data = EX(prev_execute_data);
4643 LOAD_NEXT_OPLINE();
4644 ZEND_VM_LEAVE();
4645 } else if (EXPECTED(!(call_info & ZEND_CALL_TOP))) {
4646 zend_execute_data *old_execute_data = execute_data;
4647 execute_data = EX(prev_execute_data);
4648 zend_vm_stack_free_call_frame_ex(call_info, old_execute_data);
4649 LOAD_NEXT_OPLINE();
4650 ZEND_VM_LEAVE();
4651 } else {
4652 ZEND_VM_RETURN();
4653 }
4654 } else {
4655 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
4656 }
4657 }
4658
4659 ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER))
4660 {
4661 USE_OPLINE
4662 zval *retval;
4663
4664 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
4665
4666 SAVE_OPLINE();
4667 retval = GET_OP1_ZVAL_PTR(BP_VAR_R);
4668
4669 /* Copy return value into generator->retval */
4670 if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
4671 ZVAL_COPY_VALUE(&generator->retval, retval);
4672 if (OP1_TYPE == IS_CONST) {
4673 if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->retval))) {
4674 Z_ADDREF(generator->retval);
4675 }
4676 }
4677 } else if (OP1_TYPE == IS_CV) {
4678 ZVAL_COPY_DEREF(&generator->retval, retval);
4679 } else /* if (OP1_TYPE == IS_VAR) */ {
4680 if (UNEXPECTED(Z_ISREF_P(retval))) {
4681 zend_refcounted *ref = Z_COUNTED_P(retval);
4682
4683 retval = Z_REFVAL_P(retval);
4684 ZVAL_COPY_VALUE(&generator->retval, retval);
4685 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4686 efree_size(ref, sizeof(zend_reference));
4687 } else if (Z_OPT_REFCOUNTED_P(retval)) {
4688 Z_ADDREF_P(retval);
4689 }
4690 } else {
4691 ZVAL_COPY_VALUE(&generator->retval, retval);
4692 }
4693 }
4694
4695 ZEND_OBSERVER_FCALL_END(generator->execute_data, &generator->retval);
4696
4697 EG(current_execute_data) = EX(prev_execute_data);
4698
4699 /* Close the generator to free up resources */
4700 zend_generator_close(generator, 1);
4701
4702 /* Pass execution back to handling code */
4703 ZEND_VM_RETURN();
4704 }
4705
4706 ZEND_VM_COLD_CONST_HANDLER(108, ZEND_THROW, CONST|TMPVAR|CV, ANY)
4707 {
4708 USE_OPLINE
4709 zval *value;
4710
4711 SAVE_OPLINE();
4712 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4713
4714 do {
4715 if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
4716 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
4717 value = Z_REFVAL_P(value);
4718 if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
4719 break;
4720 }
4721 }
4722 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
4723 ZVAL_UNDEFINED_OP1();
4724 if (UNEXPECTED(EG(exception) != NULL)) {
4725 HANDLE_EXCEPTION();
4726 }
4727 }
4728 zend_throw_error(NULL, "Can only throw objects");
4729 FREE_OP1();
4730 HANDLE_EXCEPTION();
4731 }
4732 } while (0);
4733
4734 zend_exception_save();
4735 Z_TRY_ADDREF_P(value);
4736 zend_throw_exception_object(value);
4737 zend_exception_restore();
4738 FREE_OP1();
4739 HANDLE_EXCEPTION();
4740 }
4741
4742 ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, JMP_ADDR, LAST_CATCH|CACHE_SLOT)
4743 {
4744 USE_OPLINE
4745 zend_class_entry *ce, *catch_ce;
4746 zend_object *exception;
4747
4748 SAVE_OPLINE();
4749 /* Check whether an exception has been thrown, if not, jump over code */
4750 zend_exception_restore();
4751 if (EG(exception) == NULL) {
4752 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
4753 }
4754 catch_ce = CACHED_PTR(opline->extended_value & ~ZEND_LAST_CATCH);
4755 if (UNEXPECTED(catch_ce == NULL)) {
4756 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);
4757
4758 CACHE_PTR(opline->extended_value & ~ZEND_LAST_CATCH, catch_ce);
4759 }
4760 ce = EG(exception)->ce;
4761
4762 #ifdef HAVE_DTRACE
4763 if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
4764 DTRACE_EXCEPTION_CAUGHT((char *)ce->name);
4765 }
4766 #endif /* HAVE_DTRACE */
4767
4768 if (ce != catch_ce) {
4769 if (!catch_ce || !instanceof_function(ce, catch_ce)) {
4770 if (opline->extended_value & ZEND_LAST_CATCH) {
4771 zend_rethrow_exception(execute_data);
4772 HANDLE_EXCEPTION();
4773 }
4774 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
4775 }
4776 }
4777
4778 exception = EG(exception);
4779 EG(exception) = NULL;
4780 if (RETURN_VALUE_USED(opline)) {
4781 /* Always perform a strict assignment. There is a reasonable expectation that if you
4782 * write "catch (Exception $e)" then $e will actually be instanceof Exception. As such,
4783 * we should not permit coercion to string here. */
4784 zval tmp;
4785 ZVAL_OBJ(&tmp, exception);
4786 zend_assign_to_variable(EX_VAR(opline->result.var), &tmp, IS_TMP_VAR, /* strict */ 1);
4787 } else {
4788 OBJ_RELEASE(exception);
4789 }
4790 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4791 }
4792
4793 ZEND_VM_HOT_HANDLER(65, ZEND_SEND_VAL, CONST|TMPVAR, CONST|UNUSED|NUM)
4794 {
4795 USE_OPLINE
4796 zval *value, *arg;
4797
4798 if (OP2_TYPE == IS_CONST) {
4799 SAVE_OPLINE();
4800 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4801 uint32_t arg_num;
4802 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4803 if (UNEXPECTED(!arg)) {
4804 FREE_OP1();
4805 HANDLE_EXCEPTION();
4806 }
4807 } else {
4808 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4809 }
4810
4811 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
4812 ZVAL_COPY_VALUE(arg, value);
4813 if (OP1_TYPE == IS_CONST) {
4814 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) {
4815 Z_ADDREF_P(arg);
4816 }
4817 }
4818 ZEND_VM_NEXT_OPCODE();
4819 }
4820
ZEND_VM_COLD_HELPER(zend_cannot_pass_by_ref_helper,ANY,ANY,uint32_t _arg_num,zval * _arg)4821 ZEND_VM_COLD_HELPER(zend_cannot_pass_by_ref_helper, ANY, ANY, uint32_t _arg_num, zval *_arg)
4822 {
4823 USE_OPLINE
4824
4825 SAVE_OPLINE();
4826
4827 zend_cannot_pass_by_reference(_arg_num);
4828 FREE_OP1();
4829 ZVAL_UNDEF(_arg);
4830 HANDLE_EXCEPTION();
4831 }
4832
4833 ZEND_VM_HOT_SEND_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
4834 {
4835 USE_OPLINE
4836 zval *value, *arg;
4837 uint32_t arg_num;
4838
4839 if (OP2_TYPE == IS_CONST) {
4840 SAVE_OPLINE();
4841 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4842 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4843 if (UNEXPECTED(!arg)) {
4844 FREE_OP1();
4845 HANDLE_EXCEPTION();
4846 }
4847 } else {
4848 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4849 arg_num = opline->op2.num;
4850 }
4851
4852 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
4853 if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4854 ZEND_VM_C_GOTO(send_val_by_ref);
4855 }
4856 } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4857 ZEND_VM_C_LABEL(send_val_by_ref):
4858 ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper, _arg_num, arg_num, _arg, arg);
4859 }
4860 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
4861 ZVAL_COPY_VALUE(arg, value);
4862 if (OP1_TYPE == IS_CONST) {
4863 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(arg))) {
4864 Z_ADDREF_P(arg);
4865 }
4866 }
4867 ZEND_VM_NEXT_OPCODE();
4868 }
4869
4870 ZEND_VM_HOT_HANDLER(117, ZEND_SEND_VAR, VAR|CV, CONST|UNUSED|NUM)
4871 {
4872 USE_OPLINE
4873 zval *varptr, *arg;
4874
4875 if (OP2_TYPE == IS_CONST) {
4876 SAVE_OPLINE();
4877 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4878 uint32_t arg_num;
4879 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4880 if (UNEXPECTED(!arg)) {
4881 FREE_OP1();
4882 HANDLE_EXCEPTION();
4883 }
4884 } else {
4885 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4886 }
4887
4888 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
4889 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
4890 SAVE_OPLINE();
4891 ZVAL_UNDEFINED_OP1();
4892 ZVAL_NULL(arg);
4893 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4894 }
4895
4896 if (OP1_TYPE == IS_CV) {
4897 ZVAL_COPY_DEREF(arg, varptr);
4898 } else /* if (OP1_TYPE == IS_VAR) */ {
4899 if (UNEXPECTED(Z_ISREF_P(varptr))) {
4900 zend_refcounted *ref = Z_COUNTED_P(varptr);
4901
4902 varptr = Z_REFVAL_P(varptr);
4903 ZVAL_COPY_VALUE(arg, varptr);
4904 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
4905 efree_size(ref, sizeof(zend_reference));
4906 } else if (Z_OPT_REFCOUNTED_P(arg)) {
4907 Z_ADDREF_P(arg);
4908 }
4909 } else {
4910 ZVAL_COPY_VALUE(arg, varptr);
4911 }
4912 }
4913
4914 ZEND_VM_NEXT_OPCODE();
4915 }
4916
4917 ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, CONST|UNUSED|NUM)
4918 {
4919 USE_OPLINE
4920 zval *varptr, *arg;
4921
4922 if (OP2_TYPE == IS_CONST) {
4923 SAVE_OPLINE();
4924 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4925 uint32_t arg_num;
4926 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4927 if (UNEXPECTED(!arg)) {
4928 FREE_OP1();
4929 HANDLE_EXCEPTION();
4930 }
4931 } else {
4932 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4933 }
4934
4935 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4936 ZVAL_COPY_VALUE(arg, varptr);
4937
4938 if (EXPECTED(Z_ISREF_P(varptr))) {
4939 ZEND_VM_NEXT_OPCODE();
4940 }
4941
4942 SAVE_OPLINE();
4943 ZVAL_NEW_REF(arg, arg);
4944 zend_error(E_NOTICE, "Only variables should be passed by reference");
4945 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4946 }
4947
4948 ZEND_VM_HOT_SEND_HANDLER(50, ZEND_SEND_VAR_NO_REF_EX, VAR, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
4949 {
4950 USE_OPLINE
4951 zval *varptr, *arg;
4952 uint32_t arg_num;
4953
4954 if (OP2_TYPE == IS_CONST) {
4955 SAVE_OPLINE();
4956 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
4957 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
4958 if (UNEXPECTED(!arg)) {
4959 FREE_OP1();
4960 HANDLE_EXCEPTION();
4961 }
4962 } else {
4963 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
4964 arg_num = opline->op2.num;
4965 }
4966
4967 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
4968 if (!QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4969 ZEND_VM_C_GOTO(send_var);
4970 }
4971
4972 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4973 ZVAL_COPY_VALUE(arg, varptr);
4974
4975 if (EXPECTED(Z_ISREF_P(varptr) ||
4976 QUICK_ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) {
4977 ZEND_VM_NEXT_OPCODE();
4978 }
4979 } else {
4980 if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
4981 ZEND_VM_C_GOTO(send_var);
4982 }
4983
4984 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4985 ZVAL_COPY_VALUE(arg, varptr);
4986
4987 if (EXPECTED(Z_ISREF_P(varptr) ||
4988 ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num))) {
4989 ZEND_VM_NEXT_OPCODE();
4990 }
4991 }
4992
4993 SAVE_OPLINE();
4994 ZVAL_NEW_REF(arg, arg);
4995 zend_error(E_NOTICE, "Only variables should be passed by reference");
4996 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
4997
4998 ZEND_VM_C_LABEL(send_var):
4999 varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
5000 if (UNEXPECTED(Z_ISREF_P(varptr))) {
5001 zend_refcounted *ref = Z_COUNTED_P(varptr);
5002
5003 varptr = Z_REFVAL_P(varptr);
5004 ZVAL_COPY_VALUE(arg, varptr);
5005 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
5006 efree_size(ref, sizeof(zend_reference));
5007 } else if (Z_OPT_REFCOUNTED_P(arg)) {
5008 Z_ADDREF_P(arg);
5009 }
5010 } else {
5011 ZVAL_COPY_VALUE(arg, varptr);
5012 }
5013 ZEND_VM_NEXT_OPCODE();
5014 }
5015
5016 ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, CONST|UNUSED|NUM)
5017 {
5018 USE_OPLINE
5019 zval *varptr, *arg;
5020
5021 SAVE_OPLINE();
5022 if (OP2_TYPE == IS_CONST) {
5023 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5024 uint32_t arg_num;
5025 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
5026 if (UNEXPECTED(!arg)) {
5027 FREE_OP1();
5028 HANDLE_EXCEPTION();
5029 }
5030 } else {
5031 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
5032 }
5033
5034 varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
5035 if (Z_ISREF_P(varptr)) {
5036 Z_ADDREF_P(varptr);
5037 } else {
5038 ZVAL_MAKE_REF_EX(varptr, 2);
5039 }
5040 ZVAL_REF(arg, Z_REF_P(varptr));
5041
5042 FREE_OP1();
5043 ZEND_VM_NEXT_OPCODE();
5044 }
5045
5046 ZEND_VM_HOT_SEND_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
5047 {
5048 USE_OPLINE
5049 zval *varptr, *arg;
5050 uint32_t arg_num;
5051
5052 if (OP2_TYPE == IS_CONST) {
5053 SAVE_OPLINE();
5054 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5055 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
5056 if (UNEXPECTED(!arg)) {
5057 FREE_OP1();
5058 HANDLE_EXCEPTION();
5059 }
5060 } else {
5061 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
5062 arg_num = opline->op2.num;
5063 }
5064
5065 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
5066 if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5067 ZEND_VM_C_GOTO(send_var_by_ref);
5068 }
5069 } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5070 ZEND_VM_C_LABEL(send_var_by_ref):
5071 varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
5072 if (Z_ISREF_P(varptr)) {
5073 Z_ADDREF_P(varptr);
5074 } else {
5075 ZVAL_MAKE_REF_EX(varptr, 2);
5076 }
5077 ZVAL_REF(arg, Z_REF_P(varptr));
5078
5079 FREE_OP1();
5080 ZEND_VM_NEXT_OPCODE();
5081 }
5082
5083 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5084 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) {
5085 SAVE_OPLINE();
5086 ZVAL_UNDEFINED_OP1();
5087 ZVAL_NULL(arg);
5088 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5089 }
5090
5091 if (OP1_TYPE == IS_CV) {
5092 ZVAL_COPY_DEREF(arg, varptr);
5093 } else /* if (OP1_TYPE == IS_VAR) */ {
5094 if (UNEXPECTED(Z_ISREF_P(varptr))) {
5095 zend_refcounted *ref = Z_COUNTED_P(varptr);
5096
5097 varptr = Z_REFVAL_P(varptr);
5098 ZVAL_COPY_VALUE(arg, varptr);
5099 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
5100 efree_size(ref, sizeof(zend_reference));
5101 } else if (Z_OPT_REFCOUNTED_P(arg)) {
5102 Z_ADDREF_P(arg);
5103 }
5104 } else {
5105 ZVAL_COPY_VALUE(arg, varptr);
5106 }
5107 }
5108
5109 ZEND_VM_NEXT_OPCODE();
5110 }
5111
5112 ZEND_VM_HOT_SEND_HANDLER(100, ZEND_CHECK_FUNC_ARG, UNUSED, CONST|UNUSED|NUM, SPEC(QUICK_ARG))
5113 {
5114 USE_OPLINE
5115 uint32_t arg_num;
5116
5117 if (OP2_TYPE == IS_CONST) {
5118 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5119 arg_num = zend_get_arg_offset_by_name(
5120 EX(call)->func, arg_name, CACHE_ADDR(opline->result.num)) + 1;
5121 if (UNEXPECTED(arg_num == 0)) {
5122 /* Treat this as a by-value argument, and throw an error during SEND. */
5123 ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5124 ZEND_VM_NEXT_OPCODE();
5125 }
5126 } else {
5127 arg_num = opline->op2.num;
5128 }
5129
5130 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
5131 if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5132 ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5133 } else {
5134 ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5135 }
5136 } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5137 ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5138 } else {
5139 ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5140 }
5141 ZEND_VM_NEXT_OPCODE();
5142 }
5143
5144 ZEND_VM_HOT_HANDLER(185, ZEND_SEND_FUNC_ARG, VAR, CONST|UNUSED|NUM)
5145 {
5146 USE_OPLINE
5147 zval *varptr, *arg;
5148
5149 if (OP2_TYPE == IS_CONST) {
5150 // TODO: Would it make sense to share the cache slot with CHECK_FUNC_ARG?
5151 SAVE_OPLINE();
5152 zend_string *arg_name = Z_STR_P(RT_CONSTANT(opline, opline->op2));
5153 uint32_t arg_num;
5154 arg = zend_handle_named_arg(&EX(call), arg_name, &arg_num, CACHE_ADDR(opline->result.num));
5155 if (UNEXPECTED(!arg)) {
5156 FREE_OP1();
5157 HANDLE_EXCEPTION();
5158 }
5159 } else {
5160 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
5161 }
5162
5163 if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
5164 varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
5165 if (Z_ISREF_P(varptr)) {
5166 Z_ADDREF_P(varptr);
5167 } else {
5168 ZVAL_MAKE_REF_EX(varptr, 2);
5169 }
5170 ZVAL_REF(arg, Z_REF_P(varptr));
5171
5172 FREE_OP1();
5173 ZEND_VM_NEXT_OPCODE();
5174 }
5175
5176 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5177
5178 if (UNEXPECTED(Z_ISREF_P(varptr))) {
5179 zend_refcounted *ref = Z_COUNTED_P(varptr);
5180
5181 varptr = Z_REFVAL_P(varptr);
5182 ZVAL_COPY_VALUE(arg, varptr);
5183 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
5184 efree_size(ref, sizeof(zend_reference));
5185 } else if (Z_OPT_REFCOUNTED_P(arg)) {
5186 Z_ADDREF_P(arg);
5187 }
5188 } else {
5189 ZVAL_COPY_VALUE(arg, varptr);
5190 }
5191
5192 ZEND_VM_NEXT_OPCODE();
5193 }
5194
5195 ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
5196 {
5197 USE_OPLINE
5198 zval *args;
5199 uint32_t arg_num;
5200
5201 SAVE_OPLINE();
5202 args = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5203 arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1;
5204
5205 ZEND_VM_C_LABEL(send_again):
5206 if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
5207 HashTable *ht = Z_ARRVAL_P(args);
5208 zval *arg, *top;
5209 zend_string *name;
5210 bool have_named_params = 0;
5211
5212 zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
5213
5214 // TODO: Speed this up using a flag that specifies whether there are any ref parameters.
5215 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_REFCOUNT_P(args) > 1) {
5216 uint32_t tmp_arg_num = arg_num;
5217 bool separate = 0;
5218
5219 /* check if any of arguments are going to be passed by reference */
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,name,arg)5220 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
5221 if (UNEXPECTED(name)) {
5222 void *cache_slot[2] = {NULL, NULL};
5223 tmp_arg_num = zend_get_arg_offset_by_name(
5224 EX(call)->func, name, cache_slot) + 1;
5225 }
5226 if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, tmp_arg_num)) {
5227 separate = 1;
5228 break;
5229 }
5230 tmp_arg_num++;
5231 } ZEND_HASH_FOREACH_END();
5232 if (separate) {
5233 SEPARATE_ARRAY(args);
5234 ht = Z_ARRVAL_P(args);
5235 }
5236 }
5237
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,name,arg)5238 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
5239 if (UNEXPECTED(name)) {
5240 void *cache_slot[2] = {NULL, NULL};
5241 have_named_params = 1;
5242 top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot);
5243 if (UNEXPECTED(!top)) {
5244 FREE_OP1();
5245 HANDLE_EXCEPTION();
5246 }
5247 } else {
5248 if (have_named_params) {
5249 zend_throw_error(NULL,
5250 "Cannot use positional argument after named argument during unpacking");
5251 FREE_OP1();
5252 HANDLE_EXCEPTION();
5253 }
5254
5255 top = ZEND_CALL_ARG(EX(call), arg_num);
5256 ZEND_CALL_NUM_ARGS(EX(call))++;
5257 }
5258
5259 if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5260 if (Z_ISREF_P(arg)) {
5261 Z_ADDREF_P(arg);
5262 ZVAL_REF(top, Z_REF_P(arg));
5263 } else if (OP1_TYPE & (IS_VAR|IS_CV)) {
5264 /* array is already separated above */
5265 ZVAL_MAKE_REF_EX(arg, 2);
5266 ZVAL_REF(top, Z_REF_P(arg));
5267 } else {
5268 Z_TRY_ADDREF_P(arg);
5269 ZVAL_NEW_REF(top, arg);
5270 }
5271 } else {
5272 ZVAL_COPY_DEREF(top, arg);
5273 }
5274
5275 arg_num++;
5276 } ZEND_HASH_FOREACH_END();
5277
5278 } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) {
5279 zend_class_entry *ce = Z_OBJCE_P(args);
5280 zend_object_iterator *iter;
5281 bool have_named_params = 0;
5282
5283 if (!ce || !ce->get_iterator) {
5284 zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(args));
5285 } else {
5286
5287 iter = ce->get_iterator(ce, args, 0);
5288 if (UNEXPECTED(!iter)) {
5289 FREE_OP1();
5290 if (!EG(exception)) {
5291 zend_throw_exception_ex(
5292 NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)
5293 );
5294 }
5295 HANDLE_EXCEPTION();
5296 }
5297
5298 const zend_object_iterator_funcs *funcs = iter->funcs;
5299 if (funcs->rewind) {
5300 funcs->rewind(iter);
5301 }
5302
5303 for (; funcs->valid(iter) == SUCCESS; ++arg_num) {
5304 zval *arg, *top;
5305
5306 if (UNEXPECTED(EG(exception) != NULL)) {
5307 break;
5308 }
5309
5310 arg = funcs->get_current_data(iter);
5311 if (UNEXPECTED(EG(exception) != NULL)) {
5312 break;
5313 }
5314
5315 zend_string *name = NULL;
5316 if (funcs->get_current_key) {
5317 zval key;
5318 funcs->get_current_key(iter, &key);
5319 if (UNEXPECTED(EG(exception) != NULL)) {
5320 break;
5321 }
5322
5323 if (UNEXPECTED(Z_TYPE(key) != IS_LONG)) {
5324 if (UNEXPECTED(Z_TYPE(key) != IS_STRING)) {
5325 zend_throw_error(NULL,
5326 "Keys must be of type int|string during argument unpacking");
5327 zval_ptr_dtor(&key);
5328 break;
5329 }
5330
5331 name = Z_STR_P(&key);
5332 }
5333 }
5334
5335 if (UNEXPECTED(name)) {
5336 void *cache_slot[2] = {NULL, NULL};
5337 have_named_params = 1;
5338 top = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot);
5339 if (UNEXPECTED(!top)) {
5340 zend_string_release(name);
5341 break;
5342 }
5343
5344 ZVAL_DEREF(arg);
5345 Z_TRY_ADDREF_P(arg);
5346
5347 if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5348 zend_error(
5349 E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
5350 " by unpacking a Traversable, passing by-value instead", arg_num,
5351 EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
5352 EX(call)->func->common.scope ? "::" : "",
5353 ZSTR_VAL(EX(call)->func->common.function_name)
5354 );
5355 ZVAL_NEW_REF(top, arg);
5356 } else {
5357 ZVAL_COPY_VALUE(top, arg);
5358 }
5359
5360 zend_string_release(name);
5361 } else {
5362 if (have_named_params) {
5363 zend_throw_error(NULL,
5364 "Cannot use positional argument after named argument during unpacking");
5365 break;
5366 }
5367
5368 zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1);
5369 top = ZEND_CALL_ARG(EX(call), arg_num);
5370 ZVAL_DEREF(arg);
5371 Z_TRY_ADDREF_P(arg);
5372
5373 if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5374 zend_error(
5375 E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
5376 " by unpacking a Traversable, passing by-value instead", arg_num,
5377 EX(call)->func->common.scope ? ZSTR_VAL(EX(call)->func->common.scope->name) : "",
5378 EX(call)->func->common.scope ? "::" : "",
5379 ZSTR_VAL(EX(call)->func->common.function_name)
5380 );
5381 ZVAL_NEW_REF(top, arg);
5382 } else {
5383 ZVAL_COPY_VALUE(top, arg);
5384 }
5385
5386 ZEND_CALL_NUM_ARGS(EX(call))++;
5387 }
5388
5389 funcs->move_forward(iter);
5390 }
5391
5392 zend_iterator_dtor(iter);
5393 }
5394 } else if (EXPECTED(Z_ISREF_P(args))) {
5395 args = Z_REFVAL_P(args);
5396 ZEND_VM_C_GOTO(send_again);
5397 } else {
5398 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) {
5399 ZVAL_UNDEFINED_OP1();
5400 }
5401 zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(args));
5402 }
5403
5404 FREE_OP1();
5405 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5406 }
5407
5408 ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY, NUM)
5409 {
5410 USE_OPLINE
5411 zval *args;
5412
5413 SAVE_OPLINE();
5414 args = GET_OP1_ZVAL_PTR(BP_VAR_R);
5415
5416 if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) {
5417 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(args)) {
5418 args = Z_REFVAL_P(args);
5419 if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
5420 ZEND_VM_C_GOTO(send_array);
5421 }
5422 }
5423 zend_type_error("call_user_func_array(): Argument #2 ($args) must be of type array, %s given", zend_zval_value_name(args));
5424 FREE_OP2();
5425 FREE_OP1();
5426 HANDLE_EXCEPTION();
5427 } else {
5428 uint32_t arg_num;
5429 HashTable *ht;
5430 zval *arg, *param;
5431
5432 ZEND_VM_C_LABEL(send_array):
5433 ht = Z_ARRVAL_P(args);
5434 if (OP2_TYPE != IS_UNUSED) {
5435 /* We don't need to handle named params in this case,
5436 * because array_slice() is called with $preserve_keys == false. */
5437 zval *op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
5438 uint32_t skip = opline->extended_value;
5439 uint32_t count = zend_hash_num_elements(ht);
5440 zend_long len;
5441 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
5442 len = Z_LVAL_P(op2);
5443 } else if (Z_TYPE_P(op2) == IS_NULL) {
5444 len = count - skip;
5445 } else if (EX_USES_STRICT_TYPES()
5446 || !zend_parse_arg_long_weak(op2, &len, /* arg_num */ 3)) {
5447 zend_type_error(
5448 "array_slice(): Argument #3 ($length) must be of type ?int, %s given",
5449 zend_zval_value_name(op2));
5450 FREE_OP2();
5451 FREE_OP1();
5452 HANDLE_EXCEPTION();
5453 }
5454
5455 if (len < 0) {
5456 len += (zend_long)(count - skip);
5457 }
5458 if (skip < count && len > 0) {
5459 if (len > (zend_long)(count - skip)) {
5460 len = (zend_long)(count - skip);
5461 }
5462 zend_vm_stack_extend_call_frame(&EX(call), 0, len);
5463 arg_num = 1;
5464 param = ZEND_CALL_ARG(EX(call), 1);
ZEND_HASH_FOREACH_VAL(ht,arg)5465 ZEND_HASH_FOREACH_VAL(ht, arg) {
5466 bool must_wrap = 0;
5467 if (skip > 0) {
5468 skip--;
5469 continue;
5470 } else if ((zend_long)(arg_num - 1) >= len) {
5471 break;
5472 } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5473 if (UNEXPECTED(!Z_ISREF_P(arg))) {
5474 if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5475 /* By-value send is not allowed -- emit a warning,
5476 * but still perform the call. */
5477 zend_param_must_be_ref(EX(call)->func, arg_num);
5478 must_wrap = 1;
5479 }
5480 }
5481 } else {
5482 if (Z_ISREF_P(arg) &&
5483 !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
5484 /* don't separate references for __call */
5485 arg = Z_REFVAL_P(arg);
5486 }
5487 }
5488 if (EXPECTED(!must_wrap)) {
5489 ZVAL_COPY(param, arg);
5490 } else {
5491 Z_TRY_ADDREF_P(arg);
5492 ZVAL_NEW_REF(param, arg);
5493 }
5494 ZEND_CALL_NUM_ARGS(EX(call))++;
5495 arg_num++;
5496 param++;
5497 } ZEND_HASH_FOREACH_END();
5498 }
5499 FREE_OP2();
5500 } else {
5501 zend_string *name;
5502 bool have_named_params;
5503 zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht));
5504 arg_num = 1;
5505 param = ZEND_CALL_ARG(EX(call), 1);
5506 have_named_params = 0;
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,name,arg)5507 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
5508 if (name) {
5509 void *cache_slot[2] = {NULL, NULL};
5510 have_named_params = 1;
5511 param = zend_handle_named_arg(&EX(call), name, &arg_num, cache_slot);
5512 if (!param) {
5513 FREE_OP1();
5514 HANDLE_EXCEPTION();
5515 }
5516 } else if (have_named_params) {
5517 zend_throw_error(NULL,
5518 "Cannot use positional argument after named argument");
5519 FREE_OP1();
5520 HANDLE_EXCEPTION();
5521 }
5522
5523 bool must_wrap = 0;
5524 if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5525 if (UNEXPECTED(!Z_ISREF_P(arg))) {
5526 if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5527 /* By-value send is not allowed -- emit a warning,
5528 * but still perform the call. */
5529 zend_param_must_be_ref(EX(call)->func, arg_num);
5530 must_wrap = 1;
5531 }
5532 }
5533 } else {
5534 if (Z_ISREF_P(arg) &&
5535 !(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
5536 /* don't separate references for __call */
5537 arg = Z_REFVAL_P(arg);
5538 }
5539 }
5540
5541 if (EXPECTED(!must_wrap)) {
5542 ZVAL_COPY(param, arg);
5543 } else {
5544 Z_TRY_ADDREF_P(arg);
5545 ZVAL_NEW_REF(param, arg);
5546 }
5547 if (!name) {
5548 ZEND_CALL_NUM_ARGS(EX(call))++;
5549 arg_num++;
5550 param++;
5551 }
5552 } ZEND_HASH_FOREACH_END();
5553 }
5554 }
5555 FREE_OP1();
5556 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5557 }
5558
5559 ZEND_VM_HANDLER(120, ZEND_SEND_USER, CONST|TMP|VAR|CV, NUM)
5560 {
5561 USE_OPLINE
5562 zval *arg, *param;
5563
5564 SAVE_OPLINE();
5565
5566 arg = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
5567 param = ZEND_CALL_VAR(EX(call), opline->result.var);
5568 if (UNEXPECTED(ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num))) {
5569 zend_param_must_be_ref(EX(call)->func, opline->op2.num);
5570 Z_TRY_ADDREF_P(arg);
5571 ZVAL_NEW_REF(param, arg);
5572 } else {
5573 ZVAL_COPY(param, arg);
5574 }
5575
5576 FREE_OP1();
5577 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5578 }
5579
5580 ZEND_VM_HOT_HANDLER(199, ZEND_CHECK_UNDEF_ARGS, UNUSED, UNUSED)
5581 {
5582 USE_OPLINE
5583
5584 zend_execute_data *call = execute_data->call;
5585 if (EXPECTED(!(ZEND_CALL_INFO(call) & ZEND_CALL_MAY_HAVE_UNDEF))) {
5586 ZEND_VM_NEXT_OPCODE();
5587 }
5588
5589 SAVE_OPLINE();
5590 zend_handle_undef_args(call);
5591 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5592 }
5593
ZEND_VM_COLD_HELPER(zend_missing_arg_helper,ANY,ANY)5594 ZEND_VM_COLD_HELPER(zend_missing_arg_helper, ANY, ANY)
5595 {
5596 #ifdef ZEND_VM_IP_GLOBAL_REG
5597 USE_OPLINE
5598
5599 SAVE_OPLINE();
5600 #endif
5601 zend_missing_arg_error(execute_data);
5602 HANDLE_EXCEPTION();
5603 }
5604
ZEND_VM_HELPER(zend_verify_recv_arg_type_helper,ANY,ANY,zval * op_1)5605 ZEND_VM_HELPER(zend_verify_recv_arg_type_helper, ANY, ANY, zval *op_1)
5606 {
5607 USE_OPLINE
5608
5609 SAVE_OPLINE();
5610 if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), opline->op1.num, op_1, CACHE_ADDR(opline->extended_value)))) {
5611 HANDLE_EXCEPTION();
5612 }
5613
5614 ZEND_VM_NEXT_OPCODE();
5615 }
5616
5617 ZEND_VM_HOT_HANDLER(63, ZEND_RECV, NUM, UNUSED, CACHE_SLOT)
5618 {
5619 USE_OPLINE
5620 uint32_t arg_num = opline->op1.num;
5621 zval *param;
5622
5623 if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
5624 ZEND_VM_DISPATCH_TO_HELPER(zend_missing_arg_helper);
5625 }
5626
5627 param = EX_VAR(opline->result.var);
5628
5629 if (UNEXPECTED(!(opline->op2.num & (1u << Z_TYPE_P(param))))) {
5630 ZEND_VM_DISPATCH_TO_HELPER(zend_verify_recv_arg_type_helper, op_1, param);
5631 }
5632
5633 ZEND_VM_NEXT_OPCODE();
5634 }
5635
5636 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_RECV, op->op2.num == MAY_BE_ANY, ZEND_RECV_NOTYPE, NUM, NUM, CACHE_SLOT)
5637 {
5638 USE_OPLINE
5639 uint32_t arg_num = opline->op1.num;
5640
5641 if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
5642 ZEND_VM_DISPATCH_TO_HELPER(zend_missing_arg_helper);
5643 }
5644
5645 ZEND_VM_NEXT_OPCODE();
5646 }
5647
5648 ZEND_VM_HOT_HANDLER(64, ZEND_RECV_INIT, NUM, CONST, CACHE_SLOT)
5649 {
5650 USE_OPLINE
5651 uint32_t arg_num;
5652 zval *param;
5653
5654 ZEND_VM_REPEATABLE_OPCODE
5655
5656 arg_num = opline->op1.num;
5657 param = EX_VAR(opline->result.var);
5658 if (arg_num > EX_NUM_ARGS()) {
5659 zval *default_value = RT_CONSTANT(opline, opline->op2);
5660
5661 if (Z_OPT_TYPE_P(default_value) == IS_CONSTANT_AST) {
5662 zval *cache_val = (zval*)CACHE_ADDR(Z_CACHE_SLOT_P(default_value));
5663
5664 /* we keep in cache only not refcounted values */
5665 if (Z_TYPE_P(cache_val) != IS_UNDEF) {
5666 ZVAL_COPY_VALUE(param, cache_val);
5667 } else {
5668 SAVE_OPLINE();
5669 ZVAL_COPY(param, default_value);
5670 zend_ast_evaluate_ctx ctx = {0};
5671 if (UNEXPECTED(zval_update_constant_with_ctx(param, EX(func)->op_array.scope, &ctx) != SUCCESS)) {
5672 zval_ptr_dtor_nogc(param);
5673 ZVAL_UNDEF(param);
5674 HANDLE_EXCEPTION();
5675 }
5676 if (!Z_REFCOUNTED_P(param) && !ctx.had_side_effects) {
5677 ZVAL_COPY_VALUE(cache_val, param);
5678 }
5679 }
5680 ZEND_VM_C_GOTO(recv_init_check_type);
5681 } else {
5682 ZVAL_COPY(param, default_value);
5683 }
5684 } else {
5685 ZEND_VM_C_LABEL(recv_init_check_type):
5686 if ((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
5687 SAVE_OPLINE();
5688 if (UNEXPECTED(!zend_verify_recv_arg_type(EX(func), arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5689 HANDLE_EXCEPTION();
5690 }
5691 }
5692 }
5693
5694 ZEND_VM_REPEAT_OPCODE(ZEND_RECV_INIT);
5695 ZEND_VM_NEXT_OPCODE();
5696 }
5697
5698 ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, UNUSED, CACHE_SLOT)
5699 {
5700 USE_OPLINE
5701 uint32_t arg_num = opline->op1.num;
5702 uint32_t arg_count = EX_NUM_ARGS();
5703 zval *params;
5704
5705 SAVE_OPLINE();
5706
5707 params = EX_VAR(opline->result.var);
5708
5709 if (arg_num <= arg_count) {
5710 ZEND_ASSERT(EX(func)->common.fn_flags & ZEND_ACC_VARIADIC);
5711 ZEND_ASSERT(EX(func)->common.num_args == arg_num - 1);
5712 zend_arg_info *arg_info = &EX(func)->common.arg_info[arg_num - 1];
5713
5714 array_init_size(params, arg_count - arg_num + 1);
5715 zend_hash_real_init_packed(Z_ARRVAL_P(params));
ZEND_HASH_FILL_PACKED(Z_ARRVAL_P (params))5716 ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) {
5717 zval *param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
5718 if (ZEND_TYPE_IS_SET(arg_info->type)) {
5719 ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
5720 do {
5721 if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5722 ZEND_HASH_FILL_FINISH();
5723 HANDLE_EXCEPTION();
5724 }
5725
5726 if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
5727 ZEND_HASH_FILL_ADD(param);
5728 param++;
5729 } while (++arg_num <= arg_count);
5730 } else {
5731 do {
5732 if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
5733 ZEND_HASH_FILL_ADD(param);
5734 param++;
5735 } while (++arg_num <= arg_count);
5736 }
5737 } ZEND_HASH_FILL_END();
5738 } else {
5739 ZVAL_EMPTY_ARRAY(params);
5740 }
5741
5742 if (EX_CALL_INFO() & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS) {
5743 zend_string *name;
5744 zval *param;
5745 zend_arg_info *arg_info = &EX(func)->common.arg_info[EX(func)->common.num_args];
5746 if (ZEND_TYPE_IS_SET(arg_info->type)) {
5747 SEPARATE_ARRAY(params);
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX (extra_named_params),name,param)5748 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) {
5749 if (UNEXPECTED(!zend_verify_variadic_arg_type(EX(func), arg_info, arg_num, param, CACHE_ADDR(opline->extended_value)))) {
5750 HANDLE_EXCEPTION();
5751 }
5752 Z_TRY_ADDREF_P(param);
5753 zend_hash_add_new(Z_ARRVAL_P(params), name, param);
5754 } ZEND_HASH_FOREACH_END();
5755 } else if (zend_hash_num_elements(Z_ARRVAL_P(params)) == 0) {
5756 GC_ADDREF(EX(extra_named_params));
5757 ZVAL_ARR(params, EX(extra_named_params));
5758 } else {
5759 SEPARATE_ARRAY(params);
ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX (extra_named_params),name,param)5760 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(EX(extra_named_params), name, param) {
5761 Z_TRY_ADDREF_P(param);
5762 zend_hash_add_new(Z_ARRVAL_P(params), name, param);
5763 } ZEND_HASH_FOREACH_END();
5764 }
5765 }
5766
5767 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5768 }
5769
5770 ZEND_VM_COLD_CONST_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
5771 {
5772 USE_OPLINE
5773 zval *val;
5774
5775 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5776 if (Z_TYPE_INFO_P(val) == IS_TRUE) {
5777 ZVAL_TRUE(EX_VAR(opline->result.var));
5778 } else if (EXPECTED(Z_TYPE_INFO_P(val) <= IS_TRUE)) {
5779 /* The result and op1 can be the same cv zval */
5780 const uint32_t orig_val_type = Z_TYPE_INFO_P(val);
5781 ZVAL_FALSE(EX_VAR(opline->result.var));
5782 if (OP1_TYPE == IS_CV && UNEXPECTED(orig_val_type == IS_UNDEF)) {
5783 SAVE_OPLINE();
5784 ZVAL_UNDEFINED_OP1();
5785 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5786 }
5787 } else {
5788 SAVE_OPLINE();
5789 ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val));
5790 FREE_OP1();
5791 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5792 }
5793 ZEND_VM_NEXT_OPCODE();
5794 }
5795
ZEND_VM_HELPER(zend_case_helper,ANY,ANY,zval * op_1,zval * op_2)5796 ZEND_VM_HELPER(zend_case_helper, ANY, ANY, zval *op_1, zval *op_2)
5797 {
5798 int ret;
5799 USE_OPLINE
5800
5801 SAVE_OPLINE();
5802 if (UNEXPECTED(Z_TYPE_INFO_P(op_1) == IS_UNDEF)) {
5803 op_1 = ZVAL_UNDEFINED_OP1();
5804 }
5805 if (UNEXPECTED(Z_TYPE_INFO_P(op_2) == IS_UNDEF)) {
5806 op_2 = ZVAL_UNDEFINED_OP2();
5807 }
5808 ret = zend_compare(op_1, op_2);
5809 if (OP2_TYPE & (IS_TMP_VAR|IS_VAR)) {
5810 zval_ptr_dtor_nogc(op_2);
5811 }
5812 ZEND_VM_SMART_BRANCH(ret == 0, 1);
5813 }
5814
5815 ZEND_VM_HANDLER(48, ZEND_CASE, TMPVAR, CONST|TMPVAR|CV)
5816 {
5817 USE_OPLINE
5818 zval *op1, *op2;
5819 double d1, d2;
5820
5821 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
5822 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
5823 if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
5824 if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
5825 if (EXPECTED(Z_LVAL_P(op1) == Z_LVAL_P(op2))) {
5826 ZEND_VM_C_LABEL(case_true):
5827 ZEND_VM_SMART_BRANCH_TRUE();
5828 } else {
5829 ZEND_VM_C_LABEL(case_false):
5830 ZEND_VM_SMART_BRANCH_FALSE();
5831 }
5832 } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
5833 d1 = (double)Z_LVAL_P(op1);
5834 d2 = Z_DVAL_P(op2);
5835 ZEND_VM_C_GOTO(case_double);
5836 }
5837 } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
5838 if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
5839 d1 = Z_DVAL_P(op1);
5840 d2 = Z_DVAL_P(op2);
5841 ZEND_VM_C_LABEL(case_double):
5842 if (d1 == d2) {
5843 ZEND_VM_C_GOTO(case_true);
5844 } else {
5845 ZEND_VM_C_GOTO(case_false);
5846 }
5847 } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
5848 d1 = Z_DVAL_P(op1);
5849 d2 = (double)Z_LVAL_P(op2);
5850 ZEND_VM_C_GOTO(case_double);
5851 }
5852 } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
5853 if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
5854 bool result = zend_fast_equal_strings(Z_STR_P(op1), Z_STR_P(op2));
5855 FREE_OP2();
5856 if (result) {
5857 ZEND_VM_C_GOTO(case_true);
5858 } else {
5859 ZEND_VM_C_GOTO(case_false);
5860 }
5861 }
5862 }
5863 ZEND_VM_DISPATCH_TO_HELPER(zend_case_helper, op_1, op1, op_2, op2);
5864 }
5865
5866 ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, UNUSED|CACHE_SLOT, NUM)
5867 {
5868 USE_OPLINE
5869 zval *result;
5870 zend_function *constructor;
5871 zend_class_entry *ce;
5872 zend_execute_data *call;
5873
5874 SAVE_OPLINE();
5875 if (OP1_TYPE == IS_CONST) {
5876 ce = CACHED_PTR(opline->op2.num);
5877 if (UNEXPECTED(ce == NULL)) {
5878 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);
5879 if (UNEXPECTED(ce == NULL)) {
5880 ZVAL_UNDEF(EX_VAR(opline->result.var));
5881 HANDLE_EXCEPTION();
5882 }
5883 CACHE_PTR(opline->op2.num, ce);
5884 }
5885 } else if (OP1_TYPE == IS_UNUSED) {
5886 ce = zend_fetch_class(NULL, opline->op1.num);
5887 if (UNEXPECTED(ce == NULL)) {
5888 ZVAL_UNDEF(EX_VAR(opline->result.var));
5889 HANDLE_EXCEPTION();
5890 }
5891 } else {
5892 ce = Z_CE_P(EX_VAR(opline->op1.var));
5893 }
5894
5895 result = EX_VAR(opline->result.var);
5896 if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) {
5897 ZVAL_UNDEF(result);
5898 HANDLE_EXCEPTION();
5899 }
5900
5901 constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result));
5902 if (constructor == NULL) {
5903 if (UNEXPECTED(EG(exception))) {
5904 HANDLE_EXCEPTION();
5905 }
5906
5907 /* If there are no arguments, skip over the DO_FCALL opcode. We check if the next
5908 * opcode is DO_FCALL in case EXT instructions are used. */
5909 if (EXPECTED(opline->extended_value == 0 && (opline+1)->opcode == ZEND_DO_FCALL)) {
5910 ZEND_VM_NEXT_OPCODE_EX(1, 2);
5911 }
5912
5913 /* Perform a dummy function call */
5914 call = zend_vm_stack_push_call_frame(
5915 ZEND_CALL_FUNCTION, (zend_function *) &zend_pass_function,
5916 opline->extended_value, NULL);
5917 } else {
5918 if (EXPECTED(constructor->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&constructor->op_array))) {
5919 init_func_run_time_cache(&constructor->op_array);
5920 }
5921 /* We are not handling overloaded classes right now */
5922 call = zend_vm_stack_push_call_frame(
5923 ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_THIS,
5924 constructor,
5925 opline->extended_value,
5926 Z_OBJ_P(result));
5927 Z_ADDREF_P(result);
5928 }
5929
5930 call->prev_execute_data = EX(call);
5931 EX(call) = call;
5932 ZEND_VM_NEXT_OPCODE();
5933 }
5934
5935 ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
5936 {
5937 USE_OPLINE
5938 zval *obj;
5939 zend_object *zobj;
5940 zend_class_entry *ce, *scope;
5941 zend_function *clone;
5942 zend_object_clone_obj_t clone_call;
5943
5944 SAVE_OPLINE();
5945 obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
5946
5947 do {
5948 if (OP1_TYPE == IS_CONST ||
5949 (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
5950 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
5951 obj = Z_REFVAL_P(obj);
5952 if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
5953 break;
5954 }
5955 }
5956 ZVAL_UNDEF(EX_VAR(opline->result.var));
5957 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
5958 ZVAL_UNDEFINED_OP1();
5959 if (UNEXPECTED(EG(exception) != NULL)) {
5960 HANDLE_EXCEPTION();
5961 }
5962 }
5963 zend_throw_error(NULL, "__clone method called on non-object");
5964 FREE_OP1();
5965 HANDLE_EXCEPTION();
5966 }
5967 } while (0);
5968
5969 zobj = Z_OBJ_P(obj);
5970 ce = zobj->ce;
5971 clone = ce->clone;
5972 clone_call = zobj->handlers->clone_obj;
5973 if (UNEXPECTED(clone_call == NULL)) {
5974 zend_throw_error(NULL, "Trying to clone an uncloneable object of class %s", ZSTR_VAL(ce->name));
5975 FREE_OP1();
5976 ZVAL_UNDEF(EX_VAR(opline->result.var));
5977 HANDLE_EXCEPTION();
5978 }
5979
5980 if (clone && !(clone->common.fn_flags & ZEND_ACC_PUBLIC)) {
5981 scope = EX(func)->op_array.scope;
5982 if (clone->common.scope != scope) {
5983 if (UNEXPECTED(clone->common.fn_flags & ZEND_ACC_PRIVATE)
5984 || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), scope))) {
5985 zend_wrong_clone_call(clone, scope);
5986 FREE_OP1();
5987 ZVAL_UNDEF(EX_VAR(opline->result.var));
5988 HANDLE_EXCEPTION();
5989 }
5990 }
5991 }
5992
5993 ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(zobj));
5994
5995 FREE_OP1();
5996 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
5997 }
5998
5999 ZEND_VM_HOT_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED|CONST_FETCH, CONST, CACHE_SLOT)
6000 {
6001 USE_OPLINE
6002 zend_constant *c;
6003
6004 c = CACHED_PTR(opline->extended_value);
6005 if (EXPECTED(c != NULL) && EXPECTED(!IS_SPECIAL_CACHE_VAL(c))) {
6006 ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
6007 ZEND_VM_NEXT_OPCODE();
6008 }
6009
6010 SAVE_OPLINE();
6011 zend_quick_get_constant(RT_CONSTANT(opline, opline->op2) + 1, opline->op1.num OPLINE_CC EXECUTE_DATA_CC);
6012 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6013 }
6014
6015 ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED|CLASS_FETCH, CONST|TMPVARCV, CACHE_SLOT)
6016 {
6017 zend_class_entry *ce, *scope;
6018 zend_class_constant *c;
6019 zval *value, *zv, *constant_zv;
6020 zend_string *constant_name;
6021 USE_OPLINE
6022
6023 SAVE_OPLINE();
6024
6025 do {
6026 if (OP1_TYPE == IS_CONST && OP2_TYPE == IS_CONST) {
6027 if (EXPECTED(CACHED_PTR(opline->extended_value + sizeof(void*)))) {
6028 value = CACHED_PTR(opline->extended_value + sizeof(void*));
6029 break;
6030 }
6031 }
6032 if (OP1_TYPE == IS_CONST) {
6033 if (EXPECTED(CACHED_PTR(opline->extended_value))) {
6034 ce = CACHED_PTR(opline->extended_value);
6035 } else {
6036 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);
6037 if (UNEXPECTED(ce == NULL)) {
6038 ZVAL_UNDEF(EX_VAR(opline->result.var));
6039 FREE_OP2();
6040 HANDLE_EXCEPTION();
6041 }
6042 CACHE_PTR(opline->extended_value, ce);
6043 }
6044 } else if (OP1_TYPE == IS_UNUSED) {
6045 ce = zend_fetch_class(NULL, opline->op1.num);
6046 if (UNEXPECTED(ce == NULL)) {
6047 ZVAL_UNDEF(EX_VAR(opline->result.var));
6048 FREE_OP2();
6049 HANDLE_EXCEPTION();
6050 }
6051 } else {
6052 ce = Z_CE_P(EX_VAR(opline->op1.var));
6053 }
6054 if (OP1_TYPE != IS_CONST
6055 && OP2_TYPE == IS_CONST
6056 && EXPECTED(CACHED_PTR(opline->extended_value) == ce)) {
6057 value = CACHED_PTR(opline->extended_value + sizeof(void*));
6058 break;
6059 }
6060
6061 constant_zv = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
6062 if (UNEXPECTED(Z_TYPE_P(constant_zv) != IS_STRING)) {
6063 zend_invalid_class_constant_type_error(Z_TYPE_P(constant_zv));
6064 ZVAL_UNDEF(EX_VAR(opline->result.var));
6065 FREE_OP2();
6066 HANDLE_EXCEPTION();
6067 }
6068 constant_name = Z_STR_P(constant_zv);
6069 /* Magic 'class' for constant OP2 is caught at compile-time */
6070 if (OP2_TYPE != IS_CONST && UNEXPECTED(zend_string_equals_literal_ci(constant_name, "class"))) {
6071 ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
6072 FREE_OP2();
6073 ZEND_VM_NEXT_OPCODE();
6074 }
6075 zv = OP2_TYPE == IS_CONST
6076 ? zend_hash_find_known_hash(CE_CONSTANTS_TABLE(ce), constant_name)
6077 : zend_hash_find(CE_CONSTANTS_TABLE(ce), constant_name);
6078
6079 if (EXPECTED(zv != NULL)) {
6080 c = Z_PTR_P(zv);
6081 scope = EX(func)->op_array.scope;
6082 if (!zend_verify_const_access(c, scope)) {
6083 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));
6084 ZVAL_UNDEF(EX_VAR(opline->result.var));
6085 FREE_OP2();
6086 HANDLE_EXCEPTION();
6087 }
6088
6089 if (ce->ce_flags & ZEND_ACC_TRAIT) {
6090 zend_throw_error(NULL, "Cannot access trait constant %s::%s directly", ZSTR_VAL(ce->name), ZSTR_VAL(constant_name));
6091 ZVAL_UNDEF(EX_VAR(opline->result.var));
6092 FREE_OP2();
6093 HANDLE_EXCEPTION();
6094 }
6095
6096 bool is_constant_deprecated = ZEND_CLASS_CONST_FLAGS(c) & ZEND_ACC_DEPRECATED;
6097 if (UNEXPECTED(is_constant_deprecated)) {
6098 zend_deprecated_class_constant(c, constant_name);
6099
6100 if (EG(exception)) {
6101 ZVAL_UNDEF(EX_VAR(opline->result.var));
6102 FREE_OP2();
6103 HANDLE_EXCEPTION();
6104 }
6105 }
6106
6107 value = &c->value;
6108 // Enums require loading of all class constants to build the backed enum table
6109 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)) {
6110 if (UNEXPECTED(zend_update_class_constants(ce) == FAILURE)) {
6111 ZVAL_UNDEF(EX_VAR(opline->result.var));
6112 FREE_OP2();
6113 HANDLE_EXCEPTION();
6114 }
6115 }
6116 if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
6117 if (UNEXPECTED(zend_update_class_constant(c, constant_name, c->ce) != SUCCESS)) {
6118 ZVAL_UNDEF(EX_VAR(opline->result.var));
6119 FREE_OP2();
6120 HANDLE_EXCEPTION();
6121 }
6122 }
6123 if (OP2_TYPE == IS_CONST && !is_constant_deprecated) {
6124 CACHE_POLYMORPHIC_PTR(opline->extended_value, ce, value);
6125 }
6126 } else {
6127 zend_throw_error(NULL, "Undefined constant %s::%s",
6128 ZSTR_VAL(ce->name), ZSTR_VAL(constant_name));
6129 ZVAL_UNDEF(EX_VAR(opline->result.var));
6130 FREE_OP2();
6131 HANDLE_EXCEPTION();
6132 }
6133 } while (0);
6134
6135 ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), value);
6136
6137 FREE_OP2();
6138 ZEND_VM_NEXT_OPCODE();
6139 }
6140
6141 ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, REF)
6142 {
6143 USE_OPLINE
6144 zval *expr_ptr, new_expr;
6145
6146 SAVE_OPLINE();
6147 if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) &&
6148 UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
6149 expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
6150 if (Z_ISREF_P(expr_ptr)) {
6151 Z_ADDREF_P(expr_ptr);
6152 } else {
6153 ZVAL_MAKE_REF_EX(expr_ptr, 2);
6154 }
6155 FREE_OP1();
6156 } else {
6157 expr_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
6158 if (OP1_TYPE == IS_TMP_VAR) {
6159 /* pass */
6160 } else if (OP1_TYPE == IS_CONST) {
6161 Z_TRY_ADDREF_P(expr_ptr);
6162 } else if (OP1_TYPE == IS_CV) {
6163 ZVAL_DEREF(expr_ptr);
6164 Z_TRY_ADDREF_P(expr_ptr);
6165 } else /* if (OP1_TYPE == IS_VAR) */ {
6166 if (UNEXPECTED(Z_ISREF_P(expr_ptr))) {
6167 zend_refcounted *ref = Z_COUNTED_P(expr_ptr);
6168
6169 expr_ptr = Z_REFVAL_P(expr_ptr);
6170 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
6171 ZVAL_COPY_VALUE(&new_expr, expr_ptr);
6172 expr_ptr = &new_expr;
6173 efree_size(ref, sizeof(zend_reference));
6174 } else if (Z_OPT_REFCOUNTED_P(expr_ptr)) {
6175 Z_ADDREF_P(expr_ptr);
6176 }
6177 }
6178 }
6179 }
6180
6181 if (OP2_TYPE != IS_UNUSED) {
6182 zval *offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
6183 zend_string *str;
6184 zend_ulong hval;
6185
6186 ZEND_VM_C_LABEL(add_again):
6187 if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
6188 str = Z_STR_P(offset);
6189 if (OP2_TYPE != IS_CONST) {
6190 if (ZEND_HANDLE_NUMERIC(str, hval)) {
6191 ZEND_VM_C_GOTO(num_index);
6192 }
6193 }
6194 ZEND_VM_C_LABEL(str_index):
6195 zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
6196 } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
6197 hval = Z_LVAL_P(offset);
6198 ZEND_VM_C_LABEL(num_index):
6199 zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
6200 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
6201 offset = Z_REFVAL_P(offset);
6202 ZEND_VM_C_GOTO(add_again);
6203 } else if (Z_TYPE_P(offset) == IS_NULL) {
6204 str = ZSTR_EMPTY_ALLOC();
6205 ZEND_VM_C_GOTO(str_index);
6206 } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
6207 hval = zend_dval_to_lval_safe(Z_DVAL_P(offset));
6208 ZEND_VM_C_GOTO(num_index);
6209 } else if (Z_TYPE_P(offset) == IS_FALSE) {
6210 hval = 0;
6211 ZEND_VM_C_GOTO(num_index);
6212 } else if (Z_TYPE_P(offset) == IS_TRUE) {
6213 hval = 1;
6214 ZEND_VM_C_GOTO(num_index);
6215 } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
6216 zend_use_resource_as_offset(offset);
6217 hval = Z_RES_HANDLE_P(offset);
6218 ZEND_VM_C_GOTO(num_index);
6219 } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
6220 ZVAL_UNDEFINED_OP2();
6221 str = ZSTR_EMPTY_ALLOC();
6222 ZEND_VM_C_GOTO(str_index);
6223 } else {
6224 zend_illegal_array_offset_access(offset);
6225 zval_ptr_dtor_nogc(expr_ptr);
6226 }
6227 FREE_OP2();
6228 } else {
6229 if (!zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr)) {
6230 zend_cannot_add_element();
6231 zval_ptr_dtor_nogc(expr_ptr);
6232 }
6233 }
6234 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6235 }
6236
6237 ZEND_VM_HANDLER(147, ZEND_ADD_ARRAY_UNPACK, ANY, ANY)
6238 {
6239 USE_OPLINE
6240 zval *op1;
6241 HashTable *result_ht;
6242
6243 SAVE_OPLINE();
6244 op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
6245 result_ht = Z_ARRVAL_P(EX_VAR(opline->result.var));
6246
6247 ZEND_VM_C_LABEL(add_unpack_again):
6248 if (EXPECTED(Z_TYPE_P(op1) == IS_ARRAY)) {
6249 HashTable *ht = Z_ARRVAL_P(op1);
6250 zval *val;
6251
6252 if (HT_IS_PACKED(ht) && (zend_hash_num_elements(result_ht) == 0 || HT_IS_PACKED(result_ht))) {
6253 zend_hash_extend(result_ht, result_ht->nNumUsed + zend_hash_num_elements(ht), 1);
ZEND_HASH_FILL_PACKED(result_ht)6254 ZEND_HASH_FILL_PACKED(result_ht) {
6255 ZEND_HASH_PACKED_FOREACH_VAL(ht, val) {
6256 if (UNEXPECTED(Z_ISREF_P(val)) &&
6257 UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
6258 val = Z_REFVAL_P(val);
6259 }
6260 Z_TRY_ADDREF_P(val);
6261 ZEND_HASH_FILL_ADD(val);
6262 } ZEND_HASH_FOREACH_END();
6263 } ZEND_HASH_FILL_END();
6264 } else {
6265 zend_string *key;
6266
ZEND_HASH_FOREACH_STR_KEY_VAL(ht,key,val)6267 ZEND_HASH_FOREACH_STR_KEY_VAL(ht, key, val) {
6268 if (UNEXPECTED(Z_ISREF_P(val)) &&
6269 UNEXPECTED(Z_REFCOUNT_P(val) == 1)) {
6270 val = Z_REFVAL_P(val);
6271 }
6272 Z_TRY_ADDREF_P(val);
6273 if (key) {
6274 zend_hash_update(result_ht, key, val);
6275 } else {
6276 if (!zend_hash_next_index_insert(result_ht, val)) {
6277 zend_cannot_add_element();
6278 zval_ptr_dtor_nogc(val);
6279 break;
6280 }
6281 }
6282 } ZEND_HASH_FOREACH_END();
6283 }
6284 } else if (EXPECTED(Z_TYPE_P(op1) == IS_OBJECT)) {
6285 zend_class_entry *ce = Z_OBJCE_P(op1);
6286 zend_object_iterator *iter;
6287
6288 if (!ce || !ce->get_iterator) {
6289 zend_type_error("Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(op1));
6290 } else {
6291 iter = ce->get_iterator(ce, op1, 0);
6292 if (UNEXPECTED(!iter)) {
6293 FREE_OP1();
6294 if (!EG(exception)) {
6295 zend_throw_exception_ex(
6296 NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name)
6297 );
6298 }
6299 HANDLE_EXCEPTION();
6300 }
6301
6302 const zend_object_iterator_funcs *funcs = iter->funcs;
6303 if (funcs->rewind) {
6304 funcs->rewind(iter);
6305 }
6306
6307 for (; funcs->valid(iter) == SUCCESS; ) {
6308 zval *val;
6309
6310 if (UNEXPECTED(EG(exception) != NULL)) {
6311 break;
6312 }
6313
6314 val = funcs->get_current_data(iter);
6315 if (UNEXPECTED(EG(exception) != NULL)) {
6316 break;
6317 }
6318
6319 zval key;
6320 if (funcs->get_current_key) {
6321 funcs->get_current_key(iter, &key);
6322 if (UNEXPECTED(EG(exception) != NULL)) {
6323 break;
6324 }
6325
6326 if (UNEXPECTED(Z_TYPE(key) != IS_LONG && Z_TYPE(key) != IS_STRING)) {
6327 zend_throw_error(NULL,
6328 "Keys must be of type int|string during array unpacking");
6329 zval_ptr_dtor(&key);
6330 break;
6331 }
6332 } else {
6333 ZVAL_UNDEF(&key);
6334 }
6335
6336 ZVAL_DEREF(val);
6337 Z_TRY_ADDREF_P(val);
6338
6339 zend_ulong num_key;
6340 if (Z_TYPE(key) == IS_STRING && !ZEND_HANDLE_NUMERIC(Z_STR(key), num_key)) {
6341 zend_hash_update(result_ht, Z_STR(key), val);
6342 zval_ptr_dtor_str(&key);
6343 } else {
6344 zval_ptr_dtor(&key);
6345 if (!zend_hash_next_index_insert(result_ht, val)) {
6346 zend_cannot_add_element();
6347 zval_ptr_dtor_nogc(val);
6348 break;
6349 }
6350 }
6351
6352 funcs->move_forward(iter);
6353 if (UNEXPECTED(EG(exception))) {
6354 break;
6355 }
6356 }
6357
6358 zend_iterator_dtor(iter);
6359 }
6360 } else if (EXPECTED(Z_ISREF_P(op1))) {
6361 op1 = Z_REFVAL_P(op1);
6362 ZEND_VM_C_GOTO(add_unpack_again);
6363 } else {
6364 zend_throw_error(NULL, "Only arrays and Traversables can be unpacked, %s given", zend_zval_value_name(op1));
6365 }
6366
6367 FREE_OP1();
6368 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6369 }
6370
6371 ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|UNUSED|NEXT|CV, ARRAY_INIT|REF)
6372 {
6373 zval *array;
6374 uint32_t size;
6375 USE_OPLINE
6376
6377 array = EX_VAR(opline->result.var);
6378 if (OP1_TYPE != IS_UNUSED) {
6379 size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
6380 ZVAL_ARR(array, zend_new_array(size));
6381 /* Explicitly initialize array as not-packed if flag is set */
6382 if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
6383 zend_hash_real_init_mixed(Z_ARRVAL_P(array));
6384 }
6385 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT);
6386 } else {
6387 ZVAL_ARR(array, zend_new_array(0));
6388 ZEND_VM_NEXT_OPCODE();
6389 }
6390 }
6391
6392 ZEND_VM_COLD_CONST_HANDLER(51, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
6393 {
6394 USE_OPLINE
6395 zval *expr;
6396 zval *result = EX_VAR(opline->result.var);
6397 HashTable *ht;
6398
6399 SAVE_OPLINE();
6400 expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
6401
6402 switch (opline->extended_value) {
6403 case IS_LONG:
6404 ZVAL_LONG(result, zval_get_long(expr));
6405 break;
6406 case IS_DOUBLE:
6407 ZVAL_DOUBLE(result, zval_get_double(expr));
6408 break;
6409 case IS_STRING:
6410 ZVAL_STR(result, zval_get_string(expr));
6411 break;
6412 default:
6413 ZEND_ASSERT(opline->extended_value != _IS_BOOL && "Must use ZEND_BOOL instead");
6414 if (OP1_TYPE & (IS_VAR|IS_CV)) {
6415 ZVAL_DEREF(expr);
6416 }
6417 /* If value is already of correct type, return it directly */
6418 if (Z_TYPE_P(expr) == opline->extended_value) {
6419 ZVAL_COPY_VALUE(result, expr);
6420 if (OP1_TYPE == IS_CONST) {
6421 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result);
6422 } else if (OP1_TYPE != IS_TMP_VAR) {
6423 if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result);
6424 }
6425
6426 FREE_OP1_IF_VAR();
6427 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6428 }
6429
6430 if (opline->extended_value == IS_ARRAY) {
6431 if (OP1_TYPE == IS_CONST || Z_TYPE_P(expr) != IS_OBJECT || Z_OBJCE_P(expr) == zend_ce_closure) {
6432 if (Z_TYPE_P(expr) != IS_NULL) {
6433 ZVAL_ARR(result, zend_new_array(1));
6434 expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
6435 if (OP1_TYPE == IS_CONST) {
6436 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
6437 } else {
6438 if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
6439 }
6440 } else {
6441 ZVAL_EMPTY_ARRAY(result);
6442 }
6443 } else if (ZEND_STD_BUILD_OBJECT_PROPERTIES_ARRAY_COMPATIBLE(expr)) {
6444 /* Optimized version without rebuilding properties HashTable */
6445 ZVAL_ARR(result, zend_std_build_object_properties_array(Z_OBJ_P(expr)));
6446 } else {
6447 HashTable *obj_ht = zend_get_properties_for(expr, ZEND_PROP_PURPOSE_ARRAY_CAST);
6448 if (obj_ht) {
6449 /* fast copy */
6450 ZVAL_ARR(result, zend_proptable_to_symtable(obj_ht,
6451 (Z_OBJCE_P(expr)->default_properties_count ||
6452 Z_OBJ_P(expr)->handlers != &std_object_handlers ||
6453 GC_IS_RECURSIVE(obj_ht))));
6454 zend_release_properties(obj_ht);
6455 } else {
6456 ZVAL_EMPTY_ARRAY(result);
6457 }
6458 }
6459 } else {
6460 ZEND_ASSERT(opline->extended_value == IS_OBJECT);
6461 ZVAL_OBJ(result, zend_objects_new(zend_standard_class_def));
6462 if (Z_TYPE_P(expr) == IS_ARRAY) {
6463 ht = zend_symtable_to_proptable(Z_ARR_P(expr));
6464 if (GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) {
6465 /* TODO: try not to duplicate immutable arrays as well ??? */
6466 ht = zend_array_dup(ht);
6467 }
6468 Z_OBJ_P(result)->properties = ht;
6469 } else if (Z_TYPE_P(expr) != IS_NULL) {
6470 Z_OBJ_P(result)->properties = ht = zend_new_array(1);
6471 expr = zend_hash_add_new(ht, ZSTR_KNOWN(ZEND_STR_SCALAR), expr);
6472 if (OP1_TYPE == IS_CONST) {
6473 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(expr))) Z_ADDREF_P(expr);
6474 } else {
6475 if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
6476 }
6477 }
6478 }
6479 }
6480
6481 FREE_OP1();
6482 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6483 }
6484
6485 ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSERVER))
6486 {
6487 USE_OPLINE
6488 zend_op_array *new_op_array;
6489 zval *inc_filename;
6490
6491 SAVE_OPLINE();
6492 inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R);
6493 new_op_array = zend_include_or_eval(inc_filename, opline->extended_value);
6494 if (UNEXPECTED(EG(exception) != NULL)) {
6495 FREE_OP1();
6496 if (new_op_array != ZEND_FAKE_OP_ARRAY && new_op_array != NULL) {
6497 destroy_op_array(new_op_array);
6498 efree_size(new_op_array, sizeof(zend_op_array));
6499 }
6500 UNDEF_RESULT();
6501 HANDLE_EXCEPTION();
6502 } else if (new_op_array == ZEND_FAKE_OP_ARRAY) {
6503 if (RETURN_VALUE_USED(opline)) {
6504 ZVAL_TRUE(EX_VAR(opline->result.var));
6505 }
6506 } else if (UNEXPECTED(new_op_array == NULL)) {
6507 if (RETURN_VALUE_USED(opline)) {
6508 ZVAL_FALSE(EX_VAR(opline->result.var));
6509 }
6510 } else if (new_op_array->last == 1
6511 && new_op_array->opcodes[0].opcode == ZEND_RETURN
6512 && new_op_array->opcodes[0].op1_type == IS_CONST
6513 && EXPECTED(zend_execute_ex == execute_ex)) {
6514 if (RETURN_VALUE_USED(opline)) {
6515 const zend_op *op = new_op_array->opcodes;
6516
6517 ZVAL_COPY(EX_VAR(opline->result.var), RT_CONSTANT(op, op->op1));
6518 }
6519 zend_destroy_static_vars(new_op_array);
6520 destroy_op_array(new_op_array);
6521 efree_size(new_op_array, sizeof(zend_op_array));
6522 } else {
6523 zval *return_value = NULL;
6524 zend_execute_data *call;
6525 if (RETURN_VALUE_USED(opline)) {
6526 return_value = EX_VAR(opline->result.var);
6527 }
6528
6529 new_op_array->scope = EX(func)->op_array.scope;
6530
6531 call = zend_vm_stack_push_call_frame(
6532 (Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
6533 (zend_function*)new_op_array, 0,
6534 Z_PTR(EX(This)));
6535
6536 if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
6537 call->symbol_table = EX(symbol_table);
6538 } else {
6539 call->symbol_table = zend_rebuild_symbol_table();
6540 }
6541
6542 call->prev_execute_data = execute_data;
6543 i_init_code_execute_data(call, new_op_array, return_value);
6544 ZEND_OBSERVER_FCALL_BEGIN(call);
6545 if (EXPECTED(zend_execute_ex == execute_ex)) {
6546 FREE_OP1();
6547 ZEND_VM_ENTER();
6548 } else {
6549 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
6550 zend_execute_ex(call);
6551 zend_vm_stack_free_call_frame(call);
6552 }
6553
6554 zend_destroy_static_vars(new_op_array);
6555 destroy_op_array(new_op_array);
6556 efree_size(new_op_array, sizeof(zend_op_array));
6557 if (UNEXPECTED(EG(exception) != NULL)) {
6558 zend_rethrow_exception(execute_data);
6559 FREE_OP1();
6560 UNDEF_RESULT();
6561 HANDLE_EXCEPTION();
6562 }
6563 }
6564 FREE_OP1();
6565 ZEND_VM_NEXT_OPCODE();
6566 }
6567
6568 ZEND_VM_HANDLER(153, ZEND_UNSET_CV, CV, UNUSED)
6569 {
6570 USE_OPLINE
6571 zval *var = EX_VAR(opline->op1.var);
6572
6573 if (Z_REFCOUNTED_P(var)) {
6574 zend_refcounted *garbage = Z_COUNTED_P(var);
6575
6576 ZVAL_UNDEF(var);
6577 SAVE_OPLINE();
6578 GC_DTOR(garbage);
6579 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6580 } else {
6581 ZVAL_UNDEF(var);
6582 }
6583 ZEND_VM_NEXT_OPCODE();
6584 }
6585
6586 ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
6587 {
6588 USE_OPLINE
6589 zval *varname;
6590 zend_string *name, *tmp_name;
6591 HashTable *target_symbol_table;
6592
6593 SAVE_OPLINE();
6594
6595 varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
6596
6597 if (OP1_TYPE == IS_CONST) {
6598 name = Z_STR_P(varname);
6599 } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
6600 name = Z_STR_P(varname);
6601 tmp_name = NULL;
6602 } else {
6603 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
6604 varname = ZVAL_UNDEFINED_OP1();
6605 }
6606 name = zval_try_get_tmp_string(varname, &tmp_name);
6607 if (UNEXPECTED(!name)) {
6608 FREE_OP1();
6609 HANDLE_EXCEPTION();
6610 }
6611 }
6612
6613 target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
6614 zend_hash_del_ind(target_symbol_table, name);
6615
6616 if (OP1_TYPE != IS_CONST) {
6617 zend_tmp_string_release(tmp_name);
6618 }
6619 FREE_OP1();
6620 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6621 }
6622
6623 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
6624 ZEND_VM_COLD_HANDLER(179, ZEND_UNSET_STATIC_PROP, ANY, ANY, CACHE_SLOT)
6625 {
6626 USE_OPLINE
6627 zval *varname;
6628 zend_string *name, *tmp_name = NULL;
6629 zend_class_entry *ce;
6630
6631 SAVE_OPLINE();
6632
6633 if (OP2_TYPE == IS_CONST) {
6634 ce = CACHED_PTR(opline->extended_value);
6635 if (UNEXPECTED(ce == NULL)) {
6636 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);
6637 if (UNEXPECTED(ce == NULL)) {
6638 FREE_OP1();
6639 HANDLE_EXCEPTION();
6640 }
6641 /*CACHE_PTR(opline->extended_value, ce);*/
6642 }
6643 } else if (OP2_TYPE == IS_UNUSED) {
6644 ce = zend_fetch_class(NULL, opline->op2.num);
6645 if (UNEXPECTED(ce == NULL)) {
6646 FREE_OP1();
6647 HANDLE_EXCEPTION();
6648 }
6649 } else {
6650 ce = Z_CE_P(EX_VAR(opline->op2.var));
6651 }
6652
6653 varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
6654 if (OP1_TYPE == IS_CONST) {
6655 name = Z_STR_P(varname);
6656 } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
6657 name = Z_STR_P(varname);
6658 } else {
6659 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
6660 varname = ZVAL_UNDEFINED_OP1();
6661 }
6662 name = zval_try_get_tmp_string(varname, &tmp_name);
6663 if (UNEXPECTED(!name)) {
6664 FREE_OP1();
6665 HANDLE_EXCEPTION();
6666 }
6667 }
6668
6669 zend_std_unset_static_property(ce, name);
6670
6671 zend_tmp_string_release(tmp_name);
6672 FREE_OP1();
6673 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6674 }
6675
6676 ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|CV, CONST|TMPVAR|CV)
6677 {
6678 USE_OPLINE
6679 zval *container;
6680 zval *offset;
6681 zend_ulong hval;
6682 zend_string *key;
6683
6684 SAVE_OPLINE();
6685 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
6686 offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
6687
6688 do {
6689 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
6690 HashTable *ht;
6691
6692 ZEND_VM_C_LABEL(unset_dim_array):
6693 SEPARATE_ARRAY(container);
6694 ht = Z_ARRVAL_P(container);
6695 ZEND_VM_C_LABEL(offset_again):
6696 if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
6697 key = Z_STR_P(offset);
6698 if (OP2_TYPE != IS_CONST) {
6699 if (ZEND_HANDLE_NUMERIC(key, hval)) {
6700 ZEND_VM_C_GOTO(num_index_dim);
6701 }
6702 }
6703 ZEND_VM_C_LABEL(str_index_dim):
6704 ZEND_ASSERT(ht != &EG(symbol_table));
6705 zend_hash_del(ht, key);
6706 } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
6707 hval = Z_LVAL_P(offset);
6708 ZEND_VM_C_LABEL(num_index_dim):
6709 zend_hash_index_del(ht, hval);
6710 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
6711 offset = Z_REFVAL_P(offset);
6712 ZEND_VM_C_GOTO(offset_again);
6713 } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
6714 hval = zend_dval_to_lval_safe(Z_DVAL_P(offset));
6715 ZEND_VM_C_GOTO(num_index_dim);
6716 } else if (Z_TYPE_P(offset) == IS_NULL) {
6717 key = ZSTR_EMPTY_ALLOC();
6718 ZEND_VM_C_GOTO(str_index_dim);
6719 } else if (Z_TYPE_P(offset) == IS_FALSE) {
6720 hval = 0;
6721 ZEND_VM_C_GOTO(num_index_dim);
6722 } else if (Z_TYPE_P(offset) == IS_TRUE) {
6723 hval = 1;
6724 ZEND_VM_C_GOTO(num_index_dim);
6725 } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
6726 zend_use_resource_as_offset(offset);
6727 hval = Z_RES_HANDLE_P(offset);
6728 ZEND_VM_C_GOTO(num_index_dim);
6729 } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
6730 ZVAL_UNDEFINED_OP2();
6731 key = ZSTR_EMPTY_ALLOC();
6732 ZEND_VM_C_GOTO(str_index_dim);
6733 } else {
6734 zend_illegal_array_offset_unset(offset);
6735 }
6736 break;
6737 } else if (Z_ISREF_P(container)) {
6738 container = Z_REFVAL_P(container);
6739 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
6740 ZEND_VM_C_GOTO(unset_dim_array);
6741 }
6742 }
6743 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
6744 container = ZVAL_UNDEFINED_OP1();
6745 }
6746 if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
6747 offset = ZVAL_UNDEFINED_OP2();
6748 }
6749 if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
6750 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
6751 offset++;
6752 }
6753 Z_OBJ_HT_P(container)->unset_dimension(Z_OBJ_P(container), offset);
6754 } else if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
6755 zend_throw_error(NULL, "Cannot unset string offsets");
6756 } else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) {
6757 zend_throw_error(NULL, "Cannot unset offset in a non-array variable");
6758 } else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) {
6759 zend_false_to_array_deprecated();
6760 }
6761 } while (0);
6762
6763 FREE_OP2();
6764 FREE_OP1();
6765 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6766 }
6767
6768 ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACHE_SLOT)
6769 {
6770 USE_OPLINE
6771 zval *container;
6772 zval *offset;
6773 zend_string *name, *tmp_name;
6774
6775 SAVE_OPLINE();
6776 container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
6777 offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
6778
6779 do {
6780 if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
6781 if (Z_ISREF_P(container)) {
6782 container = Z_REFVAL_P(container);
6783 if (Z_TYPE_P(container) != IS_OBJECT) {
6784 if (OP1_TYPE == IS_CV
6785 && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
6786 ZVAL_UNDEFINED_OP1();
6787 }
6788 break;
6789 }
6790 } else {
6791 break;
6792 }
6793 }
6794 if (OP2_TYPE == IS_CONST) {
6795 name = Z_STR_P(offset);
6796 } else {
6797 name = zval_try_get_tmp_string(offset, &tmp_name);
6798 if (UNEXPECTED(!name)) {
6799 break;
6800 }
6801 }
6802 Z_OBJ_HT_P(container)->unset_property(Z_OBJ_P(container), name, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL));
6803 if (OP2_TYPE != IS_CONST) {
6804 zend_tmp_string_release(tmp_name);
6805 }
6806 } while (0);
6807
6808 FREE_OP2();
6809 FREE_OP1();
6810 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6811 }
6812
6813 ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
6814 {
6815 USE_OPLINE
6816 zval *array_ptr, *result;
6817
6818 SAVE_OPLINE();
6819
6820 array_ptr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
6821 if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) {
6822 result = EX_VAR(opline->result.var);
6823 ZVAL_COPY_VALUE(result, array_ptr);
6824 if (OP1_TYPE != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) {
6825 Z_ADDREF_P(array_ptr);
6826 }
6827 Z_FE_POS_P(result) = 0;
6828
6829 FREE_OP1_IF_VAR();
6830 ZEND_VM_NEXT_OPCODE();
6831 } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
6832 zend_object *zobj = Z_OBJ_P(array_ptr);
6833 if (!zobj->ce->get_iterator) {
6834 if (UNEXPECTED(zend_object_is_lazy(zobj))) {
6835 zobj = zend_lazy_object_init(zobj);
6836 if (UNEXPECTED(EG(exception))) {
6837 UNDEF_RESULT();
6838 FREE_OP1_IF_VAR();
6839 HANDLE_EXCEPTION();
6840 }
6841 }
6842 HashTable *properties = zobj->properties;
6843 if (properties) {
6844 if (UNEXPECTED(GC_REFCOUNT(properties) > 1)) {
6845 if (EXPECTED(!(GC_FLAGS(properties) & IS_ARRAY_IMMUTABLE))) {
6846 GC_DELREF(properties);
6847 }
6848 properties = zobj->properties = zend_array_dup(properties);
6849 }
6850 } else {
6851 properties = zobj->handlers->get_properties(zobj);
6852 }
6853
6854 result = EX_VAR(opline->result.var);
6855 ZVAL_COPY_VALUE(result, array_ptr);
6856 if (OP1_TYPE != IS_TMP_VAR) {
6857 Z_ADDREF_P(array_ptr);
6858 }
6859
6860 if (zend_hash_num_elements(properties) == 0) {
6861 Z_FE_ITER_P(result) = (uint32_t) -1;
6862 FREE_OP1_IF_VAR();
6863 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6864 }
6865
6866 Z_FE_ITER_P(result) = zend_hash_iterator_add(properties, 0);
6867 FREE_OP1_IF_VAR();
6868 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6869 } else {
6870 bool is_empty = zend_fe_reset_iterator(array_ptr, 0 OPLINE_CC EXECUTE_DATA_CC);
6871
6872 FREE_OP1();
6873 if (UNEXPECTED(EG(exception))) {
6874 HANDLE_EXCEPTION();
6875 } else if (is_empty) {
6876 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
6877 } else {
6878 ZEND_VM_NEXT_OPCODE();
6879 }
6880 }
6881 } else {
6882 zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr));
6883 ZVAL_UNDEF(EX_VAR(opline->result.var));
6884 Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
6885 FREE_OP1();
6886 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6887 }
6888 }
6889
6890 ZEND_VM_COLD_CONST_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
6891 {
6892 USE_OPLINE
6893 zval *array_ptr, *array_ref;
6894
6895 SAVE_OPLINE();
6896
6897 if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
6898 array_ref = array_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
6899 if (Z_ISREF_P(array_ref)) {
6900 array_ptr = Z_REFVAL_P(array_ref);
6901 }
6902 } else {
6903 array_ref = array_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
6904 }
6905
6906 if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) {
6907 if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
6908 if (array_ptr == array_ref) {
6909 ZVAL_NEW_REF(array_ref, array_ref);
6910 array_ptr = Z_REFVAL_P(array_ref);
6911 }
6912 Z_ADDREF_P(array_ref);
6913 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
6914 } else {
6915 array_ref = EX_VAR(opline->result.var);
6916 ZVAL_NEW_REF(array_ref, array_ptr);
6917 array_ptr = Z_REFVAL_P(array_ref);
6918 }
6919 if (OP1_TYPE == IS_CONST) {
6920 ZVAL_ARR(array_ptr, zend_array_dup(Z_ARRVAL_P(array_ptr)));
6921 } else {
6922 SEPARATE_ARRAY(array_ptr);
6923 }
6924 Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(Z_ARRVAL_P(array_ptr), 0);
6925
6926 FREE_OP1_IF_VAR();
6927 ZEND_VM_NEXT_OPCODE();
6928 } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
6929 if (!Z_OBJCE_P(array_ptr)->get_iterator) {
6930 zend_object *zobj = Z_OBJ_P(array_ptr);
6931 HashTable *properties;
6932 if (UNEXPECTED(zend_object_is_lazy(zobj))) {
6933 zobj = zend_lazy_object_init(zobj);
6934 if (UNEXPECTED(EG(exception))) {
6935 UNDEF_RESULT();
6936 FREE_OP1_IF_VAR();
6937 HANDLE_EXCEPTION();
6938 }
6939 }
6940 if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
6941 if (array_ptr == array_ref) {
6942 ZVAL_NEW_REF(array_ref, array_ref);
6943 array_ptr = Z_REFVAL_P(array_ref);
6944 }
6945 Z_ADDREF_P(array_ref);
6946 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
6947 } else {
6948 array_ptr = EX_VAR(opline->result.var);
6949 ZVAL_COPY_VALUE(array_ptr, array_ref);
6950 }
6951 if (Z_OBJ_P(array_ptr)->properties
6952 && UNEXPECTED(GC_REFCOUNT(Z_OBJ_P(array_ptr)->properties) > 1)) {
6953 if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array_ptr)->properties) & IS_ARRAY_IMMUTABLE))) {
6954 GC_DELREF(Z_OBJ_P(array_ptr)->properties);
6955 }
6956 Z_OBJ_P(array_ptr)->properties = zend_array_dup(Z_OBJ_P(array_ptr)->properties);
6957 }
6958
6959 properties = Z_OBJPROP_P(array_ptr);
6960 if (zend_hash_num_elements(properties) == 0) {
6961 Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t) -1;
6962 FREE_OP1_IF_VAR();
6963 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6964 }
6965
6966 Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(properties, 0);
6967 FREE_OP1_IF_VAR();
6968 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
6969 } else {
6970 bool is_empty = zend_fe_reset_iterator(array_ptr, 1 OPLINE_CC EXECUTE_DATA_CC);
6971 FREE_OP1();
6972 if (UNEXPECTED(EG(exception))) {
6973 HANDLE_EXCEPTION();
6974 } else if (is_empty) {
6975 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
6976 } else {
6977 ZEND_VM_NEXT_OPCODE();
6978 }
6979 }
6980 } else {
6981 zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array_ptr));
6982 ZVAL_UNDEF(EX_VAR(opline->result.var));
6983 Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
6984 FREE_OP1();
6985 ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
6986 }
6987 }
6988
ZEND_VM_HELPER(zend_fe_fetch_object_helper,ANY,ANY)6989 ZEND_VM_HELPER(zend_fe_fetch_object_helper, ANY, ANY)
6990 {
6991 USE_OPLINE
6992 zval *array;
6993 zval *value;
6994 uint32_t value_type;
6995 HashTable *fe_ht;
6996 HashPosition pos;
6997 Bucket *p;
6998 zend_object_iterator *iter;
6999
7000 array = EX_VAR(opline->op1.var);
7001 SAVE_OPLINE();
7002
7003 ZEND_ASSERT(Z_TYPE_P(array) == IS_OBJECT);
7004 if ((iter = zend_iterator_unwrap(array)) == NULL) {
7005 /* plain object */
7006
7007 fe_ht = Z_OBJPROP_P(array);
7008 pos = zend_hash_iterator_pos(Z_FE_ITER_P(array), fe_ht);
7009 p = fe_ht->arData + pos;
7010 while (1) {
7011 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7012 /* reached end of iteration */
7013 ZEND_VM_C_GOTO(fe_fetch_r_exit);
7014 }
7015 pos++;
7016 value = &p->val;
7017 value_type = Z_TYPE_INFO_P(value);
7018 if (EXPECTED(value_type != IS_UNDEF)) {
7019 if (UNEXPECTED(value_type == IS_INDIRECT)) {
7020 value = Z_INDIRECT_P(value);
7021 value_type = Z_TYPE_INFO_P(value);
7022 if (EXPECTED(value_type != IS_UNDEF)
7023 && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
7024 break;
7025 }
7026 } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
7027 || !p->key
7028 || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
7029 break;
7030 }
7031 }
7032 p++;
7033 }
7034 EG(ht_iterators)[Z_FE_ITER_P(array)].pos = pos;
7035 if (RETURN_VALUE_USED(opline)) {
7036 if (UNEXPECTED(!p->key)) {
7037 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7038 } else if (ZSTR_VAL(p->key)[0]) {
7039 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7040 } else {
7041 const char *class_name, *prop_name;
7042 size_t prop_name_len;
7043 zend_unmangle_property_name_ex(
7044 p->key, &class_name, &prop_name, &prop_name_len);
7045 ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len);
7046 }
7047 }
7048 } else {
7049 const zend_object_iterator_funcs *funcs = iter->funcs;
7050 if (EXPECTED(++iter->index > 0)) {
7051 /* This could cause an endless loop if index becomes zero again.
7052 * In case that ever happens we need an additional flag. */
7053 funcs->move_forward(iter);
7054 if (UNEXPECTED(EG(exception) != NULL)) {
7055 UNDEF_RESULT();
7056 HANDLE_EXCEPTION();
7057 }
7058 if (UNEXPECTED(funcs->valid(iter) == FAILURE)) {
7059 /* reached end of iteration */
7060 if (UNEXPECTED(EG(exception) != NULL)) {
7061 UNDEF_RESULT();
7062 HANDLE_EXCEPTION();
7063 }
7064 ZEND_VM_C_LABEL(fe_fetch_r_exit):
7065 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7066 ZEND_VM_CONTINUE();
7067 }
7068 }
7069 value = funcs->get_current_data(iter);
7070 if (UNEXPECTED(EG(exception) != NULL)) {
7071 UNDEF_RESULT();
7072 HANDLE_EXCEPTION();
7073 }
7074 if (!value) {
7075 /* failure in get_current_data */
7076 ZEND_VM_C_GOTO(fe_fetch_r_exit);
7077 }
7078 if (RETURN_VALUE_USED(opline)) {
7079 if (funcs->get_current_key) {
7080 funcs->get_current_key(iter, EX_VAR(opline->result.var));
7081 if (UNEXPECTED(EG(exception) != NULL)) {
7082 UNDEF_RESULT();
7083 HANDLE_EXCEPTION();
7084 }
7085 } else {
7086 ZVAL_LONG(EX_VAR(opline->result.var), iter->index);
7087 }
7088 }
7089 value_type = Z_TYPE_INFO_P(value);
7090 }
7091
7092 if (EXPECTED(OP2_TYPE == IS_CV)) {
7093 zval *variable_ptr = EX_VAR(opline->op2.var);
7094 zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
7095 } else {
7096 zval *res = EX_VAR(opline->op2.var);
7097 zend_refcounted *gc = Z_COUNTED_P(value);
7098
7099 ZVAL_COPY_VALUE_EX(res, value, gc, value_type);
7100 if (Z_TYPE_INFO_REFCOUNTED(value_type)) {
7101 GC_ADDREF(gc);
7102 }
7103 }
7104 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7105 }
7106
7107 ZEND_VM_HOT_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
7108 {
7109 USE_OPLINE
7110 zval *array;
7111 zval *value;
7112 uint32_t value_type;
7113 HashTable *fe_ht;
7114 HashPosition pos;
7115
7116 array = EX_VAR(opline->op1.var);
7117 if (UNEXPECTED(Z_TYPE_P(array) != IS_ARRAY)) {
7118 ZEND_VM_DISPATCH_TO_HELPER(zend_fe_fetch_object_helper);
7119 }
7120 fe_ht = Z_ARRVAL_P(array);
7121 pos = Z_FE_POS_P(array);
7122 if (HT_IS_PACKED(fe_ht)) {
7123 value = fe_ht->arPacked + pos;
7124 while (1) {
7125 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7126 /* reached end of iteration */
7127 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7128 ZEND_VM_CONTINUE();
7129 }
7130 value_type = Z_TYPE_INFO_P(value);
7131 ZEND_ASSERT(value_type != IS_INDIRECT);
7132 if (EXPECTED(value_type != IS_UNDEF)) {
7133 break;
7134 }
7135 pos++;
7136 value++;
7137 }
7138 Z_FE_POS_P(array) = pos + 1;
7139 if (RETURN_VALUE_USED(opline)) {
7140 ZVAL_LONG(EX_VAR(opline->result.var), pos);
7141 }
7142 } else {
7143 Bucket *p;
7144
7145 p = fe_ht->arData + pos;
7146 while (1) {
7147 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7148 /* reached end of iteration */
7149 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7150 ZEND_VM_CONTINUE();
7151 }
7152 pos++;
7153 value = &p->val;
7154 value_type = Z_TYPE_INFO_P(value);
7155 ZEND_ASSERT(value_type != IS_INDIRECT);
7156 if (EXPECTED(value_type != IS_UNDEF)) {
7157 break;
7158 }
7159 p++;
7160 }
7161 Z_FE_POS_P(array) = pos;
7162 if (RETURN_VALUE_USED(opline)) {
7163 if (!p->key) {
7164 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7165 } else {
7166 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7167 }
7168 }
7169 }
7170 if (EXPECTED(OP2_TYPE == IS_CV)) {
7171 zval *variable_ptr = EX_VAR(opline->op2.var);
7172 SAVE_OPLINE();
7173 zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
7174 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7175 } else {
7176 zval *res = EX_VAR(opline->op2.var);
7177 zend_refcounted *gc = Z_COUNTED_P(value);
7178
7179 ZVAL_COPY_VALUE_EX(res, value, gc, value_type);
7180 if (Z_TYPE_INFO_REFCOUNTED(value_type)) {
7181 GC_ADDREF(gc);
7182 }
7183 ZEND_VM_NEXT_OPCODE();
7184 }
7185 }
7186
7187 ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR)
7188 {
7189 USE_OPLINE
7190 zval *array;
7191 zval *value;
7192 uint32_t value_type;
7193 HashTable *fe_ht;
7194 HashPosition pos;
7195 Bucket *p;
7196
7197 array = EX_VAR(opline->op1.var);
7198 SAVE_OPLINE();
7199
7200 ZVAL_DEREF(array);
7201 if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
7202 pos = zend_hash_iterator_pos_ex(Z_FE_ITER_P(EX_VAR(opline->op1.var)), array);
7203 fe_ht = Z_ARRVAL_P(array);
7204 if (HT_IS_PACKED(fe_ht)) {
7205 value = fe_ht->arPacked + pos;
7206 while (1) {
7207 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7208 /* reached end of iteration */
7209 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7210 }
7211 value_type = Z_TYPE_INFO_P(value);
7212 ZEND_ASSERT(value_type != IS_INDIRECT);
7213 if (EXPECTED(value_type != IS_UNDEF)) {
7214 break;
7215 }
7216 pos++;
7217 value++;
7218 }
7219 EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos + 1;
7220 if (RETURN_VALUE_USED(opline)) {
7221 ZVAL_LONG(EX_VAR(opline->result.var), pos);
7222 }
7223 } else {
7224 p = fe_ht->arData + pos;
7225 while (1) {
7226 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7227 /* reached end of iteration */
7228 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7229 }
7230 pos++;
7231 value = &p->val;
7232 value_type = Z_TYPE_INFO_P(value);
7233 ZEND_ASSERT(value_type != IS_INDIRECT);
7234 if (EXPECTED(value_type != IS_UNDEF)) {
7235 break;
7236 }
7237 p++;
7238 }
7239 EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos;
7240 if (RETURN_VALUE_USED(opline)) {
7241 if (!p->key) {
7242 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7243 } else {
7244 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7245 }
7246 }
7247 }
7248 } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
7249 zend_object_iterator *iter;
7250
7251 if ((iter = zend_iterator_unwrap(array)) == NULL) {
7252 /* plain object */
7253
7254 fe_ht = Z_OBJPROP_P(array);
7255 pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht);
7256 p = fe_ht->arData + pos;
7257 while (1) {
7258 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
7259 /* reached end of iteration */
7260 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7261 }
7262 pos++;
7263 value = &p->val;
7264 value_type = Z_TYPE_INFO_P(value);
7265 if (EXPECTED(value_type != IS_UNDEF)) {
7266 if (UNEXPECTED(value_type == IS_INDIRECT)) {
7267 value = Z_INDIRECT_P(value);
7268 value_type = Z_TYPE_INFO_P(value);
7269 if (EXPECTED(value_type != IS_UNDEF)
7270 && EXPECTED(zend_check_property_access(Z_OBJ_P(array), p->key, 0) == SUCCESS)) {
7271 if ((value_type & Z_TYPE_MASK) != IS_REFERENCE) {
7272 zend_property_info *prop_info =
7273 zend_get_property_info_for_slot(Z_OBJ_P(array), value);
7274 if (prop_info) {
7275 if (UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) {
7276 zend_throw_error(NULL,
7277 "Cannot acquire reference to readonly property %s::$%s",
7278 ZSTR_VAL(prop_info->ce->name), ZSTR_VAL(p->key));
7279 UNDEF_RESULT();
7280 HANDLE_EXCEPTION();
7281 }
7282 if (ZEND_TYPE_IS_SET(prop_info->type)) {
7283 ZVAL_NEW_REF(value, value);
7284 ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(value), prop_info);
7285 value_type = IS_REFERENCE_EX;
7286 }
7287 }
7288 }
7289 break;
7290 }
7291 } else if (EXPECTED(Z_OBJCE_P(array)->default_properties_count == 0)
7292 || !p->key
7293 || zend_check_property_access(Z_OBJ_P(array), p->key, 1) == SUCCESS) {
7294 break;
7295 }
7296 }
7297 p++;
7298 }
7299 EG(ht_iterators)[Z_FE_ITER_P(EX_VAR(opline->op1.var))].pos = pos;
7300 if (RETURN_VALUE_USED(opline)) {
7301 if (UNEXPECTED(!p->key)) {
7302 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
7303 } else if (ZSTR_VAL(p->key)[0]) {
7304 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
7305 } else {
7306 const char *class_name, *prop_name;
7307 size_t prop_name_len;
7308 zend_unmangle_property_name_ex(
7309 p->key, &class_name, &prop_name, &prop_name_len);
7310 ZVAL_STRINGL(EX_VAR(opline->result.var), prop_name, prop_name_len);
7311 }
7312 }
7313 } else {
7314 const zend_object_iterator_funcs *funcs = iter->funcs;
7315 if (++iter->index > 0) {
7316 /* This could cause an endless loop if index becomes zero again.
7317 * In case that ever happens we need an additional flag. */
7318 funcs->move_forward(iter);
7319 if (UNEXPECTED(EG(exception) != NULL)) {
7320 UNDEF_RESULT();
7321 HANDLE_EXCEPTION();
7322 }
7323 if (UNEXPECTED(funcs->valid(iter) == FAILURE)) {
7324 /* reached end of iteration */
7325 if (UNEXPECTED(EG(exception) != NULL)) {
7326 UNDEF_RESULT();
7327 HANDLE_EXCEPTION();
7328 }
7329 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7330 }
7331 }
7332 value = funcs->get_current_data(iter);
7333 if (UNEXPECTED(EG(exception) != NULL)) {
7334 UNDEF_RESULT();
7335 HANDLE_EXCEPTION();
7336 }
7337 if (!value) {
7338 /* failure in get_current_data */
7339 ZEND_VM_C_GOTO(fe_fetch_w_exit);
7340 }
7341 if (RETURN_VALUE_USED(opline)) {
7342 if (funcs->get_current_key) {
7343 funcs->get_current_key(iter, EX_VAR(opline->result.var));
7344 if (UNEXPECTED(EG(exception) != NULL)) {
7345 UNDEF_RESULT();
7346 HANDLE_EXCEPTION();
7347 }
7348 } else {
7349 ZVAL_LONG(EX_VAR(opline->result.var), iter->index);
7350 }
7351 }
7352 value_type = Z_TYPE_INFO_P(value);
7353 }
7354 } else {
7355 zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array));
7356 if (UNEXPECTED(EG(exception))) {
7357 UNDEF_RESULT();
7358 HANDLE_EXCEPTION();
7359 }
7360 ZEND_VM_C_LABEL(fe_fetch_w_exit):
7361 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
7362 ZEND_VM_CONTINUE();
7363 }
7364
7365 if (EXPECTED((value_type & Z_TYPE_MASK) != IS_REFERENCE)) {
7366 zend_refcounted *gc = Z_COUNTED_P(value);
7367 zval *ref;
7368 ZVAL_NEW_EMPTY_REF(value);
7369 ref = Z_REFVAL_P(value);
7370 ZVAL_COPY_VALUE_EX(ref, value, gc, value_type);
7371 }
7372 if (EXPECTED(OP2_TYPE == IS_CV)) {
7373 zval *variable_ptr = EX_VAR(opline->op2.var);
7374 if (EXPECTED(variable_ptr != value)) {
7375 zend_reference *ref;
7376
7377 ref = Z_REF_P(value);
7378 GC_ADDREF(ref);
7379 i_zval_ptr_dtor(variable_ptr);
7380 ZVAL_REF(variable_ptr, ref);
7381 }
7382 } else {
7383 Z_ADDREF_P(value);
7384 ZVAL_REF(EX_VAR(opline->op2.var), Z_REF_P(value));
7385 }
7386 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7387 }
7388
7389 ZEND_VM_HOT_HANDLER(154, ZEND_ISSET_ISEMPTY_CV, CV, UNUSED, ISSET, SPEC(ISSET))
7390 {
7391 USE_OPLINE
7392 zval *value;
7393
7394 value = EX_VAR(opline->op1.var);
7395 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7396 if (Z_TYPE_P(value) > IS_NULL &&
7397 (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL)) {
7398 ZEND_VM_SMART_BRANCH_TRUE();
7399 } else {
7400 ZEND_VM_SMART_BRANCH_FALSE();
7401 }
7402 } else {
7403 bool result;
7404
7405 SAVE_OPLINE();
7406 result = !i_zend_is_true(value);
7407 ZEND_VM_SMART_BRANCH(result, 1);
7408 }
7409 }
7410
7411 ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ISSET)
7412 {
7413 USE_OPLINE
7414 zval *value;
7415 bool result;
7416 zval *varname;
7417 zend_string *name, *tmp_name;
7418 HashTable *target_symbol_table;
7419
7420 SAVE_OPLINE();
7421 varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
7422 if (OP1_TYPE == IS_CONST) {
7423 name = Z_STR_P(varname);
7424 } else {
7425 name = zval_get_tmp_string(varname, &tmp_name);
7426 }
7427
7428 target_symbol_table = zend_get_target_symbol_table(opline->extended_value EXECUTE_DATA_CC);
7429 value = zend_hash_find_ex(target_symbol_table, name, OP1_TYPE == IS_CONST);
7430
7431 if (OP1_TYPE != IS_CONST) {
7432 zend_tmp_string_release(tmp_name);
7433 }
7434 FREE_OP1();
7435
7436 if (!value) {
7437 result = (opline->extended_value & ZEND_ISEMPTY);
7438 } else {
7439 if (Z_TYPE_P(value) == IS_INDIRECT) {
7440 value = Z_INDIRECT_P(value);
7441 }
7442 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7443 if (Z_ISREF_P(value)) {
7444 value = Z_REFVAL_P(value);
7445 }
7446 result = Z_TYPE_P(value) > IS_NULL;
7447 } else {
7448 result = !i_zend_is_true(value);
7449 }
7450 }
7451
7452 ZEND_VM_SMART_BRANCH(result, true);
7453 }
7454
7455 /* No specialization for op_types (CONST|TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR) */
7456 ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, ANY, CLASS_FETCH, ISSET|CACHE_SLOT)
7457 {
7458 USE_OPLINE
7459 zval *value;
7460 zend_result fetch_result;
7461 bool result;
7462
7463 SAVE_OPLINE();
7464
7465 fetch_result = zend_fetch_static_property_address(&value, NULL, opline->extended_value & ~ZEND_ISEMPTY, BP_VAR_IS, 0 OPLINE_CC EXECUTE_DATA_CC);
7466
7467 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7468 result = fetch_result == SUCCESS && Z_TYPE_P(value) > IS_NULL &&
7469 (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
7470 } else {
7471 result = fetch_result != SUCCESS || !i_zend_is_true(value);
7472 }
7473
7474 ZEND_VM_SMART_BRANCH(result, 1);
7475 }
7476
7477 ZEND_VM_COLD_CONSTCONST_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|CV, CONST|TMPVAR|CV, ISSET)
7478 {
7479 USE_OPLINE
7480 zval *container;
7481 bool result;
7482 zend_ulong hval;
7483 zval *offset;
7484
7485 SAVE_OPLINE();
7486 container = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_IS);
7487 offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
7488
7489 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
7490 HashTable *ht;
7491 zval *value;
7492 zend_string *str;
7493
7494 ZEND_VM_C_LABEL(isset_dim_obj_array):
7495 ht = Z_ARRVAL_P(container);
7496 ZEND_VM_C_LABEL(isset_again):
7497 if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
7498 str = Z_STR_P(offset);
7499 if (OP2_TYPE != IS_CONST) {
7500 if (ZEND_HANDLE_NUMERIC(str, hval)) {
7501 ZEND_VM_C_GOTO(num_index_prop);
7502 }
7503 }
7504 value = zend_hash_find_ex(ht, str, OP2_TYPE == IS_CONST);
7505 } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
7506 hval = Z_LVAL_P(offset);
7507 ZEND_VM_C_LABEL(num_index_prop):
7508 value = zend_hash_index_find(ht, hval);
7509 } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
7510 offset = Z_REFVAL_P(offset);
7511 ZEND_VM_C_GOTO(isset_again);
7512 } else {
7513 value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
7514 if (UNEXPECTED(EG(exception))) {
7515 result = 0;
7516 ZEND_VM_C_GOTO(isset_dim_obj_exit);
7517 }
7518 }
7519
7520 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7521 /* > IS_NULL means not IS_UNDEF and not IS_NULL */
7522 result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
7523 (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
7524
7525 if (OP1_TYPE & (IS_CONST|IS_CV)) {
7526 /* avoid exception check */
7527 FREE_OP2();
7528 ZEND_VM_SMART_BRANCH(result, 0);
7529 }
7530 } else {
7531 result = (value == NULL || !i_zend_is_true(value));
7532 }
7533 ZEND_VM_C_GOTO(isset_dim_obj_exit);
7534 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(container))) {
7535 container = Z_REFVAL_P(container);
7536 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
7537 ZEND_VM_C_GOTO(isset_dim_obj_array);
7538 }
7539 }
7540
7541 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(offset) == ZEND_EXTRA_VALUE) {
7542 offset++;
7543 }
7544 if (!(opline->extended_value & ZEND_ISEMPTY)) {
7545 result = zend_isset_dim_slow(container, offset EXECUTE_DATA_CC);
7546 } else {
7547 result = zend_isempty_dim_slow(container, offset EXECUTE_DATA_CC);
7548 }
7549
7550 ZEND_VM_C_LABEL(isset_dim_obj_exit):
7551 FREE_OP2();
7552 FREE_OP1();
7553 ZEND_VM_SMART_BRANCH(result, 1);
7554 }
7555
7556 ZEND_VM_COLD_CONST_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, ISSET|CACHE_SLOT)
7557 {
7558 USE_OPLINE
7559 zval *container;
7560 int result;
7561 zval *offset;
7562 zend_string *name, *tmp_name;
7563
7564 SAVE_OPLINE();
7565 container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
7566 offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
7567
7568 if (OP1_TYPE == IS_CONST ||
7569 (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
7570 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
7571 container = Z_REFVAL_P(container);
7572 if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
7573 result = (opline->extended_value & ZEND_ISEMPTY);
7574 ZEND_VM_C_GOTO(isset_object_finish);
7575 }
7576 } else {
7577 result = (opline->extended_value & ZEND_ISEMPTY);
7578 ZEND_VM_C_GOTO(isset_object_finish);
7579 }
7580 }
7581
7582 if (OP2_TYPE == IS_CONST) {
7583 name = Z_STR_P(offset);
7584 } else {
7585 name = zval_try_get_tmp_string(offset, &tmp_name);
7586 if (UNEXPECTED(!name)) {
7587 result = 0;
7588 ZEND_VM_C_GOTO(isset_object_finish);
7589 }
7590 }
7591
7592 result =
7593 (opline->extended_value & ZEND_ISEMPTY) ^
7594 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));
7595
7596 if (OP2_TYPE != IS_CONST) {
7597 zend_tmp_string_release(tmp_name);
7598 }
7599
7600 ZEND_VM_C_LABEL(isset_object_finish):
7601 FREE_OP2();
7602 FREE_OP1();
7603 ZEND_VM_SMART_BRANCH(result, 1);
7604 }
7605
7606 ZEND_VM_HANDLER(194, ZEND_ARRAY_KEY_EXISTS, CV|TMPVAR|CONST, CV|TMPVAR|CONST)
7607 {
7608 USE_OPLINE
7609
7610 zval *key, *subject;
7611 HashTable *ht;
7612 bool result;
7613
7614 SAVE_OPLINE();
7615
7616 key = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7617 subject = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
7618
7619 if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
7620 ZEND_VM_C_LABEL(array_key_exists_array):
7621 ht = Z_ARRVAL_P(subject);
7622 result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC);
7623 } else {
7624 if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(subject))) {
7625 subject = Z_REFVAL_P(subject);
7626 if (EXPECTED(Z_TYPE_P(subject) == IS_ARRAY)) {
7627 ZEND_VM_C_GOTO(array_key_exists_array);
7628 }
7629 }
7630 zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
7631 result = 0;
7632 }
7633
7634 FREE_OP2();
7635 FREE_OP1();
7636 ZEND_VM_SMART_BRANCH(result, 1);
7637 }
7638
7639 ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
7640 {
7641 USE_OPLINE
7642
7643 ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
7644
7645 if (!E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))) {
7646 do {
7647 /* Do not silence fatal errors */
7648 EG(error_reporting) &= E_FATAL_ERRORS;
7649 if (!EG(error_reporting_ini_entry)) {
7650 zval *zv = zend_hash_find_known_hash(EG(ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING));
7651 if (zv) {
7652 EG(error_reporting_ini_entry) = (zend_ini_entry *)Z_PTR_P(zv);
7653 } else {
7654 break;
7655 }
7656 }
7657 if (!EG(error_reporting_ini_entry)->modified) {
7658 if (!EG(modified_ini_directives)) {
7659 ALLOC_HASHTABLE(EG(modified_ini_directives));
7660 zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
7661 }
7662 if (EXPECTED(zend_hash_add_ptr(EG(modified_ini_directives), ZSTR_KNOWN(ZEND_STR_ERROR_REPORTING), EG(error_reporting_ini_entry)) != NULL)) {
7663 EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
7664 EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
7665 EG(error_reporting_ini_entry)->modified = 1;
7666 }
7667 }
7668 } while (0);
7669 }
7670 ZEND_VM_NEXT_OPCODE();
7671 }
7672
7673 ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
7674 {
7675 USE_OPLINE
7676
7677 if (E_HAS_ONLY_FATAL_ERRORS(EG(error_reporting))
7678 && !E_HAS_ONLY_FATAL_ERRORS(Z_LVAL_P(EX_VAR(opline->op1.var)))) {
7679 EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var));
7680 }
7681 ZEND_VM_NEXT_OPCODE();
7682 }
7683
7684 ZEND_VM_COLD_CONST_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR)
7685 {
7686 USE_OPLINE
7687 zval *value;
7688 zend_reference *ref = NULL;
7689 bool ret;
7690
7691 SAVE_OPLINE();
7692 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
7693
7694 if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) && Z_ISREF_P(value)) {
7695 if (OP1_TYPE == IS_VAR) {
7696 ref = Z_REF_P(value);
7697 }
7698 value = Z_REFVAL_P(value);
7699 }
7700
7701 ret = i_zend_is_true(value);
7702
7703 if (UNEXPECTED(EG(exception))) {
7704 FREE_OP1();
7705 ZVAL_UNDEF(EX_VAR(opline->result.var));
7706 HANDLE_EXCEPTION();
7707 }
7708
7709 if (ret) {
7710 zval *result = EX_VAR(opline->result.var);
7711
7712 ZVAL_COPY_VALUE(result, value);
7713 if (OP1_TYPE == IS_CONST) {
7714 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result);
7715 } else if (OP1_TYPE == IS_CV) {
7716 if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result);
7717 } else if (OP1_TYPE == IS_VAR && ref) {
7718 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
7719 efree_size(ref, sizeof(zend_reference));
7720 } else if (Z_OPT_REFCOUNTED_P(result)) {
7721 Z_ADDREF_P(result);
7722 }
7723 }
7724 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
7725 }
7726
7727 FREE_OP1();
7728 ZEND_VM_NEXT_OPCODE();
7729 }
7730
7731 ZEND_VM_COLD_CONST_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
7732 {
7733 USE_OPLINE
7734 zval *value;
7735 zend_reference *ref = NULL;
7736
7737 SAVE_OPLINE();
7738 value = GET_OP1_ZVAL_PTR(BP_VAR_IS);
7739
7740 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
7741 if (OP1_TYPE & IS_VAR) {
7742 ref = Z_REF_P(value);
7743 }
7744 value = Z_REFVAL_P(value);
7745 }
7746
7747 if (Z_TYPE_P(value) > IS_NULL) {
7748 zval *result = EX_VAR(opline->result.var);
7749 ZVAL_COPY_VALUE(result, value);
7750 if (OP1_TYPE == IS_CONST) {
7751 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) Z_ADDREF_P(result);
7752 } else if (OP1_TYPE == IS_CV) {
7753 if (Z_OPT_REFCOUNTED_P(result)) Z_ADDREF_P(result);
7754 } else if ((OP1_TYPE & IS_VAR) && ref) {
7755 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
7756 efree_size(ref, sizeof(zend_reference));
7757 } else if (Z_OPT_REFCOUNTED_P(result)) {
7758 Z_ADDREF_P(result);
7759 }
7760 }
7761 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
7762 }
7763
7764 if ((OP1_TYPE & IS_VAR) && ref) {
7765 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
7766 efree_size(ref, sizeof(zend_reference));
7767 }
7768 }
7769 ZEND_VM_NEXT_OPCODE();
7770 }
7771
7772 ZEND_VM_HOT_NOCONST_HANDLER(198, ZEND_JMP_NULL, CONST|TMP|VAR|CV, JMP_ADDR)
7773 {
7774 USE_OPLINE
7775 zval *val, *result;
7776
7777 val = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7778
7779 if (Z_TYPE_P(val) > IS_NULL) {
7780 do {
7781 if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_TYPE_P(val) == IS_REFERENCE) {
7782 val = Z_REFVAL_P(val);
7783 if (Z_TYPE_P(val) <= IS_NULL) {
7784 FREE_OP1();
7785 break;
7786 }
7787 }
7788 ZEND_VM_NEXT_OPCODE();
7789 } while (0);
7790 }
7791
7792 result = EX_VAR(opline->result.var);
7793 uint32_t short_circuiting_type = opline->extended_value & ZEND_SHORT_CIRCUITING_CHAIN_MASK;
7794 if (EXPECTED(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EXPR)) {
7795 ZVAL_NULL(result);
7796 if (OP1_TYPE == IS_CV
7797 && UNEXPECTED(Z_TYPE_P(val) == IS_UNDEF)
7798 && (opline->extended_value & ZEND_JMP_NULL_BP_VAR_IS) == 0
7799 ) {
7800 SAVE_OPLINE();
7801 ZVAL_UNDEFINED_OP1();
7802 if (UNEXPECTED(EG(exception) != NULL)) {
7803 HANDLE_EXCEPTION();
7804 }
7805 }
7806 } else if (short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_ISSET) {
7807 ZVAL_FALSE(result);
7808 } else {
7809 ZEND_ASSERT(short_circuiting_type == ZEND_SHORT_CIRCUITING_CHAIN_EMPTY);
7810 ZVAL_TRUE(result);
7811 }
7812
7813 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 0);
7814 }
7815
7816 ZEND_VM_HOT_HANDLER(31, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
7817 {
7818 USE_OPLINE
7819 zval *value;
7820 zval *result = EX_VAR(opline->result.var);
7821
7822 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7823 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
7824 SAVE_OPLINE();
7825 ZVAL_UNDEFINED_OP1();
7826 ZVAL_NULL(result);
7827 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7828 }
7829
7830 if (OP1_TYPE == IS_CV) {
7831 ZVAL_COPY_DEREF(result, value);
7832 } else if (OP1_TYPE == IS_VAR) {
7833 if (UNEXPECTED(Z_ISREF_P(value))) {
7834 ZVAL_COPY_VALUE(result, Z_REFVAL_P(value));
7835 if (UNEXPECTED(Z_DELREF_P(value) == 0)) {
7836 efree_size(Z_REF_P(value), sizeof(zend_reference));
7837 } else if (Z_OPT_REFCOUNTED_P(result)) {
7838 Z_ADDREF_P(result);
7839 }
7840 } else {
7841 ZVAL_COPY_VALUE(result, value);
7842 }
7843 } else {
7844 ZVAL_COPY_VALUE(result, value);
7845 if (OP1_TYPE == IS_CONST) {
7846 if (UNEXPECTED(Z_OPT_REFCOUNTED_P(result))) {
7847 Z_ADDREF_P(result);
7848 }
7849 }
7850 }
7851 ZEND_VM_NEXT_OPCODE();
7852 }
7853
7854 ZEND_VM_COLD_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
7855 {
7856 USE_OPLINE
7857
7858 if (!EG(no_extensions)) {
7859 SAVE_OPLINE();
7860 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, execute_data);
7861 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7862 }
7863 ZEND_VM_NEXT_OPCODE();
7864 }
7865
7866 ZEND_VM_COLD_HANDLER(102, ZEND_EXT_FCALL_BEGIN, ANY, ANY)
7867 {
7868 USE_OPLINE
7869
7870 if (!EG(no_extensions)) {
7871 SAVE_OPLINE();
7872 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, execute_data);
7873 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7874 }
7875 ZEND_VM_NEXT_OPCODE();
7876 }
7877
7878 ZEND_VM_COLD_HANDLER(103, ZEND_EXT_FCALL_END, ANY, ANY)
7879 {
7880 USE_OPLINE
7881
7882 if (!EG(no_extensions)) {
7883 SAVE_OPLINE();
7884 zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, execute_data);
7885 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7886 }
7887 ZEND_VM_NEXT_OPCODE();
7888 }
7889
7890 ZEND_VM_HANDLER(144, ZEND_DECLARE_CLASS, CONST, ANY)
7891 {
7892 USE_OPLINE
7893
7894 SAVE_OPLINE();
7895 do_bind_class(RT_CONSTANT(opline, opline->op1), (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL);
7896 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7897 }
7898
7899 ZEND_VM_HANDLER(145, ZEND_DECLARE_CLASS_DELAYED, CONST, CONST)
7900 {
7901 USE_OPLINE
7902
7903 zend_class_entry *ce = CACHED_PTR(opline->extended_value);
7904 if (ce == NULL) {
7905 zval *lcname = RT_CONSTANT(opline, opline->op1);
7906 zval *zv = zend_hash_find_known_hash(EG(class_table), Z_STR_P(lcname + 1));
7907 if (zv) {
7908 SAVE_OPLINE();
7909 ce = zend_bind_class_in_slot(zv, lcname, Z_STR_P(RT_CONSTANT(opline, opline->op2)));
7910 if (!ce) {
7911 HANDLE_EXCEPTION();
7912 }
7913 }
7914 CACHE_PTR(opline->extended_value, ce);
7915 }
7916 ZEND_VM_NEXT_OPCODE();
7917 }
7918
7919 ZEND_VM_HANDLER(146, ZEND_DECLARE_ANON_CLASS, ANY, ANY, CACHE_SLOT)
7920 {
7921 zval *zv;
7922 zend_class_entry *ce;
7923 USE_OPLINE
7924
7925 ce = CACHED_PTR(opline->extended_value);
7926 if (UNEXPECTED(ce == NULL)) {
7927 zend_string *rtd_key = Z_STR_P(RT_CONSTANT(opline, opline->op1));
7928 zv = zend_hash_find_known_hash(EG(class_table), rtd_key);
7929 ZEND_ASSERT(zv != NULL);
7930 ce = Z_CE_P(zv);
7931 if (!(ce->ce_flags & ZEND_ACC_LINKED)) {
7932 SAVE_OPLINE();
7933 ce = zend_do_link_class(ce, (OP2_TYPE == IS_CONST) ? Z_STR_P(RT_CONSTANT(opline, opline->op2)) : NULL, rtd_key);
7934 if (!ce) {
7935 HANDLE_EXCEPTION();
7936 }
7937 }
7938 CACHE_PTR(opline->extended_value, ce);
7939 }
7940 Z_CE_P(EX_VAR(opline->result.var)) = ce;
7941 ZEND_VM_NEXT_OPCODE();
7942 }
7943
7944 ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, NUM)
7945 {
7946 zend_function *func;
7947 USE_OPLINE
7948
7949 SAVE_OPLINE();
7950 func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num];
7951 do_bind_function(func, RT_CONSTANT(opline, opline->op1));
7952 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7953 }
7954
7955 ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM)
7956 {
7957 USE_OPLINE
7958
7959 if ((uint32_t)++EG(ticks_count) >= opline->extended_value) {
7960 EG(ticks_count) = 0;
7961 if (zend_ticks_function) {
7962 SAVE_OPLINE();
7963 zend_fiber_switch_block();
7964 zend_ticks_function(opline->extended_value);
7965 zend_fiber_switch_unblock();
7966 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
7967 }
7968 }
7969 ZEND_VM_NEXT_OPCODE();
7970 }
7971
7972 ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CLASS_FETCH|CONST|VAR, CACHE_SLOT)
7973 {
7974 USE_OPLINE
7975 zval *expr;
7976 bool result;
7977
7978 SAVE_OPLINE();
7979 expr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
7980
7981 ZEND_VM_C_LABEL(try_instanceof):
7982 if (Z_TYPE_P(expr) == IS_OBJECT) {
7983 zend_class_entry *ce;
7984
7985 if (OP2_TYPE == IS_CONST) {
7986 ce = CACHED_PTR(opline->extended_value);
7987 if (UNEXPECTED(ce == NULL)) {
7988 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);
7989 if (EXPECTED(ce)) {
7990 CACHE_PTR(opline->extended_value, ce);
7991 }
7992 }
7993 } else if (OP2_TYPE == IS_UNUSED) {
7994 ce = zend_fetch_class(NULL, opline->op2.num);
7995 if (UNEXPECTED(ce == NULL)) {
7996 FREE_OP1();
7997 ZVAL_UNDEF(EX_VAR(opline->result.var));
7998 HANDLE_EXCEPTION();
7999 }
8000 } else {
8001 ce = Z_CE_P(EX_VAR(opline->op2.var));
8002 }
8003 result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
8004 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
8005 expr = Z_REFVAL_P(expr);
8006 ZEND_VM_C_GOTO(try_instanceof);
8007 } else {
8008 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) {
8009 ZVAL_UNDEFINED_OP1();
8010 }
8011 result = 0;
8012 }
8013 FREE_OP1();
8014 ZEND_VM_SMART_BRANCH(result, 1);
8015 }
8016
8017 ZEND_VM_HOT_HANDLER(104, ZEND_EXT_NOP, ANY, ANY)
8018 {
8019 USE_OPLINE
8020
8021 ZEND_VM_NEXT_OPCODE();
8022 }
8023
8024 ZEND_VM_HOT_HANDLER(0, ZEND_NOP, ANY, ANY)
8025 {
8026 USE_OPLINE
8027
8028 ZEND_VM_NEXT_OPCODE();
8029 }
8030
ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper,ANY,ANY,uint32_t try_catch_offset,uint32_t op_num)8031 ZEND_VM_HELPER(zend_dispatch_try_catch_finally_helper, ANY, ANY, uint32_t try_catch_offset, uint32_t op_num)
8032 {
8033 /* May be NULL during generator closing (only finally blocks are executed) */
8034 zend_object *ex = EG(exception);
8035
8036 /* Walk try/catch/finally structures upwards, performing the necessary actions */
8037 for (; try_catch_offset != (uint32_t) -1; try_catch_offset--) {
8038 zend_try_catch_element *try_catch =
8039 &EX(func)->op_array.try_catch_array[try_catch_offset];
8040
8041 if (op_num < try_catch->catch_op && ex) {
8042 /* Go to catch block */
8043 cleanup_live_vars(execute_data, op_num, try_catch->catch_op);
8044 ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->catch_op], 0);
8045
8046 } else if (op_num < try_catch->finally_op) {
8047 if (ex && zend_is_unwind_exit(ex)) {
8048 /* Don't execute finally blocks on exit (for now) */
8049 continue;
8050 }
8051
8052 /* Go to finally block */
8053 zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var);
8054 cleanup_live_vars(execute_data, op_num, try_catch->finally_op);
8055 Z_OBJ_P(fast_call) = EG(exception);
8056 EG(exception) = NULL;
8057 Z_OPLINE_NUM_P(fast_call) = (uint32_t)-1;
8058 ZEND_VM_JMP_EX(&EX(func)->op_array.opcodes[try_catch->finally_op], 0);
8059
8060 } else if (op_num < try_catch->finally_end) {
8061 zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[try_catch->finally_end].op1.var);
8062
8063 /* cleanup incomplete RETURN statement */
8064 if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1
8065 && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) {
8066 zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var);
8067
8068 zval_ptr_dtor(return_value);
8069 }
8070
8071 /* Chain potential exception from wrapping finally block */
8072 if (Z_OBJ_P(fast_call)) {
8073 if (ex) {
8074 if (zend_is_unwind_exit(ex) || zend_is_graceful_exit(ex)) {
8075 /* discard the previously thrown exception */
8076 OBJ_RELEASE(Z_OBJ_P(fast_call));
8077 } else {
8078 zend_exception_set_previous(ex, Z_OBJ_P(fast_call));
8079 }
8080 } else {
8081 ex = EG(exception) = Z_OBJ_P(fast_call);
8082 }
8083 }
8084 }
8085 }
8086
8087 /* Uncaught exception */
8088
8089 /* Don't use ZEND_OBSERVER_ENABLED because it gets replaced by zend_vm_gen.php. */
8090 if (zend_observer_fcall_op_array_extension != -1) {
8091 zend_observer_fcall_end(execute_data, NULL);
8092 }
8093 cleanup_live_vars(execute_data, op_num, 0);
8094 if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) {
8095 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8096 EG(current_execute_data) = EX(prev_execute_data);
8097 zend_generator_close(generator, 1);
8098 ZEND_VM_RETURN();
8099 } else {
8100 /* We didn't execute RETURN, and have to initialize return_value */
8101 if (EX(return_value)) {
8102 ZVAL_UNDEF(EX(return_value));
8103 }
8104 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
8105 }
8106 }
8107
8108 ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
8109 {
8110 const zend_op *throw_op = EG(opline_before_exception);
8111
8112 /* Exception was thrown before executing any op */
8113 if (UNEXPECTED(!throw_op)) {
8114 ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, -1, op_num, 0);
8115 }
8116
8117 uint32_t throw_op_num = throw_op - EX(func)->op_array.opcodes;
8118 int i, current_try_catch_offset = -1;
8119
8120 if ((throw_op->opcode == ZEND_FREE || throw_op->opcode == ZEND_FE_FREE)
8121 && throw_op->extended_value & ZEND_FREE_ON_RETURN) {
8122 /* exceptions thrown because of loop var destruction on return/break/...
8123 * are logically thrown at the end of the foreach loop, so adjust the
8124 * throw_op_num.
8125 */
8126 const zend_live_range *range = find_live_range(
8127 &EX(func)->op_array, throw_op_num, throw_op->op1.var);
8128 /* free op1 of the corresponding RETURN */
8129 for (i = throw_op_num; i < range->end; i++) {
8130 if (EX(func)->op_array.opcodes[i].opcode == ZEND_FREE
8131 || EX(func)->op_array.opcodes[i].opcode == ZEND_FE_FREE) {
8132 /* pass */
8133 } else {
8134 if (EX(func)->op_array.opcodes[i].opcode == ZEND_RETURN
8135 && (EX(func)->op_array.opcodes[i].op1_type & (IS_VAR|IS_TMP_VAR))) {
8136 zval_ptr_dtor(EX_VAR(EX(func)->op_array.opcodes[i].op1.var));
8137 }
8138 break;
8139 }
8140 }
8141 throw_op_num = range->end;
8142 }
8143
8144 /* Find the innermost try/catch/finally the exception was thrown in */
8145 for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
8146 zend_try_catch_element *try_catch = &EX(func)->op_array.try_catch_array[i];
8147 if (try_catch->try_op > throw_op_num) {
8148 /* further blocks will not be relevant... */
8149 break;
8150 }
8151 if (throw_op_num < try_catch->catch_op || throw_op_num < try_catch->finally_end) {
8152 current_try_catch_offset = i;
8153 }
8154 }
8155
8156 cleanup_unfinished_calls(execute_data, throw_op_num);
8157
8158 if (throw_op->result_type & (IS_VAR | IS_TMP_VAR)) {
8159 switch (throw_op->opcode) {
8160 case ZEND_ADD_ARRAY_ELEMENT:
8161 case ZEND_ADD_ARRAY_UNPACK:
8162 case ZEND_ROPE_INIT:
8163 case ZEND_ROPE_ADD:
8164 break; /* exception while building structures, live range handling will free those */
8165
8166 case ZEND_FETCH_CLASS:
8167 case ZEND_DECLARE_ANON_CLASS:
8168 break; /* return value is zend_class_entry pointer */
8169
8170 default:
8171 /* smart branch opcodes may not initialize result */
8172 if (!zend_is_smart_branch(throw_op)) {
8173 zval_ptr_dtor_nogc(EX_VAR(throw_op->result.var));
8174 }
8175 }
8176 }
8177
8178 ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, current_try_catch_offset, op_num, throw_op_num);
8179 }
8180
8181 ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
8182 {
8183 USE_OPLINE
8184 int ret;
8185
8186 SAVE_OPLINE();
8187 ret = zend_user_opcode_handlers[opline->opcode](execute_data);
8188 opline = EX(opline);
8189
8190 switch (ret) {
8191 case ZEND_USER_OPCODE_CONTINUE:
8192 ZEND_VM_CONTINUE();
8193 case ZEND_USER_OPCODE_RETURN:
8194 if (UNEXPECTED((EX_CALL_INFO() & ZEND_CALL_GENERATOR) != 0)) {
8195 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8196 EG(current_execute_data) = EX(prev_execute_data);
8197 zend_generator_close(generator, 1);
8198 ZEND_VM_RETURN();
8199 } else {
8200 ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
8201 }
8202 case ZEND_USER_OPCODE_ENTER:
8203 ZEND_VM_ENTER();
8204 case ZEND_USER_OPCODE_LEAVE:
8205 ZEND_VM_LEAVE();
8206 case ZEND_USER_OPCODE_DISPATCH:
8207 ZEND_VM_DISPATCH(opline->opcode, opline);
8208 default:
8209 ZEND_VM_DISPATCH((uint8_t)(ret & 0xff), opline);
8210 }
8211 }
8212
8213 ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST)
8214 {
8215 USE_OPLINE
8216 zval *name;
8217 zval *val;
8218 zend_constant c;
8219
8220 SAVE_OPLINE();
8221 name = GET_OP1_ZVAL_PTR(BP_VAR_R);
8222 val = GET_OP2_ZVAL_PTR(BP_VAR_R);
8223
8224 ZVAL_COPY(&c.value, val);
8225 if (Z_OPT_CONSTANT(c.value)) {
8226 if (UNEXPECTED(zval_update_constant_ex(&c.value, EX(func)->op_array.scope) != SUCCESS)) {
8227 zval_ptr_dtor_nogc(&c.value);
8228 FREE_OP1();
8229 FREE_OP2();
8230 HANDLE_EXCEPTION();
8231 }
8232 }
8233 /* non persistent, case sensitive */
8234 ZEND_CONSTANT_SET_FLAGS(&c, 0, PHP_USER_CONSTANT);
8235 c.name = zend_string_copy(Z_STR_P(name));
8236
8237 if (zend_register_constant(&c) == FAILURE) {
8238 }
8239
8240 FREE_OP1();
8241 FREE_OP2();
8242 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8243 }
8244
8245 ZEND_VM_HANDLER(142, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, NUM)
8246 {
8247 USE_OPLINE
8248 zend_function *func;
8249 zval *object;
8250 zend_class_entry *called_scope;
8251
8252 func = (zend_function *) EX(func)->op_array.dynamic_func_defs[opline->op2.num];
8253 if (Z_TYPE(EX(This)) == IS_OBJECT) {
8254 called_scope = Z_OBJCE(EX(This));
8255 if (UNEXPECTED((func->common.fn_flags & ZEND_ACC_STATIC) ||
8256 (EX(func)->common.fn_flags & ZEND_ACC_STATIC))) {
8257 object = NULL;
8258 } else {
8259 object = &EX(This);
8260 }
8261 } else {
8262 called_scope = Z_CE(EX(This));
8263 object = NULL;
8264 }
8265 SAVE_OPLINE();
8266 zend_create_closure(EX_VAR(opline->result.var), func,
8267 EX(func)->op_array.scope, called_scope, object);
8268
8269 ZEND_VM_NEXT_OPCODE();
8270 }
8271
8272 ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
8273 {
8274 USE_OPLINE
8275 zval *var_ptr;
8276
8277 var_ptr = EX_VAR(opline->op1.var);
8278 if (UNEXPECTED(Z_ISREF_P(var_ptr))) {
8279 if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) {
8280 ZVAL_UNREF(var_ptr);
8281 }
8282 }
8283
8284 ZEND_VM_NEXT_OPCODE();
8285 }
8286
ZEND_VM_COLD_HELPER(zend_yield_in_closed_generator_helper,ANY,ANY)8287 ZEND_VM_COLD_HELPER(zend_yield_in_closed_generator_helper, ANY, ANY)
8288 {
8289 USE_OPLINE
8290
8291 SAVE_OPLINE();
8292 zend_throw_error(NULL, "Cannot yield from finally in a force-closed generator");
8293 FREE_OP2();
8294 FREE_OP1();
8295 UNDEF_RESULT();
8296 HANDLE_EXCEPTION();
8297 }
8298
8299 ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED, SRC)
8300 {
8301 USE_OPLINE
8302
8303 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8304
8305 SAVE_OPLINE();
8306 if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
8307 ZEND_VM_DISPATCH_TO_HELPER(zend_yield_in_closed_generator_helper);
8308 }
8309
8310 /* Destroy the previously yielded value */
8311 zval_ptr_dtor(&generator->value);
8312
8313 /* Destroy the previously yielded key */
8314 zval_ptr_dtor(&generator->key);
8315
8316 /* Set the new yielded value */
8317 if (OP1_TYPE != IS_UNUSED) {
8318 if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
8319 /* Constants and temporary variables aren't yieldable by reference,
8320 * but we still allow them with a notice. */
8321 if (OP1_TYPE & (IS_CONST|IS_TMP_VAR)) {
8322 zval *value;
8323
8324 zend_error(E_NOTICE, "Only variable references should be yielded by reference");
8325
8326 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
8327 ZVAL_COPY_VALUE(&generator->value, value);
8328 if (OP1_TYPE == IS_CONST) {
8329 if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) {
8330 Z_ADDREF(generator->value);
8331 }
8332 }
8333 } else {
8334 zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
8335
8336 /* If a function call result is yielded and the function did
8337 * not return by reference we throw a notice. */
8338 do {
8339 if (OP1_TYPE == IS_VAR) {
8340 ZEND_ASSERT(value_ptr != &EG(uninitialized_zval));
8341 if (opline->extended_value == ZEND_RETURNS_FUNCTION
8342 && !Z_ISREF_P(value_ptr)) {
8343 zend_error(E_NOTICE, "Only variable references should be yielded by reference");
8344 ZVAL_COPY(&generator->value, value_ptr);
8345 break;
8346 }
8347 }
8348 if (Z_ISREF_P(value_ptr)) {
8349 Z_ADDREF_P(value_ptr);
8350 } else {
8351 ZVAL_MAKE_REF_EX(value_ptr, 2);
8352 }
8353 ZVAL_REF(&generator->value, Z_REF_P(value_ptr));
8354 } while (0);
8355
8356 FREE_OP1();
8357 }
8358 } else {
8359 zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
8360
8361 /* Consts, temporary variables and references need copying */
8362 if (OP1_TYPE == IS_CONST) {
8363 ZVAL_COPY_VALUE(&generator->value, value);
8364 if (UNEXPECTED(Z_OPT_REFCOUNTED(generator->value))) {
8365 Z_ADDREF(generator->value);
8366 }
8367 } else if (OP1_TYPE == IS_TMP_VAR) {
8368 ZVAL_COPY_VALUE(&generator->value, value);
8369 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
8370 ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
8371 FREE_OP1_IF_VAR();
8372 } else {
8373 ZVAL_COPY_VALUE(&generator->value, value);
8374 if (OP1_TYPE == IS_CV) {
8375 if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
8376 }
8377 }
8378 }
8379 } else {
8380 /* If no value was specified yield null */
8381 ZVAL_NULL(&generator->value);
8382 }
8383
8384 /* Set the new yielded key */
8385 if (OP2_TYPE != IS_UNUSED) {
8386 zval *key = GET_OP2_ZVAL_PTR(BP_VAR_R);
8387 if ((OP2_TYPE & (IS_CV|IS_VAR)) && UNEXPECTED(Z_TYPE_P(key) == IS_REFERENCE)) {
8388 key = Z_REFVAL_P(key);
8389 }
8390 ZVAL_COPY(&generator->key, key);
8391 FREE_OP2();
8392
8393 if (Z_TYPE(generator->key) == IS_LONG
8394 && Z_LVAL(generator->key) > generator->largest_used_integer_key
8395 ) {
8396 generator->largest_used_integer_key = Z_LVAL(generator->key);
8397 }
8398 } else {
8399 /* If no key was specified we use auto-increment keys */
8400 generator->largest_used_integer_key++;
8401 ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
8402 }
8403
8404 if (RETURN_VALUE_USED(opline)) {
8405 /* If the return value of yield is used set the send
8406 * target and initialize it to NULL */
8407 generator->send_target = EX_VAR(opline->result.var);
8408 ZVAL_NULL(generator->send_target);
8409 } else {
8410 generator->send_target = NULL;
8411 }
8412
8413 /* The GOTO VM uses a local opline variable. We need to set the opline
8414 * variable in execute_data so we don't resume at an old position. */
8415 SAVE_OPLINE();
8416
8417 ZEND_VM_RETURN();
8418 }
8419
8420 ZEND_VM_HANDLER(166, ZEND_YIELD_FROM, CONST|TMPVAR|CV, ANY)
8421 {
8422 USE_OPLINE
8423 zend_generator *generator = zend_get_running_generator(EXECUTE_DATA_C);
8424 zval *val;
8425
8426 SAVE_OPLINE();
8427 val = GET_OP1_ZVAL_PTR(BP_VAR_R);
8428
8429 if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
8430 zend_throw_error(NULL, "Cannot use \"yield from\" in a force-closed generator");
8431 FREE_OP1();
8432 UNDEF_RESULT();
8433 HANDLE_EXCEPTION();
8434 }
8435
8436 ZEND_VM_C_LABEL(yield_from_try_again):
8437 if (Z_TYPE_P(val) == IS_ARRAY) {
8438 ZVAL_COPY_VALUE(&generator->values, val);
8439 if (Z_OPT_REFCOUNTED_P(val)) {
8440 Z_ADDREF_P(val);
8441 }
8442 Z_FE_POS(generator->values) = 0;
8443 FREE_OP1();
8444 } else if (OP1_TYPE != IS_CONST && Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val)->get_iterator) {
8445 zend_class_entry *ce = Z_OBJCE_P(val);
8446 if (ce == zend_ce_generator) {
8447 zend_generator *new_gen = (zend_generator *) Z_OBJ_P(val);
8448
8449 Z_ADDREF_P(val);
8450 FREE_OP1();
8451
8452 if (UNEXPECTED(new_gen->execute_data == NULL)) {
8453 zend_throw_error(NULL, "Generator passed to yield from was aborted without proper return and is unable to continue");
8454 zval_ptr_dtor(val);
8455 UNDEF_RESULT();
8456 HANDLE_EXCEPTION();
8457 } else if (Z_ISUNDEF(new_gen->retval)) {
8458 if (UNEXPECTED(zend_generator_get_current(new_gen) == generator)) {
8459 zend_throw_error(NULL, "Impossible to yield from the Generator being currently run");
8460 zval_ptr_dtor(val);
8461 UNDEF_RESULT();
8462 HANDLE_EXCEPTION();
8463 } else {
8464 zend_generator_yield_from(generator, new_gen);
8465 }
8466 } else {
8467 if (RETURN_VALUE_USED(opline)) {
8468 ZVAL_COPY(EX_VAR(opline->result.var), &new_gen->retval);
8469 }
8470 ZEND_VM_NEXT_OPCODE();
8471 }
8472 } else {
8473 zend_object_iterator *iter = ce->get_iterator(ce, val, 0);
8474 FREE_OP1();
8475
8476 if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) {
8477 if (!EG(exception)) {
8478 zend_throw_error(NULL, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name));
8479 }
8480 UNDEF_RESULT();
8481 HANDLE_EXCEPTION();
8482 }
8483
8484 iter->index = 0;
8485 if (iter->funcs->rewind) {
8486 iter->funcs->rewind(iter);
8487 if (UNEXPECTED(EG(exception) != NULL)) {
8488 OBJ_RELEASE(&iter->std);
8489 UNDEF_RESULT();
8490 HANDLE_EXCEPTION();
8491 }
8492 }
8493
8494 ZVAL_OBJ(&generator->values, &iter->std);
8495 }
8496 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(val) == IS_REFERENCE) {
8497 val = Z_REFVAL_P(val);
8498 ZEND_VM_C_GOTO(yield_from_try_again);
8499 } else {
8500 zend_throw_error(NULL, "Can use \"yield from\" only with arrays and Traversables");
8501 FREE_OP1();
8502 UNDEF_RESULT();
8503 HANDLE_EXCEPTION();
8504 }
8505
8506 /* This is the default return value
8507 * when the expression is a Generator, it will be overwritten in zend_generator_resume() */
8508 if (RETURN_VALUE_USED(opline)) {
8509 ZVAL_NULL(EX_VAR(opline->result.var));
8510 }
8511
8512 /* This generator has no send target (though the generator we delegate to might have one) */
8513 generator->send_target = NULL;
8514
8515 /* The GOTO VM uses a local opline variable. We need to set the opline
8516 * variable in execute_data so we don't resume at an old position. */
8517 SAVE_OPLINE();
8518
8519 ZEND_VM_RETURN();
8520 }
8521
8522 ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
8523 {
8524 USE_OPLINE
8525 zval *fast_call = EX_VAR(opline->op1.var);
8526 SAVE_OPLINE();
8527
8528 /* cleanup incomplete RETURN statement */
8529 if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1
8530 && (EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2_type & (IS_TMP_VAR | IS_VAR))) {
8531 zval *return_value = EX_VAR(EX(func)->op_array.opcodes[Z_OPLINE_NUM_P(fast_call)].op2.var);
8532
8533 zval_ptr_dtor(return_value);
8534 }
8535
8536 /* cleanup delayed exception */
8537 if (Z_OBJ_P(fast_call) != NULL) {
8538 /* discard the previously thrown exception */
8539 OBJ_RELEASE(Z_OBJ_P(fast_call));
8540 Z_OBJ_P(fast_call) = NULL;
8541 }
8542
8543 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8544 }
8545
8546 ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, ANY)
8547 {
8548 USE_OPLINE
8549 zval *fast_call = EX_VAR(opline->result.var);
8550
8551 Z_OBJ_P(fast_call) = NULL;
8552 /* set return address */
8553 Z_OPLINE_NUM_P(fast_call) = opline - EX(func)->op_array.opcodes;
8554 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op1), 0);
8555 }
8556
8557 ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH)
8558 {
8559 USE_OPLINE
8560 zval *fast_call = EX_VAR(opline->op1.var);
8561 uint32_t current_try_catch_offset, current_op_num;
8562
8563 if (Z_OPLINE_NUM_P(fast_call) != (uint32_t)-1) {
8564 const zend_op *fast_ret = EX(func)->op_array.opcodes + Z_OPLINE_NUM_P(fast_call);
8565
8566 ZEND_VM_JMP_EX(fast_ret + 1, 0);
8567 }
8568
8569 /* special case for unhandled exceptions */
8570 EG(exception) = Z_OBJ_P(fast_call);
8571 Z_OBJ_P(fast_call) = NULL;
8572 current_try_catch_offset = opline->op2.num;
8573 current_op_num = opline - EX(func)->op_array.opcodes;
8574 ZEND_VM_DISPATCH_TO_HELPER(zend_dispatch_try_catch_finally_helper, try_catch_offset, current_try_catch_offset, op_num, current_op_num);
8575 }
8576
8577 ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT)
8578 {
8579 USE_OPLINE
8580 zend_string *varname;
8581 zval *value;
8582 zval *variable_ptr;
8583 uintptr_t idx;
8584 zend_reference *ref;
8585
8586 ZEND_VM_REPEATABLE_OPCODE
8587
8588 varname = Z_STR_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
8589
8590 /* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
8591 idx = (uintptr_t)CACHED_PTR(opline->extended_value) - 1;
8592 if (EXPECTED(idx < EG(symbol_table).nNumUsed * sizeof(Bucket))) {
8593 Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx);
8594
8595 if (EXPECTED(p->key == varname) ||
8596 (EXPECTED(p->h == ZSTR_H(varname)) &&
8597 EXPECTED(p->key != NULL) &&
8598 EXPECTED(zend_string_equal_content(p->key, varname)))) {
8599
8600 value = (zval*)p; /* value = &p->val; */
8601 ZEND_VM_C_GOTO(check_indirect);
8602 }
8603 }
8604
8605 value = zend_hash_find_known_hash(&EG(symbol_table), varname);
8606 if (UNEXPECTED(value == NULL)) {
8607 value = zend_hash_add_new(&EG(symbol_table), varname, &EG(uninitialized_zval));
8608 idx = (char*)value - (char*)EG(symbol_table).arData;
8609 /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
8610 CACHE_PTR(opline->extended_value, (void*)(idx + 1));
8611 } else {
8612 idx = (char*)value - (char*)EG(symbol_table).arData;
8613 /* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
8614 CACHE_PTR(opline->extended_value, (void*)(idx + 1));
8615 ZEND_VM_C_LABEL(check_indirect):
8616 /* GLOBAL variable may be an INDIRECT pointer to CV */
8617 if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
8618 value = Z_INDIRECT_P(value);
8619 if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
8620 ZVAL_NULL(value);
8621 }
8622 }
8623 }
8624
8625 if (UNEXPECTED(!Z_ISREF_P(value))) {
8626 ZVAL_MAKE_REF_EX(value, 2);
8627 ref = Z_REF_P(value);
8628 } else {
8629 ref = Z_REF_P(value);
8630 GC_ADDREF(ref);
8631 }
8632
8633 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
8634
8635 if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
8636 zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
8637
8638 ZVAL_REF(variable_ptr, ref);
8639 SAVE_OPLINE();
8640 if (GC_DELREF(garbage) == 0) {
8641 rc_dtor_func(garbage);
8642 if (UNEXPECTED(EG(exception))) {
8643 ZVAL_NULL(variable_ptr);
8644 HANDLE_EXCEPTION();
8645 }
8646 } else {
8647 gc_check_possible_root(garbage);
8648 }
8649 } else {
8650 ZVAL_REF(variable_ptr, ref);
8651 }
8652
8653 ZEND_VM_REPEAT_OPCODE(ZEND_BIND_GLOBAL);
8654 ZEND_VM_NEXT_OPCODE();
8655 }
8656
8657 ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
8658 {
8659 USE_OPLINE
8660 zval *value;
8661
8662 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
8663 if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
8664 ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
8665 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
8666 zval_ptr_dtor_str(value);
8667 }
8668 ZEND_VM_NEXT_OPCODE();
8669 } else {
8670 bool strict;
8671
8672 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
8673 value = Z_REFVAL_P(value);
8674 if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
8675 ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
8676 FREE_OP1();
8677 ZEND_VM_NEXT_OPCODE();
8678 }
8679 }
8680
8681 SAVE_OPLINE();
8682 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
8683 value = ZVAL_UNDEFINED_OP1();
8684 }
8685 strict = EX_USES_STRICT_TYPES();
8686 do {
8687 if (EXPECTED(!strict)) {
8688 zend_string *str;
8689 zval tmp;
8690
8691 if (UNEXPECTED(Z_TYPE_P(value) == IS_NULL)) {
8692 zend_error(E_DEPRECATED,
8693 "strlen(): Passing null to parameter #1 ($string) of type string is deprecated");
8694 ZVAL_LONG(EX_VAR(opline->result.var), 0);
8695 if (UNEXPECTED(EG(exception))) {
8696 HANDLE_EXCEPTION();
8697 }
8698 break;
8699 }
8700
8701 ZVAL_COPY(&tmp, value);
8702 if (zend_parse_arg_str_weak(&tmp, &str, 1)) {
8703 ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str));
8704 zval_ptr_dtor(&tmp);
8705 break;
8706 }
8707 zval_ptr_dtor(&tmp);
8708 }
8709 if (!EG(exception)) {
8710 zend_type_error("strlen(): Argument #1 ($string) must be of type string, %s given", zend_zval_value_name(value));
8711 }
8712 ZVAL_UNDEF(EX_VAR(opline->result.var));
8713 } while (0);
8714 }
8715 FREE_OP1();
8716 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8717 }
8718
8719 ZEND_VM_HOT_NOCONST_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMPVAR|CV, ANY, TYPE_MASK)
8720 {
8721 USE_OPLINE
8722 zval *value;
8723 int result = 0;
8724
8725 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
8726 if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
8727 ZEND_VM_C_LABEL(type_check_resource):
8728 if (opline->extended_value != MAY_BE_RESOURCE
8729 || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) {
8730 result = 1;
8731 }
8732 } else if ((OP1_TYPE & (IS_CV|IS_VAR)) && Z_ISREF_P(value)) {
8733 value = Z_REFVAL_P(value);
8734 if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) {
8735 ZEND_VM_C_GOTO(type_check_resource);
8736 }
8737 } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
8738 result = ((1 << IS_NULL) & opline->extended_value) != 0;
8739 SAVE_OPLINE();
8740 ZVAL_UNDEFINED_OP1();
8741 if (UNEXPECTED(EG(exception))) {
8742 ZVAL_UNDEF(EX_VAR(opline->result.var));
8743 HANDLE_EXCEPTION();
8744 }
8745 }
8746 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
8747 SAVE_OPLINE();
8748 FREE_OP1();
8749 ZEND_VM_SMART_BRANCH(result, 1);
8750 } else {
8751 ZEND_VM_SMART_BRANCH(result, 0);
8752 }
8753 }
8754
8755 ZEND_VM_HOT_HANDLER(122, ZEND_DEFINED, CONST, ANY, CACHE_SLOT)
8756 {
8757 USE_OPLINE
8758 zend_constant *c;
8759
8760 c = CACHED_PTR(opline->extended_value);
8761 if (EXPECTED(c != NULL)) {
8762 if (!IS_SPECIAL_CACHE_VAL(c)) {
8763 ZEND_VM_C_LABEL(defined_true):
8764 ZEND_VM_SMART_BRANCH_TRUE();
8765 } else if (EXPECTED(zend_hash_num_elements(EG(zend_constants)) == DECODE_SPECIAL_CACHE_NUM(c))) {
8766 ZEND_VM_C_LABEL(defined_false):
8767 ZEND_VM_SMART_BRANCH_FALSE();
8768 }
8769 }
8770 if (zend_quick_check_constant(RT_CONSTANT(opline, opline->op1) OPLINE_CC EXECUTE_DATA_CC) != SUCCESS) {
8771 CACHE_PTR(opline->extended_value, ENCODE_SPECIAL_CACHE_NUM(zend_hash_num_elements(EG(zend_constants))));
8772 ZEND_VM_C_GOTO(defined_false);
8773 } else {
8774 ZEND_VM_C_GOTO(defined_true);
8775 }
8776 }
8777
8778 ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
8779 {
8780 USE_OPLINE
8781
8782 if (EG(assertions) <= 0) {
8783 zend_op *target = OP_JMP_ADDR(opline, opline->op2);
8784 if (RETURN_VALUE_USED(opline)) {
8785 ZVAL_TRUE(EX_VAR(opline->result.var));
8786 }
8787 ZEND_VM_JMP_EX(target, 0);
8788 } else {
8789 ZEND_VM_NEXT_OPCODE();
8790 }
8791 }
8792
8793 ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, CV|TMPVAR|UNUSED|CLASS_FETCH, ANY)
8794 {
8795 uint32_t fetch_type;
8796 zend_class_entry *called_scope, *scope;
8797 USE_OPLINE
8798
8799 if (OP1_TYPE != IS_UNUSED) {
8800 SAVE_OPLINE();
8801 zval *op = GET_OP1_ZVAL_PTR(BP_VAR_R);
8802 if (UNEXPECTED(Z_TYPE_P(op) != IS_OBJECT)) {
8803 ZVAL_DEREF(op);
8804 if (Z_TYPE_P(op) != IS_OBJECT) {
8805 zend_type_error("Cannot use \"::class\" on %s", zend_zval_value_name(op));
8806 ZVAL_UNDEF(EX_VAR(opline->result.var));
8807 FREE_OP1();
8808 HANDLE_EXCEPTION();
8809 }
8810 }
8811
8812 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op)->name);
8813 FREE_OP1();
8814 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
8815 }
8816
8817 fetch_type = opline->op1.num;
8818 scope = EX(func)->op_array.scope;
8819 if (UNEXPECTED(scope == NULL)) {
8820 SAVE_OPLINE();
8821 zend_throw_error(NULL, "Cannot use \"%s\" in the global scope",
8822 fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
8823 fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
8824 ZVAL_UNDEF(EX_VAR(opline->result.var));
8825 HANDLE_EXCEPTION();
8826 }
8827
8828 switch (fetch_type) {
8829 case ZEND_FETCH_CLASS_SELF:
8830 ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->name);
8831 break;
8832 case ZEND_FETCH_CLASS_PARENT:
8833 if (UNEXPECTED(scope->parent == NULL)) {
8834 SAVE_OPLINE();
8835 zend_throw_error(NULL,
8836 "Cannot use \"parent\" when current class scope has no parent");
8837 ZVAL_UNDEF(EX_VAR(opline->result.var));
8838 HANDLE_EXCEPTION();
8839 }
8840 ZVAL_STR_COPY(EX_VAR(opline->result.var), scope->parent->name);
8841 break;
8842 case ZEND_FETCH_CLASS_STATIC:
8843 if (Z_TYPE(EX(This)) == IS_OBJECT) {
8844 called_scope = Z_OBJCE(EX(This));
8845 } else {
8846 called_scope = Z_CE(EX(This));
8847 }
8848 ZVAL_STR_COPY(EX_VAR(opline->result.var), called_scope->name);
8849 break;
8850 EMPTY_SWITCH_DEFAULT_CASE()
8851 }
8852 ZEND_VM_NEXT_OPCODE();
8853 }
8854
8855 ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
8856 {
8857 zend_array *args = NULL;
8858 zend_function *fbc = EX(func);
8859 zval *ret = EX(return_value);
8860 uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS | ZEND_CALL_HAS_EXTRA_NAMED_PARAMS);
8861 uint32_t num_args = EX_NUM_ARGS();
8862 zend_execute_data *call;
8863
8864 SAVE_OPLINE();
8865
8866 if (num_args) {
8867 zval *p = ZEND_CALL_ARG(execute_data, 1);
8868 zval *end = p + num_args;
8869
8870 args = zend_new_array(num_args);
8871 zend_hash_real_init_packed(args);
ZEND_HASH_FILL_PACKED(args)8872 ZEND_HASH_FILL_PACKED(args) {
8873 do {
8874 ZEND_HASH_FILL_ADD(p);
8875 p++;
8876 } while (p != end);
8877 } ZEND_HASH_FILL_END();
8878 }
8879
8880 call = execute_data;
8881 execute_data = EG(current_execute_data) = EX(prev_execute_data);
8882
8883 call->func = (fbc->op_array.fn_flags & ZEND_ACC_STATIC) ? fbc->op_array.scope->__callstatic : fbc->op_array.scope->__call;
8884 ZEND_ASSERT(zend_vm_calc_used_stack(2, call->func) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call));
8885 ZEND_CALL_NUM_ARGS(call) = 2;
8886
8887 ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name);
8888
8889 zval *call_args = ZEND_CALL_ARG(call, 2);
8890 if (args) {
8891 ZVAL_ARR(call_args, args);
8892 } else {
8893 ZVAL_EMPTY_ARRAY(call_args);
8894 }
8895 if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
8896 if (zend_hash_num_elements(Z_ARRVAL_P(call_args)) == 0) {
8897 GC_ADDREF(call->extra_named_params);
8898 ZVAL_ARR(call_args, call->extra_named_params);
8899 } else {
8900 SEPARATE_ARRAY(call_args);
8901 zend_hash_copy(Z_ARRVAL_P(call_args), call->extra_named_params, zval_add_ref);
8902 }
8903 }
8904 zend_free_trampoline(fbc);
8905 fbc = call->func;
8906
8907 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
8908 if (UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
8909 init_func_run_time_cache(&fbc->op_array);
8910 }
8911 execute_data = call;
8912 i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC);
8913 if (EXPECTED(zend_execute_ex == execute_ex)) {
8914 LOAD_OPLINE_EX();
8915 ZEND_OBSERVER_SAVE_OPLINE();
8916 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
8917 ZEND_VM_ENTER_EX();
8918 } else {
8919 SAVE_OPLINE_EX();
8920 ZEND_OBSERVER_FCALL_BEGIN(execute_data);
8921 execute_data = EX(prev_execute_data);
8922 if (execute_data) {
8923 LOAD_OPLINE();
8924 }
8925 ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
8926 zend_execute_ex(call);
8927 }
8928 } else {
8929 zval retval;
8930
8931 ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
8932
8933 EG(current_execute_data) = call;
8934
8935 #if ZEND_DEBUG
8936 bool should_throw = zend_internal_call_should_throw(fbc, call);
8937 #endif
8938
8939 if (ret == NULL) {
8940 ret = &retval;
8941 }
8942
8943 ZVAL_NULL(ret);
8944 ZEND_OBSERVER_FCALL_BEGIN(call);
8945 if (!zend_execute_internal) {
8946 /* saves one function call if zend_execute_internal is not used */
8947 fbc->internal_function.handler(call, ret);
8948 } else {
8949 zend_execute_internal(call, ret);
8950 }
8951
8952 #if ZEND_DEBUG
8953 if (!EG(exception) && call->func) {
8954 if (should_throw) {
8955 zend_internal_call_arginfo_violation(call->func);
8956 }
8957 ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
8958 zend_verify_internal_return_type(call->func, ret));
8959 ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)
8960 ? Z_ISREF_P(ret) : !Z_ISREF_P(ret));
8961 zend_verify_internal_func_info(call->func, ret);
8962 }
8963 #endif
8964 ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
8965
8966 EG(current_execute_data) = call->prev_execute_data;
8967
8968 zend_vm_stack_free_args(call);
8969 if (UNEXPECTED(call_info & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
8970 zend_free_extra_named_params(call->extra_named_params);
8971 }
8972 if (ret == &retval) {
8973 zval_ptr_dtor(ret);
8974 }
8975 }
8976
8977 execute_data = EG(current_execute_data);
8978
8979 if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
8980 ZEND_VM_RETURN();
8981 }
8982
8983 if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) {
8984 zend_object *object = Z_OBJ(call->This);
8985 OBJ_RELEASE(object);
8986 }
8987 zend_vm_stack_free_call_frame(call);
8988
8989 if (UNEXPECTED(EG(exception) != NULL)) {
8990 zend_rethrow_exception(execute_data);
8991 HANDLE_EXCEPTION_LEAVE();
8992 }
8993
8994 LOAD_OPLINE();
8995 ZEND_VM_INC_OPCODE();
8996 ZEND_VM_LEAVE();
8997 }
8998
8999 ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF)
9000 {
9001 USE_OPLINE
9002 zval *closure, *var;
9003
9004 closure = GET_OP1_ZVAL_PTR(BP_VAR_R);
9005 if (opline->extended_value & ZEND_BIND_REF) {
9006 /* By-ref binding */
9007 var = GET_OP2_ZVAL_PTR(BP_VAR_W);
9008 if (Z_ISREF_P(var)) {
9009 Z_ADDREF_P(var);
9010 } else {
9011 ZVAL_MAKE_REF_EX(var, 2);
9012 }
9013 } else {
9014 var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9015 if (UNEXPECTED(Z_ISUNDEF_P(var)) && !(opline->extended_value & ZEND_BIND_IMPLICIT)) {
9016 SAVE_OPLINE();
9017 var = ZVAL_UNDEFINED_OP2();
9018 if (UNEXPECTED(EG(exception))) {
9019 HANDLE_EXCEPTION();
9020 }
9021 }
9022 ZVAL_DEREF(var);
9023 Z_TRY_ADDREF_P(var);
9024 }
9025
9026 zend_closure_bind_var_ex(closure,
9027 (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT)), var);
9028 ZEND_VM_NEXT_OPCODE();
9029 }
9030
9031 ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, ANY, REF)
9032 {
9033 USE_OPLINE
9034 HashTable *ht;
9035 zval *value;
9036 zval *variable_ptr;
9037
9038 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
9039
9040 SAVE_OPLINE();
9041
9042 ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
9043 if (!ht) {
9044 ht = zend_array_dup(EX(func)->op_array.static_variables);
9045 ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht);
9046 }
9047 ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
9048
9049 value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT|ZEND_BIND_EXPLICIT)));
9050
9051 if (opline->extended_value & ZEND_BIND_REF) {
9052 i_zval_ptr_dtor(variable_ptr);
9053 if (UNEXPECTED(!Z_ISREF_P(value))) {
9054 zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference));
9055 GC_SET_REFCOUNT(ref, 2);
9056 GC_TYPE_INFO(ref) = GC_REFERENCE;
9057 if (OP2_TYPE == IS_UNUSED) {
9058 ZVAL_COPY_VALUE(&ref->val, value);
9059 } else {
9060 ZEND_ASSERT(!Z_REFCOUNTED_P(value));
9061 ZVAL_COPY(&ref->val, GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R));
9062 FREE_OP2();
9063 }
9064 ref->sources.ptr = NULL;
9065 Z_REF_P(value) = ref;
9066 Z_TYPE_INFO_P(value) = IS_REFERENCE_EX;
9067 ZVAL_REF(variable_ptr, ref);
9068 } else {
9069 Z_ADDREF_P(value);
9070 ZVAL_REF(variable_ptr, Z_REF_P(value));
9071 if (OP2_TYPE != IS_UNUSED) {
9072 FREE_OP2();
9073 }
9074 }
9075 } else {
9076 i_zval_ptr_dtor(variable_ptr);
9077 ZVAL_COPY(variable_ptr, value);
9078 }
9079
9080 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9081 }
9082
9083 ZEND_VM_HANDLER(203, ZEND_BIND_INIT_STATIC_OR_JMP, CV, JMP_ADDR)
9084 {
9085 USE_OPLINE
9086 HashTable *ht;
9087 zval *value;
9088 zval *variable_ptr;
9089
9090 variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
9091
9092 ht = ZEND_MAP_PTR_GET(EX(func)->op_array.static_variables_ptr);
9093 if (!ht) {
9094 ZEND_VM_NEXT_OPCODE();
9095 }
9096 ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
9097
9098 value = (zval*)((char*)ht->arData + opline->extended_value);
9099 if (Z_TYPE_P(value) == IS_NULL) {
9100 ZEND_VM_NEXT_OPCODE();
9101 } else {
9102 SAVE_OPLINE();
9103 zval_ptr_dtor(variable_ptr);
9104 ZEND_ASSERT(Z_TYPE_P(value) == IS_REFERENCE);
9105 Z_ADDREF_P(value);
9106 ZVAL_REF(variable_ptr, Z_REF_P(value));
9107 ZEND_VM_JMP_EX(OP_JMP_ADDR(opline, opline->op2), 1);
9108 }
9109 }
9110
9111 ZEND_VM_HOT_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED)
9112 {
9113 USE_OPLINE
9114
9115 if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
9116 zval *result = EX_VAR(opline->result.var);
9117
9118 ZVAL_OBJ(result, Z_OBJ(EX(This)));
9119 Z_ADDREF_P(result);
9120 ZEND_VM_NEXT_OPCODE();
9121 } else {
9122 ZEND_VM_DISPATCH_TO_HELPER(zend_this_not_in_object_context_helper);
9123 }
9124 }
9125
9126 ZEND_VM_HANDLER(200, ZEND_FETCH_GLOBALS, UNUSED, UNUSED)
9127 {
9128 USE_OPLINE
9129
9130 /* For symbol tables we need to deal with exactly the same problems as for property tables. */
9131 ZVAL_ARR(EX_VAR(opline->result.var),
9132 zend_proptable_to_symtable(&EG(symbol_table), /* always_duplicate */ 1));
9133 ZEND_VM_NEXT_OPCODE();
9134 }
9135
9136 ZEND_VM_HANDLER(186, ZEND_ISSET_ISEMPTY_THIS, UNUSED, UNUSED)
9137 {
9138 USE_OPLINE
9139
9140 ZVAL_BOOL(EX_VAR(opline->result.var),
9141 (opline->extended_value & ZEND_ISEMPTY) ^
9142 (Z_TYPE(EX(This)) == IS_OBJECT));
9143 ZEND_VM_NEXT_OPCODE();
9144 }
9145
9146 ZEND_VM_HANDLER(49, ZEND_CHECK_VAR, CV, UNUSED)
9147 {
9148 USE_OPLINE
9149 zval *op1 = EX_VAR(opline->op1.var);
9150
9151 if (UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
9152 SAVE_OPLINE();
9153 ZVAL_UNDEFINED_OP1();
9154 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9155 }
9156 ZEND_VM_NEXT_OPCODE();
9157 }
9158
9159 ZEND_VM_HANDLER(140, ZEND_MAKE_REF, VAR|CV, UNUSED)
9160 {
9161 USE_OPLINE
9162 zval *op1 = EX_VAR(opline->op1.var);
9163
9164 if (OP1_TYPE == IS_CV) {
9165 if (UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9166 ZVAL_NEW_EMPTY_REF(op1);
9167 Z_SET_REFCOUNT_P(op1, 2);
9168 ZVAL_NULL(Z_REFVAL_P(op1));
9169 ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1));
9170 } else {
9171 if (Z_ISREF_P(op1)) {
9172 Z_ADDREF_P(op1);
9173 } else {
9174 ZVAL_MAKE_REF_EX(op1, 2);
9175 }
9176 ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1));
9177 }
9178 } else if (EXPECTED(Z_TYPE_P(op1) == IS_INDIRECT)) {
9179 op1 = Z_INDIRECT_P(op1);
9180 if (EXPECTED(!Z_ISREF_P(op1))) {
9181 ZVAL_MAKE_REF_EX(op1, 2);
9182 } else {
9183 GC_ADDREF(Z_REF_P(op1));
9184 }
9185 ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(op1));
9186 } else {
9187 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), op1);
9188 }
9189 ZEND_VM_NEXT_OPCODE();
9190 }
9191
9192 ZEND_VM_COLD_CONSTCONST_HANDLER(187, ZEND_SWITCH_LONG, CONST|TMPVARCV, CONST, JMP_ADDR)
9193 {
9194 USE_OPLINE
9195 zval *op, *jump_zv;
9196 HashTable *jumptable;
9197
9198 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9199
9200 if (Z_TYPE_P(op) != IS_LONG) {
9201 ZVAL_DEREF(op);
9202 if (Z_TYPE_P(op) != IS_LONG) {
9203 /* Wrong type, fall back to ZEND_CASE chain */
9204 ZEND_VM_NEXT_OPCODE();
9205 }
9206 }
9207
9208 jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
9209 jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
9210 if (jump_zv != NULL) {
9211 ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
9212 ZEND_VM_CONTINUE();
9213 } else {
9214 /* default */
9215 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
9216 ZEND_VM_CONTINUE();
9217 }
9218 }
9219
9220 ZEND_VM_COLD_CONSTCONST_HANDLER(188, ZEND_SWITCH_STRING, CONST|TMPVARCV, CONST, JMP_ADDR)
9221 {
9222 USE_OPLINE
9223 zval *op, *jump_zv;
9224 HashTable *jumptable;
9225
9226 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9227
9228 if (Z_TYPE_P(op) != IS_STRING) {
9229 if (OP1_TYPE == IS_CONST) {
9230 /* Wrong type, fall back to ZEND_CASE chain */
9231 ZEND_VM_NEXT_OPCODE();
9232 } else {
9233 ZVAL_DEREF(op);
9234 if (Z_TYPE_P(op) != IS_STRING) {
9235 /* Wrong type, fall back to ZEND_CASE chain */
9236 ZEND_VM_NEXT_OPCODE();
9237 }
9238 }
9239 }
9240
9241 jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
9242 jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), OP1_TYPE == IS_CONST);
9243 if (jump_zv != NULL) {
9244 ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
9245 ZEND_VM_CONTINUE();
9246 } else {
9247 /* default */
9248 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
9249 ZEND_VM_CONTINUE();
9250 }
9251 }
9252
9253 ZEND_VM_COLD_CONSTCONST_HANDLER(195, ZEND_MATCH, CONST|TMPVARCV, CONST, JMP_ADDR)
9254 {
9255 USE_OPLINE
9256 zval *op, *jump_zv;
9257 HashTable *jumptable;
9258
9259 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9260 jumptable = Z_ARRVAL_P(GET_OP2_ZVAL_PTR(BP_VAR_R));
9261
9262 ZEND_VM_C_LABEL(match_try_again):
9263 if (Z_TYPE_P(op) == IS_LONG) {
9264 jump_zv = zend_hash_index_find(jumptable, Z_LVAL_P(op));
9265 } else if (Z_TYPE_P(op) == IS_STRING) {
9266 jump_zv = zend_hash_find_ex(jumptable, Z_STR_P(op), OP1_TYPE == IS_CONST);
9267 } else if (Z_TYPE_P(op) == IS_REFERENCE) {
9268 op = Z_REFVAL_P(op);
9269 ZEND_VM_C_GOTO(match_try_again);
9270 } else {
9271 if (UNEXPECTED((OP1_TYPE & IS_CV) && Z_TYPE_P(op) == IS_UNDEF)) {
9272 SAVE_OPLINE();
9273 op = ZVAL_UNDEFINED_OP1();
9274 if (UNEXPECTED(EG(exception))) {
9275 HANDLE_EXCEPTION();
9276 }
9277 ZEND_VM_C_GOTO(match_try_again);
9278 }
9279
9280 ZEND_VM_C_GOTO(default_branch);
9281 }
9282
9283 if (jump_zv != NULL) {
9284 ZEND_VM_SET_RELATIVE_OPCODE(opline, Z_LVAL_P(jump_zv));
9285 ZEND_VM_CONTINUE();
9286 } else {
9287 ZEND_VM_C_LABEL(default_branch):
9288 /* default */
9289 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
9290 ZEND_VM_CONTINUE();
9291 }
9292 }
9293
9294 ZEND_VM_COLD_CONST_HANDLER(197, ZEND_MATCH_ERROR, CONST|TMPVARCV, UNUSED)
9295 {
9296 USE_OPLINE
9297 zval *op;
9298
9299 SAVE_OPLINE();
9300 op = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9301 zend_match_unhandled_error(op);
9302 HANDLE_EXCEPTION();
9303 }
9304
9305 ZEND_VM_COLD_CONSTCONST_HANDLER(189, ZEND_IN_ARRAY, CONST|TMP|VAR|CV, CONST, NUM)
9306 {
9307 USE_OPLINE
9308 zval *op1;
9309 HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
9310 zval *result;
9311
9312 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9313 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
9314 result = zend_hash_find_ex(ht, Z_STR_P(op1), OP1_TYPE == IS_CONST);
9315 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
9316 zval_ptr_dtor_str(op1);
9317 }
9318 ZEND_VM_SMART_BRANCH(result, 0);
9319 }
9320
9321 if (opline->extended_value) {
9322 if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
9323 result = zend_hash_index_find(ht, Z_LVAL_P(op1));
9324 ZEND_VM_SMART_BRANCH(result, 0);
9325 }
9326 SAVE_OPLINE();
9327 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) {
9328 op1 = Z_REFVAL_P(op1);
9329 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
9330 result = zend_hash_find(ht, Z_STR_P(op1));
9331 FREE_OP1();
9332 ZEND_VM_SMART_BRANCH(result, 0);
9333 } else if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
9334 result = zend_hash_index_find(ht, Z_LVAL_P(op1));
9335 FREE_OP1();
9336 ZEND_VM_SMART_BRANCH(result, 0);
9337 }
9338 } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9339 ZVAL_UNDEFINED_OP1();
9340 }
9341 } else if (Z_TYPE_P(op1) <= IS_FALSE) {
9342 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9343 SAVE_OPLINE();
9344 ZVAL_UNDEFINED_OP1();
9345 if (UNEXPECTED(EG(exception) != NULL)) {
9346 HANDLE_EXCEPTION();
9347 }
9348 }
9349 result = zend_hash_find_known_hash(ht, ZSTR_EMPTY_ALLOC());
9350 ZEND_VM_SMART_BRANCH(result, 0);
9351 } else {
9352 zend_string *key;
9353 zval key_tmp;
9354
9355 if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(op1) == IS_REFERENCE) {
9356 op1 = Z_REFVAL_P(op1);
9357 if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
9358 result = zend_hash_find(ht, Z_STR_P(op1));
9359 FREE_OP1();
9360 ZEND_VM_SMART_BRANCH(result, 0);
9361 }
9362 }
9363
9364 SAVE_OPLINE();
ZEND_HASH_MAP_FOREACH_STR_KEY(ht,key)9365 ZEND_HASH_MAP_FOREACH_STR_KEY(ht, key) {
9366 ZVAL_STR(&key_tmp, key);
9367 if (zend_compare(op1, &key_tmp) == 0) {
9368 FREE_OP1();
9369 ZEND_VM_SMART_BRANCH(1, 1);
9370 }
9371 } ZEND_HASH_FOREACH_END();
9372 }
9373 FREE_OP1();
9374 ZEND_VM_SMART_BRANCH(0, 1);
9375 }
9376
9377 ZEND_VM_COLD_CONST_HANDLER(190, ZEND_COUNT, CONST|TMPVAR|CV, UNUSED)
9378 {
9379 USE_OPLINE
9380 zval *op1;
9381 zend_long count;
9382
9383 SAVE_OPLINE();
9384 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9385
9386 while (1) {
9387 if (Z_TYPE_P(op1) == IS_ARRAY) {
9388 count = zend_hash_num_elements(Z_ARRVAL_P(op1));
9389 break;
9390 } else if (Z_TYPE_P(op1) == IS_OBJECT) {
9391 zend_object *zobj = Z_OBJ_P(op1);
9392
9393 /* first, we check if the handler is defined */
9394 if (zobj->handlers->count_elements) {
9395 if (SUCCESS == zobj->handlers->count_elements(zobj, &count)) {
9396 break;
9397 }
9398 if (UNEXPECTED(EG(exception))) {
9399 count = 0;
9400 break;
9401 }
9402 }
9403
9404 /* if not and the object implements Countable we call its count() method */
9405 if (zend_class_implements_interface(zobj->ce, zend_ce_countable)) {
9406 zval retval;
9407
9408 zend_function *count_fn = zend_hash_find_ptr(&zobj->ce->function_table, ZSTR_KNOWN(ZEND_STR_COUNT));
9409 zend_call_known_instance_method_with_0_params(count_fn, zobj, &retval);
9410 count = zval_get_long(&retval);
9411 zval_ptr_dtor(&retval);
9412 break;
9413 }
9414
9415 /* If There's no handler and it doesn't implement Countable then emit a TypeError */
9416 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
9417 op1 = Z_REFVAL_P(op1);
9418 continue;
9419 } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9420 ZVAL_UNDEFINED_OP1();
9421 }
9422 count = 0;
9423 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));
9424 break;
9425 }
9426
9427 ZVAL_LONG(EX_VAR(opline->result.var), count);
9428 FREE_OP1();
9429 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9430 }
9431
9432 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)
9433 {
9434 USE_OPLINE
9435 zend_array *ht = Z_ARRVAL_P(GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R));
9436 ZVAL_LONG(EX_VAR(opline->result.var), zend_hash_num_elements(ht));
9437 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR) && !(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
9438 SAVE_OPLINE();
9439 zend_array_destroy(ht);
9440 if (EG(exception)) {
9441 HANDLE_EXCEPTION();
9442 }
9443 }
9444 ZEND_VM_NEXT_OPCODE();
9445 }
9446
9447 ZEND_VM_COLD_CONST_HANDLER(191, ZEND_GET_CLASS, UNUSED|CONST|TMPVAR|CV, UNUSED)
9448 {
9449 USE_OPLINE
9450
9451 if (OP1_TYPE == IS_UNUSED) {
9452 SAVE_OPLINE();
9453 if (UNEXPECTED(!EX(func)->common.scope)) {
9454 zend_throw_error(NULL, "get_class() without arguments must be called from within a class");
9455 ZVAL_UNDEF(EX_VAR(opline->result.var));
9456 HANDLE_EXCEPTION();
9457 } else {
9458 zend_error(E_DEPRECATED, "Calling get_class() without arguments is deprecated");
9459 ZVAL_STR_COPY(EX_VAR(opline->result.var), EX(func)->common.scope->name);
9460 if (UNEXPECTED(EG(exception))) {
9461 HANDLE_EXCEPTION();
9462 }
9463 ZEND_VM_NEXT_OPCODE();
9464 }
9465 } else {
9466 zval *op1;
9467
9468 SAVE_OPLINE();
9469 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9470 while (1) {
9471 if (Z_TYPE_P(op1) == IS_OBJECT) {
9472 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE_P(op1)->name);
9473 } else if ((OP1_TYPE & (IS_VAR|IS_CV)) != 0 && Z_TYPE_P(op1) == IS_REFERENCE) {
9474 op1 = Z_REFVAL_P(op1);
9475 continue;
9476 } else {
9477 if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
9478 ZVAL_UNDEFINED_OP1();
9479 }
9480 zend_type_error("get_class(): Argument #1 ($object) must be of type object, %s given", zend_zval_value_name(op1));
9481 ZVAL_UNDEF(EX_VAR(opline->result.var));
9482 }
9483 break;
9484 }
9485 FREE_OP1();
9486 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9487 }
9488 }
9489
9490 ZEND_VM_HANDLER(192, ZEND_GET_CALLED_CLASS, UNUSED, UNUSED)
9491 {
9492 USE_OPLINE
9493
9494 if (Z_TYPE(EX(This)) == IS_OBJECT) {
9495 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_OBJCE(EX(This))->name);
9496 } else if (Z_CE(EX(This))) {
9497 ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_CE(EX(This))->name);
9498 } else {
9499 ZEND_ASSERT(!EX(func)->common.scope);
9500 SAVE_OPLINE();
9501 zend_throw_error(NULL, "get_called_class() must be called from within a class");
9502 ZVAL_UNDEF(EX_VAR(opline->result.var));
9503 HANDLE_EXCEPTION();
9504 }
9505 ZEND_VM_NEXT_OPCODE();
9506 }
9507
9508 ZEND_VM_COLD_CONST_HANDLER(193, ZEND_GET_TYPE, CONST|TMP|VAR|CV, UNUSED)
9509 {
9510 USE_OPLINE
9511 zval *op1;
9512 zend_string *type;
9513
9514 SAVE_OPLINE();
9515 op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9516 type = zend_zval_get_legacy_type(op1);
9517 if (EXPECTED(type)) {
9518 ZVAL_INTERNED_STR(EX_VAR(opline->result.var), type);
9519 } else {
9520 ZVAL_STRING(EX_VAR(opline->result.var), "unknown type");
9521 }
9522 FREE_OP1();
9523 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9524 }
9525
9526 ZEND_VM_HANDLER(171, ZEND_FUNC_NUM_ARGS, UNUSED, UNUSED)
9527 {
9528 USE_OPLINE
9529
9530 ZVAL_LONG(EX_VAR(opline->result.var), EX_NUM_ARGS());
9531 ZEND_VM_NEXT_OPCODE();
9532 }
9533
9534 ZEND_VM_HANDLER(172, ZEND_FUNC_GET_ARGS, UNUSED|CONST, UNUSED)
9535 {
9536 USE_OPLINE
9537 zend_array *ht;
9538 uint32_t arg_count, result_size, skip;
9539
9540 arg_count = EX_NUM_ARGS();
9541 if (OP1_TYPE == IS_CONST) {
9542 skip = Z_LVAL_P(RT_CONSTANT(opline, opline->op1));
9543 if (arg_count < skip) {
9544 result_size = 0;
9545 } else {
9546 result_size = arg_count - skip;
9547 }
9548 } else {
9549 skip = 0;
9550 result_size = arg_count;
9551 }
9552
9553 if (result_size) {
9554 SAVE_OPLINE();
9555 uint32_t first_extra_arg = EX(func)->op_array.num_args;
9556
9557 ht = zend_new_array(result_size);
9558 ZVAL_ARR(EX_VAR(opline->result.var), ht);
9559 zend_hash_real_init_packed(ht);
ZEND_HASH_FILL_PACKED(ht)9560 ZEND_HASH_FILL_PACKED(ht) {
9561 zval *p, *q;
9562 uint32_t i = skip;
9563 p = EX_VAR_NUM(i);
9564 if (arg_count > first_extra_arg) {
9565 while (i < first_extra_arg) {
9566 q = p;
9567 if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
9568 ZVAL_DEREF(q);
9569 if (Z_OPT_REFCOUNTED_P(q)) {
9570 Z_ADDREF_P(q);
9571 }
9572 ZEND_HASH_FILL_SET(q);
9573 } else {
9574 ZEND_HASH_FILL_SET_NULL();
9575 }
9576 ZEND_HASH_FILL_NEXT();
9577 p++;
9578 i++;
9579 }
9580 if (skip < first_extra_arg) {
9581 skip = 0;
9582 } else {
9583 skip -= first_extra_arg;
9584 }
9585 p = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T + skip);
9586 }
9587 while (i < arg_count) {
9588 q = p;
9589 if (EXPECTED(Z_TYPE_INFO_P(q) != IS_UNDEF)) {
9590 ZVAL_DEREF(q);
9591 if (Z_OPT_REFCOUNTED_P(q)) {
9592 Z_ADDREF_P(q);
9593 }
9594 ZEND_HASH_FILL_SET(q);
9595 } else {
9596 ZEND_HASH_FILL_SET_NULL();
9597 }
9598 ZEND_HASH_FILL_NEXT();
9599 p++;
9600 i++;
9601 }
9602 } ZEND_HASH_FILL_END();
9603 ht->nNumOfElements = result_size;
9604 } else {
9605 ZVAL_EMPTY_ARRAY(EX_VAR(opline->result.var));
9606 }
9607 ZEND_VM_NEXT_OPCODE();
9608 }
9609
9610 /* Contrary to what its name indicates, ZEND_COPY_TMP may receive and define references. */
9611 ZEND_VM_HANDLER(167, ZEND_COPY_TMP, TMPVAR, UNUSED)
9612 {
9613 USE_OPLINE
9614 zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
9615 zval *result = EX_VAR(opline->result.var);
9616 ZVAL_COPY(result, value);
9617 ZEND_VM_NEXT_OPCODE();
9618 }
9619
9620 ZEND_VM_HANDLER(202, ZEND_CALLABLE_CONVERT, UNUSED, UNUSED)
9621 {
9622 USE_OPLINE
9623 zend_execute_data *call = EX(call);
9624
9625 zend_closure_from_frame(EX_VAR(opline->result.var), call);
9626
9627 if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
9628 OBJ_RELEASE(Z_OBJ(call->This));
9629 }
9630
9631 EX(call) = call->prev_execute_data;
9632
9633 zend_vm_stack_free_call_frame(call);
9634
9635 ZEND_VM_NEXT_OPCODE();
9636 }
9637
9638 ZEND_VM_HANDLER(208, ZEND_JMP_FRAMELESS, CONST, JMP_ADDR, NUM|CACHE_SLOT)
9639 {
9640 USE_OPLINE
9641 zend_jmp_fl_result result = (uintptr_t)CACHED_PTR(opline->extended_value);
9642 ZEND_VM_C_LABEL(try_again):
9643 if (EXPECTED(result == ZEND_JMP_FL_HIT)) {
9644 OPLINE = OP_JMP_ADDR(opline, opline->op2);
9645 ZEND_VM_CONTINUE();
9646 } else if (EXPECTED(result == ZEND_JMP_FL_MISS)) {
9647 ZEND_VM_NEXT_OPCODE();
9648 } else {
9649 ZEND_ASSERT(result == ZEND_JMP_FL_UNPRIMED);
9650 /* func_name refers to the function in the local namespace, e.g. foo\substr. */
9651 zval *func_name = (zval *)RT_CONSTANT(opline, opline->op1);
9652 /* If it cannot be found locally, we must be referring to the global function. */
9653 zval *func = zend_hash_find_known_hash(EG(function_table), Z_STR_P(func_name));
9654 /* ZEND_JMP_FL_MISS = 1, ZEND_JMP_FL_HIT = 2 */
9655 result = (func == NULL) + 1;
9656 CACHE_PTR(opline->extended_value, (void *)result);
9657 ZEND_VM_C_GOTO(try_again);
9658 }
9659 }
9660
9661 ZEND_VM_HANDLER(204, ZEND_FRAMELESS_ICALL_0, UNUSED, UNUSED, SPEC(OBSERVER))
9662 {
9663 USE_OPLINE
9664 SAVE_OPLINE();
9665
9666 zval *result = EX_VAR(opline->result.var);
9667 ZVAL_NULL(result);
9668
9669 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9670 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9671 zend_frameless_observed_call(execute_data);
9672 } else
9673 #endif
9674 {
9675 zend_frameless_function_0 function = (zend_frameless_function_0)ZEND_FLF_HANDLER(opline);
9676 function(EX_VAR(opline->result.var));
9677 }
9678 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9679 }
9680
9681 ZEND_VM_HANDLER(205, ZEND_FRAMELESS_ICALL_1, ANY, UNUSED, SPEC(OBSERVER))
9682 {
9683 USE_OPLINE
9684 SAVE_OPLINE();
9685
9686 zval *result = EX_VAR(opline->result.var);
9687 ZVAL_NULL(result);
9688 zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9689 if (EG(exception)) {
9690 FREE_OP1();
9691 HANDLE_EXCEPTION();
9692 }
9693
9694 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9695 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9696 zend_frameless_observed_call(execute_data);
9697 } else
9698 #endif
9699 {
9700 zend_frameless_function_1 function = (zend_frameless_function_1)ZEND_FLF_HANDLER(opline);
9701 function(result, arg1);
9702 }
9703 FREE_OP1();
9704 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9705 }
9706
9707 ZEND_VM_HANDLER(206, ZEND_FRAMELESS_ICALL_2, ANY, ANY, SPEC(OBSERVER))
9708 {
9709 USE_OPLINE
9710 SAVE_OPLINE();
9711
9712 zval *result = EX_VAR(opline->result.var);
9713 ZVAL_NULL(result);
9714 zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9715 zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
9716 if (EG(exception)) {
9717 FREE_OP1();
9718 FREE_OP2();
9719 HANDLE_EXCEPTION();
9720 }
9721
9722 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9723 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9724 zend_frameless_observed_call(execute_data);
9725 } else
9726 #endif
9727 {
9728 zend_frameless_function_2 function = (zend_frameless_function_2)ZEND_FLF_HANDLER(opline);
9729 function(result, arg1, arg2);
9730 }
9731
9732 FREE_OP1();
9733 /* Set OP1 to UNDEF in case FREE_OP2() throws. */
9734 if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
9735 ZVAL_UNDEF(EX_VAR(opline->op1.var));
9736 }
9737 FREE_OP2();
9738 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
9739 }
9740
9741 ZEND_VM_HANDLER(207, ZEND_FRAMELESS_ICALL_3, ANY, ANY, SPEC(OBSERVER))
9742 {
9743 USE_OPLINE
9744 SAVE_OPLINE();
9745
9746 zval *result = EX_VAR(opline->result.var);
9747 ZVAL_NULL(result);
9748 zval *arg1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
9749 zval *arg2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
9750 zval *arg3 = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);
9751 if (EG(exception)) {
9752 FREE_OP1();
9753 FREE_OP2();
9754 FREE_OP_DATA();
9755 HANDLE_EXCEPTION();
9756 }
9757
9758 #if !ZEND_VM_SPEC || ZEND_OBSERVER_ENABLED
9759 if (ZEND_OBSERVER_ENABLED && UNEXPECTED(zend_observer_handler_is_unobserved(ZEND_OBSERVER_DATA(ZEND_FLF_FUNC(opline))) == false)) {
9760 zend_frameless_observed_call(execute_data);
9761 } else
9762 #endif
9763 {
9764 zend_frameless_function_3 function = (zend_frameless_function_3)ZEND_FLF_HANDLER(opline);
9765 function(result, arg1, arg2, arg3);
9766 }
9767
9768 FREE_OP1();
9769 /* Set to UNDEF in case FREE_OP2() throws. */
9770 if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
9771 ZVAL_UNDEF(EX_VAR(opline->op1.var));
9772 }
9773 FREE_OP2();
9774 if (OP2_TYPE & (IS_VAR|IS_TMP_VAR)) {
9775 ZVAL_UNDEF(EX_VAR(opline->op2.var));
9776 }
9777 FREE_OP_DATA();
9778 ZEND_VM_NEXT_OPCODE_EX(1, 2);
9779 }
9780
9781 ZEND_VM_HANDLER(209, ZEND_INIT_PARENT_PROPERTY_HOOK_CALL, CONST, UNUSED|NUM, NUM)
9782 {
9783 USE_OPLINE
9784 SAVE_OPLINE();
9785
9786 zend_class_entry *ce = EX(func)->common.scope;
9787 ZEND_ASSERT(ce);
9788
9789 zend_class_entry *parent_ce = ce->parent;
9790 if (!parent_ce) {
9791 zend_throw_error(NULL, "Cannot use \"parent\" when current class scope has no parent");
9792 UNDEF_RESULT();
9793 HANDLE_EXCEPTION();
9794 }
9795
9796 zend_string *property_name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
9797 zend_property_hook_kind hook_kind = opline->op2.num;
9798
9799 zend_property_info *prop_info = zend_hash_find_ptr(&parent_ce->properties_info, property_name);
9800 if (!prop_info) {
9801 zend_throw_error(NULL, "Undefined property %s::$%s", ZSTR_VAL(parent_ce->name), ZSTR_VAL(property_name));
9802 UNDEF_RESULT();
9803 HANDLE_EXCEPTION();
9804 }
9805 if (prop_info->flags & ZEND_ACC_PRIVATE) {
9806 zend_throw_error(NULL, "Cannot access private property %s::$%s", ZSTR_VAL(parent_ce->name), ZSTR_VAL(property_name));
9807 UNDEF_RESULT();
9808 HANDLE_EXCEPTION();
9809 }
9810
9811 zend_function **hooks = prop_info->hooks;
9812 zend_function *hook = hooks ? hooks[hook_kind] : NULL;
9813
9814 zend_execute_data *call;
9815 if (hook) {
9816 call = zend_vm_stack_push_call_frame(
9817 ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS,
9818 hook, opline->extended_value, Z_OBJ_P(ZEND_THIS));
9819 if (EXPECTED(hook->type == ZEND_USER_FUNCTION)) {
9820 if (UNEXPECTED(!RUN_TIME_CACHE(&hook->op_array))) {
9821 init_func_run_time_cache(&hook->op_array);
9822 }
9823 call->run_time_cache = RUN_TIME_CACHE(&hook->op_array);
9824 }
9825 } else {
9826 zend_function *fbc = zend_get_property_hook_trampoline(prop_info, hook_kind, property_name);
9827 call = zend_vm_stack_push_call_frame(
9828 ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_HAS_THIS,
9829 fbc, opline->extended_value, Z_OBJ_P(ZEND_THIS));
9830 }
9831
9832 call->prev_execute_data = EX(call);
9833 EX(call) = call;
9834 ZEND_VM_NEXT_OPCODE();
9835 }
9836
9837 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_JMP, (OP_JMP_ADDR(op, op->op1) > op), ZEND_JMP_FORWARD, JMP_ADDR, ANY)
9838 {
9839 USE_OPLINE
9840
9841 OPLINE = OP_JMP_ADDR(opline, opline->op1);
9842 ZEND_VM_CONTINUE();
9843 }
9844
9845 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))
9846 {
9847 USE_OPLINE
9848 zval *op1, *op2, *result;
9849
9850 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9851 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9852 result = EX_VAR(opline->result.var);
9853 ZVAL_LONG(result, Z_LVAL_P(op1) + Z_LVAL_P(op2));
9854 ZEND_VM_NEXT_OPCODE();
9855 }
9856
9857 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))
9858 {
9859 USE_OPLINE
9860 zval *op1, *op2, *result;
9861
9862 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9863 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9864 result = EX_VAR(opline->result.var);
9865 fast_long_add_function(result, op1, op2);
9866 ZEND_VM_NEXT_OPCODE();
9867 }
9868
9869 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))
9870 {
9871 USE_OPLINE
9872 zval *op1, *op2, *result;
9873
9874 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9875 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9876 result = EX_VAR(opline->result.var);
9877 ZVAL_DOUBLE(result, Z_DVAL_P(op1) + Z_DVAL_P(op2));
9878 ZEND_VM_NEXT_OPCODE();
9879 }
9880
9881 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))
9882 {
9883 USE_OPLINE
9884 zval *op1, *op2, *result;
9885
9886 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9887 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9888 result = EX_VAR(opline->result.var);
9889 ZVAL_LONG(result, Z_LVAL_P(op1) - Z_LVAL_P(op2));
9890 ZEND_VM_NEXT_OPCODE();
9891 }
9892
9893 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))
9894 {
9895 USE_OPLINE
9896 zval *op1, *op2, *result;
9897
9898 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9899 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9900 result = EX_VAR(opline->result.var);
9901 fast_long_sub_function(result, op1, op2);
9902 ZEND_VM_NEXT_OPCODE();
9903 }
9904
9905 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))
9906 {
9907 USE_OPLINE
9908 zval *op1, *op2, *result;
9909
9910 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9911 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9912 result = EX_VAR(opline->result.var);
9913 ZVAL_DOUBLE(result, Z_DVAL_P(op1) - Z_DVAL_P(op2));
9914 ZEND_VM_NEXT_OPCODE();
9915 }
9916
9917 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))
9918 {
9919 USE_OPLINE
9920 zval *op1, *op2, *result;
9921
9922 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9923 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9924 result = EX_VAR(opline->result.var);
9925 ZVAL_LONG(result, Z_LVAL_P(op1) * Z_LVAL_P(op2));
9926 ZEND_VM_NEXT_OPCODE();
9927 }
9928
9929 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))
9930 {
9931 USE_OPLINE
9932 zval *op1, *op2, *result;
9933 zend_long overflow;
9934
9935 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9936 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9937 result = EX_VAR(opline->result.var);
9938 ZEND_SIGNED_MULTIPLY_LONG(Z_LVAL_P(op1), Z_LVAL_P(op2), Z_LVAL_P(result), Z_DVAL_P(result), overflow);
9939 Z_TYPE_INFO_P(result) = overflow ? IS_DOUBLE : IS_LONG;
9940 ZEND_VM_NEXT_OPCODE();
9941 }
9942
9943 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))
9944 {
9945 USE_OPLINE
9946 zval *op1, *op2, *result;
9947
9948 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9949 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9950 result = EX_VAR(opline->result.var);
9951 ZVAL_DOUBLE(result, Z_DVAL_P(op1) * Z_DVAL_P(op2));
9952 ZEND_VM_NEXT_OPCODE();
9953 }
9954
9955 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))
9956 {
9957 USE_OPLINE
9958 zval *op1, *op2;
9959 bool result;
9960
9961 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9962 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9963 result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
9964 ZEND_VM_SMART_BRANCH(result, 0);
9965 }
9966
9967 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))
9968 {
9969 USE_OPLINE
9970 zval *op1, *op2;
9971 bool result;
9972
9973 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9974 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9975 result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
9976 ZEND_VM_SMART_BRANCH(result, 0);
9977 }
9978
9979 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))
9980 {
9981 USE_OPLINE
9982 zval *op1, *op2;
9983 bool result;
9984
9985 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9986 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9987 result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
9988 ZEND_VM_SMART_BRANCH(result, 0);
9989 }
9990
9991 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))
9992 {
9993 USE_OPLINE
9994 zval *op1, *op2;
9995 bool result;
9996
9997 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
9998 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
9999 result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
10000 ZEND_VM_SMART_BRANCH(result, 0);
10001 }
10002
10003 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))
10004 {
10005 /* This is declared below the specializations for MAY_BE_LONG/MAY_BE_DOUBLE so those will be used instead if possible. */
10006 /* This optimizes $x === SOME_CONST_EXPR and $x === $y for non-refs and non-undef, which can't throw. */
10007 /* (Infinite recursion when comparing arrays is an uncatchable fatal error) */
10008 USE_OPLINE
10009 zval *op1, *op2;
10010 bool result;
10011
10012 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10013 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10014 result = fast_is_identical_function(op1, op2);
10015 /* Free is a no-op for const/cv */
10016 ZEND_VM_SMART_BRANCH(result, 0);
10017 }
10018
10019 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))
10020 {
10021 USE_OPLINE
10022 zval *op1, *op2;
10023 bool result;
10024
10025 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10026 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10027 result = fast_is_identical_function(op1, op2);
10028 /* Free is a no-op for const/cv */
10029 ZEND_VM_SMART_BRANCH(!result, 0);
10030 }
10031
10032 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))
10033 {
10034 USE_OPLINE
10035 zval *op1, *op2;
10036 bool result;
10037
10038 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10039 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10040 result = (Z_LVAL_P(op1) < Z_LVAL_P(op2));
10041 ZEND_VM_SMART_BRANCH(result, 0);
10042 }
10043
10044 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))
10045 {
10046 USE_OPLINE
10047 zval *op1, *op2;
10048 bool result;
10049
10050 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10051 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10052 result = (Z_DVAL_P(op1) < Z_DVAL_P(op2));
10053 ZEND_VM_SMART_BRANCH(result, 0);
10054 }
10055
10056 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))
10057 {
10058 USE_OPLINE
10059 zval *op1, *op2;
10060 bool result;
10061
10062 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10063 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10064 result = (Z_LVAL_P(op1) <= Z_LVAL_P(op2));
10065 ZEND_VM_SMART_BRANCH(result, 0);
10066 }
10067
10068 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))
10069 {
10070 USE_OPLINE
10071 zval *op1, *op2;
10072 bool result;
10073
10074 op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10075 op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10076 result = (Z_DVAL_P(op1) <= Z_DVAL_P(op2));
10077 ZEND_VM_SMART_BRANCH(result, 0);
10078 }
10079
10080 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))
10081 {
10082 USE_OPLINE
10083 zval *var_ptr;
10084
10085 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10086 Z_LVAL_P(var_ptr)++;
10087 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10088 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10089 }
10090 ZEND_VM_NEXT_OPCODE();
10091 }
10092
10093 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_INC, (op1_info == MAY_BE_LONG), ZEND_PRE_INC_LONG, CV, ANY, SPEC(RETVAL))
10094 {
10095 USE_OPLINE
10096 zval *var_ptr;
10097
10098 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10099 fast_long_increment_function(var_ptr);
10100 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10101 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
10102 }
10103 ZEND_VM_NEXT_OPCODE();
10104 }
10105
10106 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))
10107 {
10108 USE_OPLINE
10109 zval *var_ptr;
10110
10111 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10112 Z_LVAL_P(var_ptr)--;
10113 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10114 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10115 }
10116 ZEND_VM_NEXT_OPCODE();
10117 }
10118
10119 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_PRE_DEC, (op1_info == MAY_BE_LONG), ZEND_PRE_DEC_LONG, CV, ANY, SPEC(RETVAL))
10120 {
10121 USE_OPLINE
10122 zval *var_ptr;
10123
10124 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10125 fast_long_decrement_function(var_ptr);
10126 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
10127 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
10128 }
10129 ZEND_VM_NEXT_OPCODE();
10130 }
10131
10132 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)
10133 {
10134 USE_OPLINE
10135 zval *var_ptr;
10136
10137 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10138 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10139 Z_LVAL_P(var_ptr)++;
10140 ZEND_VM_NEXT_OPCODE();
10141 }
10142
10143 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_INC, (op1_info == MAY_BE_LONG), ZEND_POST_INC_LONG, CV, ANY)
10144 {
10145 USE_OPLINE
10146 zval *var_ptr;
10147
10148 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10149 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10150 fast_long_increment_function(var_ptr);
10151 ZEND_VM_NEXT_OPCODE();
10152 }
10153
10154 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)
10155 {
10156 USE_OPLINE
10157 zval *var_ptr;
10158
10159 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10160 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10161 Z_LVAL_P(var_ptr)--;
10162 ZEND_VM_NEXT_OPCODE();
10163 }
10164
10165 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_POST_DEC, (op1_info == MAY_BE_LONG), ZEND_POST_DEC_LONG, CV, ANY)
10166 {
10167 USE_OPLINE
10168 zval *var_ptr;
10169
10170 var_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
10171 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(var_ptr));
10172 fast_long_decrement_function(var_ptr);
10173 ZEND_VM_NEXT_OPCODE();
10174 }
10175
10176 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_LONG), ZEND_QM_ASSIGN_LONG, CONST|TMPVARCV, ANY)
10177 {
10178 USE_OPLINE
10179 zval *value;
10180
10181 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10182 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(value));
10183 ZEND_VM_NEXT_OPCODE();
10184 }
10185
10186 ZEND_VM_HOT_TYPE_SPEC_HANDLER(ZEND_QM_ASSIGN, (op1_info == MAY_BE_DOUBLE), ZEND_QM_ASSIGN_DOUBLE, CONST|TMPVARCV, ANY)
10187 {
10188 USE_OPLINE
10189 zval *value;
10190
10191 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10192 ZVAL_DOUBLE(EX_VAR(opline->result.var), Z_DVAL_P(value));
10193 ZEND_VM_NEXT_OPCODE();
10194 }
10195
10196 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)
10197 {
10198 USE_OPLINE
10199 zval *value;
10200
10201 value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10202 ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
10203 ZEND_VM_NEXT_OPCODE();
10204 }
10205
10206 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))
10207 {
10208 USE_OPLINE
10209 zval *container, *dim, *value;
10210 zend_long offset;
10211 HashTable *ht;
10212
10213 container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10214 dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
10215 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
10216 ZEND_VM_C_LABEL(fetch_dim_r_index_array):
10217 if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
10218 offset = Z_LVAL_P(dim);
10219 } else {
10220 SAVE_OPLINE();
10221 zend_fetch_dimension_address_read_R(container, dim, OP2_TYPE OPLINE_CC EXECUTE_DATA_CC);
10222 FREE_OP1();
10223 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10224 }
10225 ht = Z_ARRVAL_P(container);
10226 ZEND_HASH_INDEX_FIND(ht, offset, value, ZEND_VM_C_LABEL(fetch_dim_r_index_undef));
10227 ZVAL_COPY_DEREF(EX_VAR(opline->result.var), value);
10228 if (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) {
10229 SAVE_OPLINE();
10230 FREE_OP1();
10231 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10232 } else {
10233 ZEND_VM_NEXT_OPCODE();
10234 }
10235 } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
10236 container = Z_REFVAL_P(container);
10237 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
10238 ZEND_VM_C_GOTO(fetch_dim_r_index_array);
10239 } else {
10240 ZEND_VM_C_GOTO(fetch_dim_r_index_slow);
10241 }
10242 } else {
10243 ZEND_VM_C_LABEL(fetch_dim_r_index_slow):
10244 SAVE_OPLINE();
10245 if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
10246 dim++;
10247 }
10248 zend_fetch_dimension_address_read_R_slow(container, dim OPLINE_CC EXECUTE_DATA_CC);
10249 FREE_OP1();
10250 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10251 }
10252
10253 ZEND_VM_C_LABEL(fetch_dim_r_index_undef):
10254 ZVAL_NULL(EX_VAR(opline->result.var));
10255 SAVE_OPLINE();
10256 zend_undefined_offset(offset);
10257 FREE_OP1();
10258 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10259 }
10260
10261 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)
10262 {
10263 USE_OPLINE
10264 zval *varptr, *arg;
10265
10266 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10267 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10268
10269 if (OP1_TYPE == IS_CV) {
10270 ZVAL_COPY(arg, varptr);
10271 } else /* if (OP1_TYPE == IS_VAR) */ {
10272 ZVAL_COPY_VALUE(arg, varptr);
10273 }
10274
10275 ZEND_VM_NEXT_OPCODE();
10276 }
10277
10278 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)
10279 {
10280 USE_OPLINE
10281 zval *varptr, *arg;
10282 uint32_t arg_num = opline->op2.num;
10283
10284 if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
10285 ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
10286 }
10287
10288 varptr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
10289 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10290
10291 if (OP1_TYPE == IS_CV) {
10292 ZVAL_COPY(arg, varptr);
10293 } else /* if (OP1_TYPE == IS_VAR) */ {
10294 ZVAL_COPY_VALUE(arg, varptr);
10295 }
10296
10297 ZEND_VM_NEXT_OPCODE();
10298 }
10299
10300 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)
10301 {
10302 USE_OPLINE
10303 zval *value, *arg;
10304
10305 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
10306 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10307 ZVAL_COPY_VALUE(arg, value);
10308 ZEND_VM_NEXT_OPCODE();
10309 }
10310
10311 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)
10312 {
10313 USE_OPLINE
10314 zval *value, *arg;
10315 uint32_t arg_num = opline->op2.num;
10316
10317 arg = ZEND_CALL_VAR(EX(call), opline->result.var);
10318 if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
10319 ZEND_VM_DISPATCH_TO_HELPER(zend_cannot_pass_by_ref_helper, _arg_num, arg_num, _arg, arg);
10320 }
10321 value = GET_OP1_ZVAL_PTR(BP_VAR_R);
10322 ZVAL_COPY_VALUE(arg, value);
10323 ZEND_VM_NEXT_OPCODE();
10324 }
10325
10326 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))
10327 {
10328 USE_OPLINE
10329 zval *array;
10330 zval *value, *variable_ptr;
10331 uint32_t value_type;
10332 HashTable *fe_ht;
10333 HashPosition pos;
10334
10335 array = EX_VAR(opline->op1.var);
10336 SAVE_OPLINE();
10337 fe_ht = Z_ARRVAL_P(array);
10338 pos = Z_FE_POS_P(array);
10339 if (HT_IS_PACKED(fe_ht)) {
10340 value = fe_ht->arPacked + pos;
10341 while (1) {
10342 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
10343 /* reached end of iteration */
10344 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
10345 ZEND_VM_CONTINUE();
10346 }
10347 value_type = Z_TYPE_INFO_P(value);
10348 ZEND_ASSERT(value_type != IS_INDIRECT);
10349 if (EXPECTED(value_type != IS_UNDEF)) {
10350 break;
10351 }
10352 pos++;
10353 value++;
10354 }
10355 Z_FE_POS_P(array) = pos + 1;
10356 if (RETURN_VALUE_USED(opline)) {
10357 ZVAL_LONG(EX_VAR(opline->result.var), pos);
10358 }
10359 } else {
10360 Bucket *p;
10361
10362 p = fe_ht->arData + pos;
10363 while (1) {
10364 if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
10365 /* reached end of iteration */
10366 ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
10367 ZEND_VM_CONTINUE();
10368 }
10369 pos++;
10370 value = &p->val;
10371 value_type = Z_TYPE_INFO_P(value);
10372 ZEND_ASSERT(value_type != IS_INDIRECT);
10373 if (EXPECTED(value_type != IS_UNDEF)) {
10374 break;
10375 }
10376 p++;
10377 }
10378 Z_FE_POS_P(array) = pos;
10379 if (RETURN_VALUE_USED(opline)) {
10380 if (!p->key) {
10381 ZVAL_LONG(EX_VAR(opline->result.var), p->h);
10382 } else {
10383 ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
10384 }
10385 }
10386 }
10387
10388 variable_ptr = EX_VAR(opline->op2.var);
10389 zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
10390 ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
10391 }
10392
10393 ZEND_VM_DEFINE_OP(137, ZEND_OP_DATA);
10394
ZEND_VM_HELPER(zend_interrupt_helper,ANY,ANY)10395 ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY)
10396 {
10397 zend_atomic_bool_store_ex(&EG(vm_interrupt), false);
10398 SAVE_OPLINE();
10399 if (zend_atomic_bool_load_ex(&EG(timed_out))) {
10400 zend_timeout();
10401 } else if (zend_interrupt_function) {
10402 zend_interrupt_function(execute_data);
10403 if (EG(exception)) {
10404 /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
10405 const zend_op *throw_op = EG(opline_before_exception);
10406
10407 if (throw_op
10408 && throw_op->result_type & (IS_TMP_VAR|IS_VAR)
10409 && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
10410 && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
10411 && throw_op->opcode != ZEND_ROPE_INIT
10412 && throw_op->opcode != ZEND_ROPE_ADD) {
10413 ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
10414
10415 }
10416 }
10417 ZEND_VM_ENTER();
10418 }
10419 ZEND_VM_CONTINUE();
10420 }
10421