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