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