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