1/*
2   +----------------------------------------------------------------------+
3   | Zend Engine                                                          |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1998-2015 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@zend.com>                                |
16   |          Zeev Suraski <zeev@zend.com>                                |
17   |          Dmitry Stogov <dmitry@zend.com>                             |
18   +----------------------------------------------------------------------+
19*/
20
21/* $Id$ */
22
23/* If you change this file, please regenerate the zend_vm_execute.h and
24 * zend_vm_opcodes.h files by running:
25 * php zend_vm_gen.php
26 */
27
28ZEND_VM_HANDLER(1, ZEND_ADD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
29{
30    USE_OPLINE
31    zend_free_op free_op1, free_op2;
32
33    SAVE_OPLINE();
34    fast_add_function(EX_VAR(opline->result.var),
35        GET_OP1_ZVAL_PTR(BP_VAR_R),
36        GET_OP2_ZVAL_PTR(BP_VAR_R));
37    FREE_OP1();
38    FREE_OP2();
39    CHECK_EXCEPTION();
40    ZEND_VM_NEXT_OPCODE();
41}
42
43ZEND_VM_HANDLER(2, ZEND_SUB, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
44{
45    USE_OPLINE
46    zend_free_op free_op1, free_op2;
47
48    SAVE_OPLINE();
49    fast_sub_function(EX_VAR(opline->result.var),
50        GET_OP1_ZVAL_PTR(BP_VAR_R),
51        GET_OP2_ZVAL_PTR(BP_VAR_R));
52    FREE_OP1();
53    FREE_OP2();
54    CHECK_EXCEPTION();
55    ZEND_VM_NEXT_OPCODE();
56}
57
58ZEND_VM_HANDLER(3, ZEND_MUL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
59{
60    USE_OPLINE
61    zend_free_op free_op1, free_op2;
62
63    SAVE_OPLINE();
64    fast_mul_function(EX_VAR(opline->result.var),
65        GET_OP1_ZVAL_PTR(BP_VAR_R),
66        GET_OP2_ZVAL_PTR(BP_VAR_R));
67    FREE_OP1();
68    FREE_OP2();
69    CHECK_EXCEPTION();
70    ZEND_VM_NEXT_OPCODE();
71}
72
73ZEND_VM_HANDLER(4, ZEND_DIV, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
74{
75    USE_OPLINE
76    zend_free_op free_op1, free_op2;
77
78    SAVE_OPLINE();
79    fast_div_function(EX_VAR(opline->result.var),
80        GET_OP1_ZVAL_PTR(BP_VAR_R),
81        GET_OP2_ZVAL_PTR(BP_VAR_R));
82    FREE_OP1();
83    FREE_OP2();
84    CHECK_EXCEPTION();
85    ZEND_VM_NEXT_OPCODE();
86}
87
88ZEND_VM_HANDLER(5, ZEND_MOD, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
89{
90    USE_OPLINE
91    zend_free_op free_op1, free_op2;
92
93    SAVE_OPLINE();
94    fast_mod_function(EX_VAR(opline->result.var),
95        GET_OP1_ZVAL_PTR(BP_VAR_R),
96        GET_OP2_ZVAL_PTR(BP_VAR_R));
97    FREE_OP1();
98    FREE_OP2();
99    CHECK_EXCEPTION();
100    ZEND_VM_NEXT_OPCODE();
101}
102
103ZEND_VM_HANDLER(6, ZEND_SL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
104{
105    USE_OPLINE
106    zend_free_op free_op1, free_op2;
107
108    SAVE_OPLINE();
109    shift_left_function(EX_VAR(opline->result.var),
110        GET_OP1_ZVAL_PTR(BP_VAR_R),
111        GET_OP2_ZVAL_PTR(BP_VAR_R));
112    FREE_OP1();
113    FREE_OP2();
114    CHECK_EXCEPTION();
115    ZEND_VM_NEXT_OPCODE();
116}
117
118ZEND_VM_HANDLER(7, ZEND_SR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
119{
120    USE_OPLINE
121    zend_free_op free_op1, free_op2;
122
123    SAVE_OPLINE();
124    shift_right_function(EX_VAR(opline->result.var),
125        GET_OP1_ZVAL_PTR(BP_VAR_R),
126        GET_OP2_ZVAL_PTR(BP_VAR_R));
127    FREE_OP1();
128    FREE_OP2();
129    CHECK_EXCEPTION();
130    ZEND_VM_NEXT_OPCODE();
131}
132
133ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
134{
135    USE_OPLINE
136    zend_free_op free_op1, free_op2;
137
138    SAVE_OPLINE();
139    concat_function(EX_VAR(opline->result.var),
140        GET_OP1_ZVAL_PTR(BP_VAR_R),
141        GET_OP2_ZVAL_PTR(BP_VAR_R));
142    FREE_OP1();
143    FREE_OP2();
144    CHECK_EXCEPTION();
145    ZEND_VM_NEXT_OPCODE();
146}
147
148ZEND_VM_HANDLER(15, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
149{
150    USE_OPLINE
151    zend_free_op free_op1, free_op2;
152
153    SAVE_OPLINE();
154    fast_is_identical_function(EX_VAR(opline->result.var),
155        GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R),
156        GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R));
157    FREE_OP1();
158    FREE_OP2();
159    CHECK_EXCEPTION();
160    ZEND_VM_NEXT_OPCODE();
161}
162
163ZEND_VM_HANDLER(16, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
164{
165    USE_OPLINE
166    zend_free_op free_op1, free_op2;
167    zval *result = EX_VAR(opline->result.var);
168
169    SAVE_OPLINE();
170    fast_is_not_identical_function(result,
171        GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R),
172        GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R));
173    FREE_OP1();
174    FREE_OP2();
175    CHECK_EXCEPTION();
176    ZEND_VM_NEXT_OPCODE();
177}
178
179ZEND_VM_HANDLER(17, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
180{
181    USE_OPLINE
182    zend_free_op free_op1, free_op2;
183    zval *result = EX_VAR(opline->result.var);
184
185    SAVE_OPLINE();
186    fast_equal_function(result,
187        GET_OP1_ZVAL_PTR(BP_VAR_R),
188        GET_OP2_ZVAL_PTR(BP_VAR_R));
189    FREE_OP1();
190    FREE_OP2();
191    CHECK_EXCEPTION();
192    ZEND_VM_NEXT_OPCODE();
193}
194
195ZEND_VM_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
196{
197    USE_OPLINE
198    zend_free_op free_op1, free_op2;
199    zval *result = EX_VAR(opline->result.var);
200
201    SAVE_OPLINE();
202    fast_not_equal_function(result,
203        GET_OP1_ZVAL_PTR(BP_VAR_R),
204        GET_OP2_ZVAL_PTR(BP_VAR_R));
205    FREE_OP1();
206    FREE_OP2();
207    CHECK_EXCEPTION();
208    ZEND_VM_NEXT_OPCODE();
209}
210
211ZEND_VM_HANDLER(19, ZEND_IS_SMALLER, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
212{
213    USE_OPLINE
214    zend_free_op free_op1, free_op2;
215    zval *result = EX_VAR(opline->result.var);
216
217    SAVE_OPLINE();
218    fast_is_smaller_function(result,
219        GET_OP1_ZVAL_PTR(BP_VAR_R),
220        GET_OP2_ZVAL_PTR(BP_VAR_R));
221    FREE_OP1();
222    FREE_OP2();
223    CHECK_EXCEPTION();
224    ZEND_VM_NEXT_OPCODE();
225}
226
227ZEND_VM_HANDLER(20, ZEND_IS_SMALLER_OR_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
228{
229    USE_OPLINE
230    zend_free_op free_op1, free_op2;
231    zval *result = EX_VAR(opline->result.var);
232
233    SAVE_OPLINE();
234    fast_is_smaller_or_equal_function(result,
235        GET_OP1_ZVAL_PTR(BP_VAR_R),
236        GET_OP2_ZVAL_PTR(BP_VAR_R));
237    FREE_OP1();
238    FREE_OP2();
239    CHECK_EXCEPTION();
240    ZEND_VM_NEXT_OPCODE();
241}
242
243ZEND_VM_HANDLER(170, ZEND_SPACESHIP, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
244{
245    USE_OPLINE
246    zend_free_op free_op1, free_op2;
247    zval *result = EX_VAR(opline->result.var);
248
249    SAVE_OPLINE();
250    compare_function(result,
251        GET_OP1_ZVAL_PTR(BP_VAR_R),
252        GET_OP2_ZVAL_PTR(BP_VAR_R));
253    FREE_OP1();
254    FREE_OP2();
255    CHECK_EXCEPTION();
256    ZEND_VM_NEXT_OPCODE();
257}
258
259ZEND_VM_HANDLER(9, ZEND_BW_OR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
260{
261    USE_OPLINE
262    zend_free_op free_op1, free_op2;
263
264    SAVE_OPLINE();
265    bitwise_or_function(EX_VAR(opline->result.var),
266        GET_OP1_ZVAL_PTR(BP_VAR_R),
267        GET_OP2_ZVAL_PTR(BP_VAR_R));
268    FREE_OP1();
269    FREE_OP2();
270    CHECK_EXCEPTION();
271    ZEND_VM_NEXT_OPCODE();
272}
273
274ZEND_VM_HANDLER(10, ZEND_BW_AND, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
275{
276    USE_OPLINE
277    zend_free_op free_op1, free_op2;
278
279    SAVE_OPLINE();
280    bitwise_and_function(EX_VAR(opline->result.var),
281        GET_OP1_ZVAL_PTR(BP_VAR_R),
282        GET_OP2_ZVAL_PTR(BP_VAR_R));
283    FREE_OP1();
284    FREE_OP2();
285    CHECK_EXCEPTION();
286    ZEND_VM_NEXT_OPCODE();
287}
288
289ZEND_VM_HANDLER(11, ZEND_BW_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
290{
291    USE_OPLINE
292    zend_free_op free_op1, free_op2;
293
294    SAVE_OPLINE();
295    bitwise_xor_function(EX_VAR(opline->result.var),
296        GET_OP1_ZVAL_PTR(BP_VAR_R),
297        GET_OP2_ZVAL_PTR(BP_VAR_R));
298    FREE_OP1();
299    FREE_OP2();
300    CHECK_EXCEPTION();
301    ZEND_VM_NEXT_OPCODE();
302}
303
304ZEND_VM_HANDLER(14, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
305{
306    USE_OPLINE
307    zend_free_op free_op1, free_op2;
308
309    SAVE_OPLINE();
310    boolean_xor_function(EX_VAR(opline->result.var),
311        GET_OP1_ZVAL_PTR(BP_VAR_R),
312        GET_OP2_ZVAL_PTR(BP_VAR_R));
313    FREE_OP1();
314    FREE_OP2();
315    CHECK_EXCEPTION();
316    ZEND_VM_NEXT_OPCODE();
317}
318
319ZEND_VM_HANDLER(12, ZEND_BW_NOT, CONST|TMPVAR|CV, ANY)
320{
321    USE_OPLINE
322    zend_free_op free_op1;
323
324    SAVE_OPLINE();
325    bitwise_not_function(EX_VAR(opline->result.var),
326        GET_OP1_ZVAL_PTR(BP_VAR_R));
327    FREE_OP1();
328    CHECK_EXCEPTION();
329    ZEND_VM_NEXT_OPCODE();
330}
331
332ZEND_VM_HANDLER(13, ZEND_BOOL_NOT, CONST|TMPVAR|CV, ANY)
333{
334    USE_OPLINE
335    zval *val;
336    zend_free_op free_op1;
337
338    SAVE_OPLINE();
339    val = GET_OP1_ZVAL_PTR(BP_VAR_R);
340    if (Z_TYPE_P(val) == IS_TRUE) {
341        ZVAL_FALSE(EX_VAR(opline->result.var));
342    } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
343        ZVAL_TRUE(EX_VAR(opline->result.var));
344    } else {
345        ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val));
346        FREE_OP1();
347        CHECK_EXCEPTION();
348    }
349    ZEND_VM_NEXT_OPCODE();
350}
351
352ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int (*binary_op)(zval *result, zval *op1, zval *op2))
353{
354    USE_OPLINE
355    zend_free_op free_op1, free_op2, free_op_data1;
356    zval *object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
357    zval *property = GET_OP2_ZVAL_PTR(BP_VAR_R);
358    zval *value;
359    zval *zptr;
360
361    if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
362        zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
363    }
364
365    do {
366        value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
367
368        if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
369            ZVAL_DEREF(object);
370            if (UNEXPECTED(!make_real_object(object))) {
371                zend_error(E_WARNING, "Attempt to assign property of non-object");
372                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
373                    ZVAL_NULL(EX_VAR(opline->result.var));
374                }
375                break;
376            }
377        }
378
379        /* here we are sure we are dealing with an object */
380        if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
381            && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
382
383            ZVAL_DEREF(zptr);
384            SEPARATE_ZVAL_NOREF(zptr);
385
386            binary_op(zptr, zptr, value);
387            if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
388                ZVAL_COPY(EX_VAR(opline->result.var), zptr);
389            }
390        } else {
391            zval *z;
392            zval rv;
393
394            if (Z_OBJ_HT_P(object)->read_property &&
395                (z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
396                if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
397                    zval rv;
398                    zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
399
400                    if (Z_REFCOUNT_P(z) == 0) {
401                        zend_objects_store_del(Z_OBJ_P(z));
402                    }
403                    ZVAL_COPY_VALUE(z, value);
404                }
405                ZVAL_DEREF(z);
406                SEPARATE_ZVAL_NOREF(z);
407                binary_op(z, z, value);
408                Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
409                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
410                    ZVAL_COPY(EX_VAR(opline->result.var), z);
411                }
412                zval_ptr_dtor(z);
413            } else {
414                zend_error(E_WARNING, "Attempt to assign property of non-object");
415                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
416                    ZVAL_NULL(EX_VAR(opline->result.var));
417                }
418            }
419        }
420    } while (0);
421
422    FREE_OP(free_op_data1);
423    FREE_OP2();
424    FREE_OP1_VAR_PTR();
425    /* assign_obj has two opcodes! */
426    CHECK_EXCEPTION();
427    ZEND_VM_INC_OPCODE();
428    ZEND_VM_NEXT_OPCODE();
429}
430
431ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, int (*binary_op)(zval *result, zval *op1, zval *op2))
432{
433    USE_OPLINE
434    zend_free_op free_op1, free_op2, free_op_data1;
435    zval *var_ptr, rv;
436    zval *value, *container, *dim;
437
438    SAVE_OPLINE();
439    container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
440    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
441        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
442    }
443
444    dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
445
446    do {
447        if (OP1_TYPE == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
448            if (OP1_TYPE != IS_UNUSED) {
449                ZVAL_DEREF(container);
450            }
451#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
452            if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
453                value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
454                zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
455                break;
456            }
457#endif
458        }
459
460        zend_fetch_dimension_address_RW(&rv, container, dim, OP2_TYPE);
461        value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
462        ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
463        var_ptr = Z_INDIRECT(rv);
464
465        if (UNEXPECTED(var_ptr == NULL)) {
466            zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
467        }
468
469        if (UNEXPECTED(var_ptr == &EG(error_zval))) {
470            if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
471                ZVAL_NULL(EX_VAR(opline->result.var));
472            }
473        } else {
474            ZVAL_DEREF(var_ptr);
475            SEPARATE_ZVAL_NOREF(var_ptr);
476
477            binary_op(var_ptr, var_ptr, value);
478
479            if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
480                ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
481            }
482        }
483    } while (0);
484
485    FREE_OP2();
486    FREE_OP(free_op_data1);
487    FREE_OP1_VAR_PTR();
488    CHECK_EXCEPTION();
489    ZEND_VM_INC_OPCODE();
490    ZEND_VM_NEXT_OPCODE();
491}
492
493ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, int (*binary_op)(zval *result, zval *op1, zval *op2))
494{
495    USE_OPLINE
496    zend_free_op free_op1, free_op2;
497    zval *var_ptr;
498    zval *value;
499
500    SAVE_OPLINE();
501    value = GET_OP2_ZVAL_PTR(BP_VAR_R);
502    var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
503
504    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
505        zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
506    }
507
508    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
509        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
510            ZVAL_NULL(EX_VAR(opline->result.var));
511        }
512    } else {
513        ZVAL_DEREF(var_ptr);
514        SEPARATE_ZVAL_NOREF(var_ptr);
515
516        binary_op(var_ptr, var_ptr, value);
517
518        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
519            ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
520        }
521    }
522
523    FREE_OP2();
524    FREE_OP1_VAR_PTR();
525    CHECK_EXCEPTION();
526    ZEND_VM_NEXT_OPCODE();
527}
528
529ZEND_VM_HANDLER(23, ZEND_ASSIGN_ADD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
530{
531#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
532    USE_OPLINE
533
534# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
535    if (EXPECTED(opline->extended_value == 0)) {
536        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, add_function);
537    }
538# endif
539    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
540        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, add_function);
541    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
542        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, add_function);
543    }
544#else
545    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, add_function);
546#endif
547}
548
549ZEND_VM_HANDLER(24, ZEND_ASSIGN_SUB, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
550{
551#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
552    USE_OPLINE
553
554# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
555    if (EXPECTED(opline->extended_value == 0)) {
556        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, sub_function);
557    }
558# endif
559    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
560        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, sub_function);
561    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
562        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, sub_function);
563    }
564#else
565    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, sub_function);
566#endif
567}
568
569ZEND_VM_HANDLER(25, ZEND_ASSIGN_MUL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
570{
571#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
572    USE_OPLINE
573
574# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
575    if (EXPECTED(opline->extended_value == 0)) {
576        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, mul_function);
577    }
578# endif
579    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
580        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mul_function);
581    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
582        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, mul_function);
583    }
584#else
585    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mul_function);
586#endif
587}
588
589ZEND_VM_HANDLER(26, ZEND_ASSIGN_DIV, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
590{
591#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
592    USE_OPLINE
593
594# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
595    if (EXPECTED(opline->extended_value == 0)) {
596        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, div_function);
597    }
598# endif
599    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
600        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, div_function);
601    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
602        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, div_function);
603    }
604#else
605    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, div_function);
606#endif
607}
608
609ZEND_VM_HANDLER(27, ZEND_ASSIGN_MOD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
610{
611#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
612    USE_OPLINE
613
614# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
615    if (EXPECTED(opline->extended_value == 0)) {
616        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, mod_function);
617    }
618# endif
619    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
620        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mod_function);
621    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
622        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, mod_function);
623    }
624#else
625    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, mod_function);
626#endif
627}
628
629ZEND_VM_HANDLER(28, ZEND_ASSIGN_SL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
630{
631#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
632    USE_OPLINE
633
634# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
635    if (EXPECTED(opline->extended_value == 0)) {
636        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, shift_left_function);
637    }
638# endif
639    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
640        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_left_function);
641    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
642        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, shift_left_function);
643    }
644#else
645    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_left_function);
646#endif
647}
648
649ZEND_VM_HANDLER(29, ZEND_ASSIGN_SR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
650{
651#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
652    USE_OPLINE
653
654# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
655    if (EXPECTED(opline->extended_value == 0)) {
656        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, shift_right_function);
657    }
658# endif
659    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
660        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_right_function);
661    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
662        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, shift_right_function);
663    }
664#else
665    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, shift_right_function);
666#endif
667}
668
669ZEND_VM_HANDLER(30, ZEND_ASSIGN_CONCAT, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
670{
671#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
672    USE_OPLINE
673
674# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
675    if (EXPECTED(opline->extended_value == 0)) {
676        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, concat_function);
677    }
678# endif
679    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
680        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, concat_function);
681    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
682        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, concat_function);
683    }
684#else
685    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, concat_function);
686#endif
687}
688
689ZEND_VM_HANDLER(31, ZEND_ASSIGN_BW_OR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
690{
691#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
692    USE_OPLINE
693
694# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
695    if (EXPECTED(opline->extended_value == 0)) {
696        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, bitwise_or_function);
697    }
698# endif
699    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
700        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_or_function);
701    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
702        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, bitwise_or_function);
703    }
704#else
705    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_or_function);
706#endif
707}
708
709ZEND_VM_HANDLER(32, ZEND_ASSIGN_BW_AND, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
710{
711#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
712    USE_OPLINE
713
714# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
715    if (EXPECTED(opline->extended_value == 0)) {
716        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, bitwise_and_function);
717    }
718# endif
719    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
720        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_and_function);
721    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
722        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, bitwise_and_function);
723    }
724#else
725    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_and_function);
726#endif
727}
728
729ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
730{
731#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
732    USE_OPLINE
733
734# if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
735    if (EXPECTED(opline->extended_value == 0)) {
736        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_helper, binary_op, bitwise_xor_function);
737    }
738# endif
739    if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
740        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_xor_function);
741    } else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
742        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_obj_helper, binary_op, bitwise_xor_function);
743    }
744#else
745    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_binary_assign_op_dim_helper, binary_op, bitwise_xor_function);
746#endif
747}
748
749ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, incdec_t incdec_op)
750{
751    USE_OPLINE
752    zend_free_op free_op1, free_op2;
753    zval *object;
754    zval *property;
755    zval *retval;
756    zval *zptr;
757
758    SAVE_OPLINE();
759    object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
760    property = GET_OP2_ZVAL_PTR(BP_VAR_R);
761    retval = EX_VAR(opline->result.var);
762
763    if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
764        zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
765    }
766
767    do {
768        if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
769            ZVAL_DEREF(object);
770            if (UNEXPECTED(!make_real_object(object))) {
771                zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
772                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
773                    ZVAL_NULL(retval);
774                }
775                break;
776            }
777        }
778
779        /* here we are sure we are dealing with an object */
780
781        if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
782            && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
783
784            ZVAL_DEREF(zptr);
785            SEPARATE_ZVAL_NOREF(zptr);
786
787            incdec_op(zptr);
788            if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
789                ZVAL_COPY(retval, zptr);
790            }
791        } else {
792            zval rv;
793
794            if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
795                zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
796
797                if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
798                    zval rv;
799                    zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
800
801                    if (Z_REFCOUNT_P(z) == 0) {
802                        zend_objects_store_del(Z_OBJ_P(z));
803                    }
804                    ZVAL_COPY_VALUE(z, value);
805                }
806                ZVAL_DEREF(z);
807                SEPARATE_ZVAL_NOREF(z);
808                incdec_op(z);
809                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
810                    ZVAL_COPY(retval, z);
811                }
812                Z_OBJ_HT_P(object)->write_property(object, property, z, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
813                zval_ptr_dtor(z);
814            } else {
815                zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
816                if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
817                    ZVAL_NULL(retval);
818                }
819            }
820        }
821    } while (0);
822
823    FREE_OP2();
824    FREE_OP1_VAR_PTR();
825    CHECK_EXCEPTION();
826    ZEND_VM_NEXT_OPCODE();
827}
828
829ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
830{
831    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, incdec_op, increment_function);
832}
833
834ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
835{
836    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, incdec_op, decrement_function);
837}
838
839ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, incdec_t incdec_op)
840{
841    USE_OPLINE
842    zend_free_op free_op1, free_op2;
843    zval *object;
844    zval *property;
845    zval *retval;
846    zval *zptr;
847
848    SAVE_OPLINE();
849    object = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
850    property = GET_OP2_ZVAL_PTR(BP_VAR_R);
851    retval = EX_VAR(opline->result.var);
852
853    if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
854        zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
855    }
856
857    do {
858        if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
859            ZVAL_DEREF(object);
860            if (UNEXPECTED(!make_real_object(object))) {
861                zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
862                ZVAL_NULL(retval);
863                break;
864            }
865        }
866
867        /* here we are sure we are dealing with an object */
868
869        if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
870            && EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
871
872            ZVAL_DEREF(zptr);
873            ZVAL_COPY_VALUE(retval, zptr);
874            zval_opt_copy_ctor(zptr);
875
876            incdec_op(zptr);
877        } else {
878            if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
879                zval rv;
880                zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
881                zval z_copy;
882
883                if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
884                    zval rv;
885                    zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
886
887                    if (Z_REFCOUNT_P(z) == 0) {
888                        zend_objects_store_del(Z_OBJ_P(z));
889                    }
890                    ZVAL_COPY_VALUE(z, value);
891                }
892                ZVAL_DUP(retval, z);
893                ZVAL_DUP(&z_copy, z);
894                incdec_op(&z_copy);
895                if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
896                Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
897                zval_ptr_dtor(&z_copy);
898                zval_ptr_dtor(z);
899            } else {
900                zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
901                ZVAL_NULL(retval);
902            }
903        }
904    } while (0);
905
906    FREE_OP2();
907    FREE_OP1_VAR_PTR();
908    CHECK_EXCEPTION();
909    ZEND_VM_NEXT_OPCODE();
910}
911
912ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
913{
914    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, incdec_op, increment_function);
915}
916
917ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
918{
919    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, incdec_op, decrement_function);
920}
921
922ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
923{
924    USE_OPLINE
925    zend_free_op free_op1;
926    zval *var_ptr;
927
928    SAVE_OPLINE();
929    var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
930
931    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
932        zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
933    }
934
935    if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
936        fast_increment_function(var_ptr);
937        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
938            ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
939        }
940        ZEND_VM_NEXT_OPCODE();
941    }
942
943    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
944        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
945            ZVAL_NULL(EX_VAR(opline->result.var));
946        }
947        CHECK_EXCEPTION();
948        ZEND_VM_NEXT_OPCODE();
949    }
950
951    ZVAL_DEREF(var_ptr);
952    SEPARATE_ZVAL_NOREF(var_ptr);
953
954    increment_function(var_ptr);
955
956    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
957        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
958    }
959
960    FREE_OP1_VAR_PTR();
961    CHECK_EXCEPTION();
962    ZEND_VM_NEXT_OPCODE();
963}
964
965ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY)
966{
967    USE_OPLINE
968    zend_free_op free_op1;
969    zval *var_ptr;
970
971    SAVE_OPLINE();
972    var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
973
974    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
975        zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
976    }
977
978    if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
979        fast_decrement_function(var_ptr);
980        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
981            ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
982        }
983        ZEND_VM_NEXT_OPCODE();
984    }
985
986    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
987        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
988            ZVAL_NULL(EX_VAR(opline->result.var));
989        }
990        CHECK_EXCEPTION();
991        ZEND_VM_NEXT_OPCODE();
992    }
993
994    ZVAL_DEREF(var_ptr);
995    SEPARATE_ZVAL_NOREF(var_ptr);
996
997    decrement_function(var_ptr);
998
999    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1000        ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
1001    }
1002
1003    FREE_OP1_VAR_PTR();
1004    CHECK_EXCEPTION();
1005    ZEND_VM_NEXT_OPCODE();
1006}
1007
1008ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
1009{
1010    USE_OPLINE
1011    zend_free_op free_op1;
1012    zval *var_ptr;
1013
1014    SAVE_OPLINE();
1015    var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
1016
1017    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
1018        zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
1019    }
1020
1021    if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
1022        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
1023        fast_increment_function(var_ptr);
1024        ZEND_VM_NEXT_OPCODE();
1025    }
1026
1027    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
1028        ZVAL_NULL(EX_VAR(opline->result.var));
1029        CHECK_EXCEPTION();
1030        ZEND_VM_NEXT_OPCODE();
1031    }
1032
1033    ZVAL_DEREF(var_ptr);
1034    ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
1035    zval_opt_copy_ctor(var_ptr);
1036
1037    increment_function(var_ptr);
1038
1039    FREE_OP1_VAR_PTR();
1040    CHECK_EXCEPTION();
1041    ZEND_VM_NEXT_OPCODE();
1042}
1043
1044ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
1045{
1046    USE_OPLINE
1047    zend_free_op free_op1;
1048    zval *var_ptr;
1049
1050    SAVE_OPLINE();
1051    var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
1052
1053    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
1054        zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
1055    }
1056
1057    if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
1058        ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
1059        fast_decrement_function(var_ptr);
1060        ZEND_VM_NEXT_OPCODE();
1061    }
1062
1063    if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
1064        ZVAL_NULL(EX_VAR(opline->result.var));
1065        CHECK_EXCEPTION();
1066        ZEND_VM_NEXT_OPCODE();
1067    }
1068
1069    ZVAL_DEREF(var_ptr);
1070    ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
1071    zval_opt_copy_ctor(var_ptr);
1072
1073    decrement_function(var_ptr);
1074
1075    FREE_OP1_VAR_PTR();
1076    CHECK_EXCEPTION();
1077    ZEND_VM_NEXT_OPCODE();
1078}
1079
1080ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
1081{
1082    USE_OPLINE
1083    zend_free_op free_op1;
1084    zval *z;
1085
1086    SAVE_OPLINE();
1087    z = GET_OP1_ZVAL_PTR(BP_VAR_R);
1088
1089    if (Z_TYPE_P(z) == IS_STRING) {
1090        zend_string *str = Z_STR_P(z);
1091
1092        if (str->len != 0) {
1093            zend_write(str->val, str->len);
1094        }
1095    } else {
1096        zend_string *str = _zval_get_string_func(z);
1097
1098        if (str->len != 0) {
1099            zend_write(str->val, str->len);
1100        }
1101        zend_string_release(str);
1102    }
1103
1104    FREE_OP1();
1105    CHECK_EXCEPTION();
1106    ZEND_VM_NEXT_OPCODE();
1107}
1108
1109ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
1110{
1111    USE_OPLINE
1112    zend_free_op free_op1;
1113    zval *varname;
1114    zval *retval;
1115    zend_string *name;
1116    HashTable *target_symbol_table;
1117
1118    SAVE_OPLINE();
1119    varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
1120
1121    if (OP1_TYPE == IS_CONST) {
1122        name = Z_STR_P(varname);
1123    } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
1124        name = Z_STR_P(varname);
1125        zend_string_addref(name);
1126    } else {
1127        name = zval_get_string(varname);
1128    }
1129
1130    if (OP2_TYPE != IS_UNUSED) {
1131        zend_class_entry *ce;
1132
1133        if (OP2_TYPE == IS_CONST) {
1134            if (OP1_TYPE == IS_CONST && CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
1135
1136                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
1137                retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
1138
1139                /* check if static properties were destoyed */
1140                if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
1141                    zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val);
1142                }
1143
1144                ZEND_VM_C_GOTO(fetch_var_return);
1145            } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
1146                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
1147            } else {
1148                ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
1149                if (UNEXPECTED(ce == NULL)) {
1150                    if (OP1_TYPE != IS_CONST) {
1151                        zend_string_release(name);
1152                    }
1153                    FREE_OP1();
1154                    CHECK_EXCEPTION();
1155                    ZEND_VM_NEXT_OPCODE();
1156                }
1157                CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
1158            }
1159        } else {
1160            ce = Z_CE_P(EX_VAR(opline->op2.var));
1161            if (OP1_TYPE == IS_CONST &&
1162                (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
1163
1164                /* check if static properties were destoyed */
1165                if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
1166                    zend_error_noreturn(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name->val, name->val);
1167                }
1168
1169                ZEND_VM_C_GOTO(fetch_var_return);
1170            }
1171        }
1172        retval = zend_std_get_static_property(ce, name, 0);
1173        if (OP1_TYPE == IS_CONST && retval) {
1174            CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
1175        }
1176
1177        FREE_OP1();
1178    } else {
1179        target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
1180        retval = zend_hash_find(target_symbol_table, name);
1181        if (retval == NULL) {
1182            switch (type) {
1183                case BP_VAR_R:
1184                case BP_VAR_UNSET:
1185                    zend_error(E_NOTICE,"Undefined variable: %s", name->val);
1186                    /* break missing intentionally */
1187                case BP_VAR_IS:
1188                    retval = &EG(uninitialized_zval);
1189                    break;
1190                case BP_VAR_RW:
1191                    zend_error(E_NOTICE,"Undefined variable: %s", name->val);
1192                    /* break missing intentionally */
1193                case BP_VAR_W:
1194                    retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
1195                    break;
1196                EMPTY_SWITCH_DEFAULT_CASE()
1197            }
1198        /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
1199        } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
1200            retval = Z_INDIRECT_P(retval);
1201            if (Z_TYPE_P(retval) == IS_UNDEF) {
1202                switch (type) {
1203                    case BP_VAR_R:
1204                    case BP_VAR_UNSET:
1205                        zend_error(E_NOTICE,"Undefined variable: %s", name->val);
1206                        /* break missing intentionally */
1207                    case BP_VAR_IS:
1208                        retval = &EG(uninitialized_zval);
1209                        break;
1210                    case BP_VAR_RW:
1211                        zend_error(E_NOTICE,"Undefined variable: %s", name->val);
1212                        /* break missing intentionally */
1213                    case BP_VAR_W:
1214                        ZVAL_NULL(retval);
1215                        break;
1216                    EMPTY_SWITCH_DEFAULT_CASE()
1217                }
1218            }
1219        }
1220        if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
1221            if (Z_CONSTANT_P(retval)) {
1222                zval_update_constant(retval, 1);
1223            }
1224        } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
1225            FREE_OP1();
1226        }
1227    }
1228
1229    if (OP1_TYPE != IS_CONST) {
1230        zend_string_release(name);
1231    }
1232
1233ZEND_VM_C_LABEL(fetch_var_return):
1234    ZEND_ASSERT(retval != NULL);
1235    if (type == BP_VAR_R || type == BP_VAR_IS) {
1236        if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
1237            ZVAL_UNREF(retval);
1238        }
1239        ZVAL_COPY(EX_VAR(opline->result.var), retval);
1240    } else {
1241        ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
1242    }
1243    CHECK_EXCEPTION();
1244    ZEND_VM_NEXT_OPCODE();
1245}
1246
1247ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
1248{
1249    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R);
1250}
1251
1252ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
1253{
1254    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W);
1255}
1256
1257ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
1258{
1259    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_RW);
1260}
1261
1262ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
1263{
1264    USE_OPLINE
1265
1266    if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
1267        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W);
1268    } else {
1269        ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R);
1270    }
1271}
1272
1273ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
1274{
1275    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
1276}
1277
1278ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
1279{
1280    ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_IS);
1281}
1282
1283ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
1284{
1285    USE_OPLINE
1286    zend_free_op free_op1, free_op2;
1287    zval *container;
1288
1289    SAVE_OPLINE();
1290    container = GET_OP1_ZVAL_PTR(BP_VAR_R);
1291    zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
1292    FREE_OP2();
1293    FREE_OP1();
1294    CHECK_EXCEPTION();
1295    ZEND_VM_NEXT_OPCODE();
1296}
1297
1298ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|CV)
1299{
1300    USE_OPLINE
1301    zend_free_op free_op1, free_op2;
1302    zval *container;
1303
1304    SAVE_OPLINE();
1305    container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1306
1307    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1308        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
1309    }
1310    zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
1311    FREE_OP2();
1312    if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1313        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1314    }
1315    FREE_OP1_VAR_PTR();
1316    CHECK_EXCEPTION();
1317    ZEND_VM_NEXT_OPCODE();
1318}
1319
1320ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|CV)
1321{
1322    USE_OPLINE
1323    zend_free_op free_op1, free_op2;
1324    zval *container;
1325
1326    SAVE_OPLINE();
1327    container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW);
1328
1329    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1330        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
1331    }
1332    zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
1333    FREE_OP2();
1334    if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1335        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1336    }
1337    FREE_OP1_VAR_PTR();
1338    CHECK_EXCEPTION();
1339    ZEND_VM_NEXT_OPCODE();
1340}
1341
1342ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
1343{
1344    USE_OPLINE
1345    zend_free_op free_op1, free_op2;
1346    zval *container;
1347
1348    SAVE_OPLINE();
1349    container = GET_OP1_ZVAL_PTR(BP_VAR_IS);
1350    zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
1351    FREE_OP2();
1352    FREE_OP1();
1353    CHECK_EXCEPTION();
1354    ZEND_VM_NEXT_OPCODE();
1355}
1356
1357ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|CV)
1358{
1359    USE_OPLINE
1360    zval *container;
1361    zend_free_op free_op1, free_op2;
1362
1363    SAVE_OPLINE();
1364
1365    if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
1366        if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
1367            zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
1368        }
1369        container = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1370        if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1371            zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
1372        }
1373        zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
1374        if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1375            EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1376        }
1377        FREE_OP2();
1378        FREE_OP1_VAR_PTR();
1379    } else {
1380        if (OP2_TYPE == IS_UNUSED) {
1381            zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
1382        }
1383        container = GET_OP1_ZVAL_PTR(BP_VAR_R);
1384        zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
1385        FREE_OP2();
1386        FREE_OP1();
1387    }
1388    CHECK_EXCEPTION();
1389    ZEND_VM_NEXT_OPCODE();
1390}
1391
1392ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV)
1393{
1394    USE_OPLINE
1395    zend_free_op free_op1, free_op2;
1396    zval *container;
1397
1398    SAVE_OPLINE();
1399    container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_UNSET);
1400
1401    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1402        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
1403    }
1404    zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
1405    FREE_OP2();
1406    if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1407        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1408    }
1409    FREE_OP1_VAR_PTR();
1410    CHECK_EXCEPTION();
1411    ZEND_VM_NEXT_OPCODE();
1412}
1413
1414ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV)
1415{
1416    USE_OPLINE
1417    zend_free_op free_op1;
1418    zval *container;
1419    zend_free_op free_op2;
1420    zval *offset;
1421
1422    SAVE_OPLINE();
1423    container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
1424    offset  = GET_OP2_ZVAL_PTR(BP_VAR_R);
1425
1426    if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1427        if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
1428            container = Z_REFVAL_P(container);
1429            if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1430                ZEND_VM_C_GOTO(fetch_obj_r_no_object);
1431            }
1432        } else {
1433            ZEND_VM_C_GOTO(fetch_obj_r_no_object);
1434        }
1435    }
1436
1437    /* here we are sure we are dealing with an object */
1438    do {
1439        zend_object *zobj = Z_OBJ_P(container);
1440        zval *retval;
1441
1442        if (OP2_TYPE == IS_CONST &&
1443            EXPECTED(zobj->ce == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
1444            uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(offset) + sizeof(void*));
1445
1446            if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
1447                retval = OBJ_PROP(zobj, prop_offset);
1448                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
1449                    ZVAL_COPY(EX_VAR(opline->result.var), retval);
1450                    break;
1451                }
1452            } else if (EXPECTED(zobj->properties != NULL)) {
1453                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
1454                if (EXPECTED(retval)) {
1455                    ZVAL_COPY(EX_VAR(opline->result.var), retval);
1456                    break;
1457                }
1458            }
1459        }
1460
1461        if (UNEXPECTED(zobj->handlers->read_property == NULL)) {
1462ZEND_VM_C_LABEL(fetch_obj_r_no_object):
1463            zend_error(E_NOTICE, "Trying to get property of non-object");
1464            ZVAL_NULL(EX_VAR(opline->result.var));
1465        } else {
1466            retval = zobj->handlers->read_property(container, offset, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
1467
1468            if (retval != EX_VAR(opline->result.var)) {
1469                ZVAL_COPY(EX_VAR(opline->result.var), retval);
1470            }
1471        }
1472    } while (0);
1473
1474    FREE_OP2();
1475    FREE_OP1();
1476    CHECK_EXCEPTION();
1477    ZEND_VM_NEXT_OPCODE();
1478}
1479
1480ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV)
1481{
1482    USE_OPLINE
1483    zend_free_op free_op1, free_op2;
1484    zval *property;
1485    zval *container;
1486
1487    SAVE_OPLINE();
1488    property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1489
1490    container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1491    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1492        zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
1493    }
1494
1495    zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
1496    FREE_OP2();
1497    if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1498        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1499    }
1500    FREE_OP1_VAR_PTR();
1501    CHECK_EXCEPTION();
1502    ZEND_VM_NEXT_OPCODE();
1503}
1504
1505ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV)
1506{
1507    USE_OPLINE
1508    zend_free_op free_op1, free_op2;
1509    zval *property;
1510    zval *container;
1511
1512    SAVE_OPLINE();
1513    property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1514    container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_RW);
1515
1516    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1517        zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
1518    }
1519    zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
1520    FREE_OP2();
1521    if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1522        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1523    }
1524    FREE_OP1_VAR_PTR();
1525    CHECK_EXCEPTION();
1526    ZEND_VM_NEXT_OPCODE();
1527}
1528
1529ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
1530{
1531    USE_OPLINE
1532    zend_free_op free_op1;
1533    zval *container;
1534    zend_free_op free_op2;
1535    zval *offset;
1536
1537    SAVE_OPLINE();
1538    container = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_IS);
1539    offset  = GET_OP2_ZVAL_PTR(BP_VAR_R);
1540
1541    if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1542        if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
1543            container = Z_REFVAL_P(container);
1544            if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1545                ZEND_VM_C_GOTO(fetch_obj_is_no_object);
1546            }
1547        } else {
1548            ZEND_VM_C_GOTO(fetch_obj_is_no_object);
1549        }
1550    }
1551
1552    /* here we are sure we are dealing with an object */
1553    do {
1554        zend_object *zobj = Z_OBJ_P(container);
1555        zval *retval;
1556
1557        if (OP2_TYPE == IS_CONST &&
1558            EXPECTED(zobj->ce == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
1559            uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(offset) + sizeof(void*));
1560
1561            if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
1562                retval = OBJ_PROP(zobj, prop_offset);
1563                if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
1564                    ZVAL_COPY(EX_VAR(opline->result.var), retval);
1565                    break;
1566                }
1567            } else if (EXPECTED(zobj->properties != NULL)) {
1568                retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
1569                if (EXPECTED(retval)) {
1570                    ZVAL_COPY(EX_VAR(opline->result.var), retval);
1571                    break;
1572                }
1573            }
1574        }
1575
1576        if (UNEXPECTED(zobj->handlers->read_property == NULL)) {
1577ZEND_VM_C_LABEL(fetch_obj_is_no_object):
1578            ZVAL_NULL(EX_VAR(opline->result.var));
1579        } else {
1580
1581            retval = zobj->handlers->read_property(container, offset, BP_VAR_IS, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
1582
1583            if (retval != EX_VAR(opline->result.var)) {
1584                ZVAL_COPY(EX_VAR(opline->result.var), retval);
1585            }
1586        }
1587    } while (0);
1588
1589    FREE_OP2();
1590    FREE_OP1();
1591    CHECK_EXCEPTION();
1592    ZEND_VM_NEXT_OPCODE();
1593}
1594
1595ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV)
1596{
1597    USE_OPLINE
1598    zval *container;
1599
1600    if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
1601        /* Behave like FETCH_OBJ_W */
1602        zend_free_op free_op1, free_op2;
1603        zval *property;
1604
1605        SAVE_OPLINE();
1606        property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1607        container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1608
1609        if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
1610            zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
1611        }
1612        if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1613            zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
1614        }
1615        zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
1616        FREE_OP2();
1617        if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1618            EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1619        }
1620        FREE_OP1_VAR_PTR();
1621        CHECK_EXCEPTION();
1622        ZEND_VM_NEXT_OPCODE();
1623    } else {
1624        ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_OBJ_R);
1625    }
1626}
1627
1628ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMPVAR|CV)
1629{
1630    USE_OPLINE
1631    zend_free_op free_op1, free_op2;
1632    zval *container, *property;
1633
1634    SAVE_OPLINE();
1635    container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
1636    property = GET_OP2_ZVAL_PTR(BP_VAR_R);
1637
1638    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
1639        zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
1640    }
1641    zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
1642    FREE_OP2();
1643    if (OP1_TYPE == IS_VAR && READY_TO_DESTROY(free_op1)) {
1644        EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
1645    }
1646    FREE_OP1_VAR_PTR();
1647    CHECK_EXCEPTION();
1648    ZEND_VM_NEXT_OPCODE();
1649}
1650
1651ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMPVAR|CV, CONST)
1652{
1653    USE_OPLINE
1654    zend_free_op free_op1;
1655    zval *container;
1656
1657    SAVE_OPLINE();
1658    container = GET_OP1_ZVAL_PTR(BP_VAR_R);
1659
1660ZEND_VM_C_LABEL(try_fetch_list):
1661    if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1662        zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), EX_CONSTANT(opline->op2), OP2_TYPE, BP_VAR_R);
1663
1664        ZVAL_COPY(EX_VAR(opline->result.var), value);
1665    } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
1666               EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
1667        zval *result = EX_VAR(opline->result.var);
1668        zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
1669
1670        if (retval) {
1671            if (result != retval) {
1672                ZVAL_COPY(result, retval);
1673            }
1674        } else {
1675            ZVAL_NULL(result);
1676        }
1677    } else if (Z_TYPE_P(container) == IS_REFERENCE) {
1678        container = Z_REFVAL_P(container);
1679        ZEND_VM_C_GOTO(try_fetch_list);
1680    } else {
1681        ZVAL_NULL(EX_VAR(opline->result.var));
1682    }
1683    CHECK_EXCEPTION();
1684    ZEND_VM_NEXT_OPCODE();
1685}
1686
1687ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
1688{
1689    USE_OPLINE
1690    zend_free_op free_op1, free_op2;
1691    zval *object;
1692    zval *property_name;
1693
1694    SAVE_OPLINE();
1695    object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1696    property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
1697
1698    if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
1699        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
1700    }
1701    zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
1702    FREE_OP2();
1703    FREE_OP1_VAR_PTR();
1704    /* assign_obj has two opcodes! */
1705    CHECK_EXCEPTION();
1706    ZEND_VM_INC_OPCODE();
1707    ZEND_VM_NEXT_OPCODE();
1708}
1709
1710ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|CV)
1711{
1712    USE_OPLINE
1713    zend_free_op free_op1;
1714    zval *object_ptr;
1715    zend_free_op free_op2, free_op_data1;
1716    zval *value;
1717    zval *variable_ptr;
1718    zval *dim;
1719
1720    SAVE_OPLINE();
1721    object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1722
1723    if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
1724        zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
1725    }
1726
1727ZEND_VM_C_LABEL(try_assign_dim):
1728    if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
1729ZEND_VM_C_LABEL(try_assign_dim_array):
1730        if (OP2_TYPE == IS_UNUSED) {
1731            SEPARATE_ARRAY(object_ptr);
1732            variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval));
1733            if (UNEXPECTED(variable_ptr == NULL)) {
1734                zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1735                variable_ptr = &EG(error_zval);
1736            }
1737        } else {
1738            dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
1739            SEPARATE_ARRAY(object_ptr);
1740            variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, OP2_TYPE, BP_VAR_W);
1741            FREE_OP2();
1742        }
1743        value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
1744        if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
1745            FREE_OP(free_op_data1);
1746            if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1747                ZVAL_NULL(EX_VAR(opline->result.var));
1748            }
1749        } else {
1750            value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
1751            if ((opline+1)->op1_type == IS_VAR) {
1752                FREE_OP(free_op_data1);
1753            }
1754            if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1755                ZVAL_COPY(EX_VAR(opline->result.var), value);
1756            }
1757        }
1758    } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
1759        zend_free_op free_op2;
1760        zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
1761
1762        zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
1763        FREE_OP2();
1764    } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
1765        if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
1766            zend_long offset;
1767
1768            dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
1769            offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
1770            FREE_OP2();
1771            value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
1772            zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
1773            FREE_OP(free_op_data1);
1774        } else {
1775            zval_ptr_dtor_nogc(object_ptr);
1776ZEND_VM_C_LABEL(assign_dim_convert_to_array):
1777            ZVAL_NEW_ARR(object_ptr);
1778            zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
1779            ZEND_VM_C_GOTO(try_assign_dim_array);
1780        }
1781    } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
1782        object_ptr = Z_REFVAL_P(object_ptr);
1783        ZEND_VM_C_GOTO(try_assign_dim);
1784    } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
1785        if (UNEXPECTED(object_ptr == &EG(error_zval))) {
1786            ZEND_VM_C_GOTO(assign_dim_clean);
1787        }
1788        ZEND_VM_C_GOTO(assign_dim_convert_to_array);
1789    } else {
1790        zend_error(E_WARNING, "Cannot use a scalar value as an array");
1791ZEND_VM_C_LABEL(assign_dim_clean):
1792        dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
1793        FREE_OP2();
1794        value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
1795        FREE_OP(free_op_data1);
1796        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1797            ZVAL_NULL(EX_VAR(opline->result.var));
1798        }
1799    }
1800    FREE_OP1_VAR_PTR();
1801    /* assign_dim has two opcodes! */
1802    CHECK_EXCEPTION();
1803    ZEND_VM_INC_OPCODE();
1804    ZEND_VM_NEXT_OPCODE();
1805}
1806
1807ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV)
1808{
1809    USE_OPLINE
1810    zend_free_op free_op1, free_op2;
1811    zval *value;
1812    zval *variable_ptr;
1813
1814    SAVE_OPLINE();
1815    value = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
1816    variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1817
1818    if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
1819        if (OP2_TYPE == IS_TMP_VAR) {
1820            FREE_OP2();
1821        }
1822        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1823            ZVAL_NULL(EX_VAR(opline->result.var));
1824        }
1825    } else {
1826        value = zend_assign_to_variable(variable_ptr, value, OP2_TYPE);
1827        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1828            ZVAL_COPY(EX_VAR(opline->result.var), value);
1829        }
1830        FREE_OP1_VAR_PTR();
1831    }
1832
1833    /* zend_assign_to_variable() always takes care of op2, never free it! */
1834    FREE_OP2_IF_VAR();
1835
1836    CHECK_EXCEPTION();
1837    ZEND_VM_NEXT_OPCODE();
1838}
1839
1840ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
1841{
1842    USE_OPLINE
1843    zend_free_op free_op1, free_op2;
1844    zval *variable_ptr;
1845    zval *value_ptr;
1846
1847    SAVE_OPLINE();
1848    value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W);
1849
1850    if (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
1851        zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
1852    }
1853    if (OP2_TYPE == IS_VAR &&
1854        (value_ptr == &EG(uninitialized_zval) ||
1855         (opline->extended_value == ZEND_RETURNS_FUNCTION &&
1856          !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
1857        if (!OP2_FREE) {
1858            PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */
1859        }
1860        zend_error(E_STRICT, "Only variables should be assigned by reference");
1861        if (UNEXPECTED(EG(exception) != NULL)) {
1862            FREE_OP2_VAR_PTR();
1863            HANDLE_EXCEPTION();
1864        }
1865        ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ASSIGN);
1866    }
1867
1868    variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
1869    if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
1870        zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
1871    }
1872    if (OP1_TYPE == IS_VAR &&
1873        UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) &&
1874        UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
1875        zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
1876    }
1877    if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
1878        (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) {
1879        variable_ptr = &EG(uninitialized_zval);
1880    } else {
1881        zend_assign_to_variable_reference(variable_ptr, value_ptr);
1882    }
1883
1884    if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1885        ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
1886    }
1887
1888    FREE_OP1_VAR_PTR();
1889    FREE_OP2_VAR_PTR();
1890
1891    CHECK_EXCEPTION();
1892    ZEND_VM_NEXT_OPCODE();
1893}
1894
1895ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
1896{
1897    zend_execute_data *old_execute_data;
1898    zend_call_kind call_kind = EX_CALL_KIND();
1899
1900    if (call_kind == ZEND_CALL_NESTED_FUNCTION) {
1901        zend_object *object;
1902
1903        i_free_compiled_variables(execute_data);
1904        if (UNEXPECTED(EX(symbol_table) != NULL)) {
1905            zend_clean_and_cache_symbol_table(EX(symbol_table));
1906        }
1907        zend_vm_stack_free_extra_args(execute_data);
1908        old_execute_data = execute_data;
1909        execute_data = EG(current_execute_data) = EX(prev_execute_data);
1910        if (UNEXPECTED((old_execute_data->func->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && old_execute_data->func->op_array.prototype) {
1911            OBJ_RELEASE((zend_object*)old_execute_data->func->op_array.prototype);
1912        }
1913        object = Z_OBJ(old_execute_data->This);
1914        zend_vm_stack_free_call_frame(old_execute_data);
1915
1916        if (object) {
1917            if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
1918                if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
1919                    GC_REFCOUNT(object)--;
1920                }
1921                if (GC_REFCOUNT(object) == 1) {
1922                    zend_object_store_ctor_failed(object);
1923                }
1924            }
1925            OBJ_RELEASE(object);
1926        }
1927        EG(scope) = EX(func)->op_array.scope;
1928
1929        if (UNEXPECTED(EG(exception) != NULL)) {
1930            const zend_op *opline = EX(opline);
1931            zend_throw_exception_internal(NULL);
1932            if (RETURN_VALUE_USED(opline)) {
1933                zval_ptr_dtor(EX_VAR(opline->result.var));
1934            }
1935            HANDLE_EXCEPTION_LEAVE();
1936        }
1937
1938        LOAD_OPLINE();
1939        ZEND_VM_INC_OPCODE();
1940        ZEND_VM_LEAVE();
1941    } else if (call_kind == ZEND_CALL_NESTED_CODE) {
1942        zend_detach_symbol_table(execute_data);
1943        destroy_op_array(&EX(func)->op_array);
1944        efree_size(EX(func), sizeof(zend_op_array));
1945        old_execute_data = execute_data;
1946        execute_data = EG(current_execute_data) = EX(prev_execute_data);
1947        zend_vm_stack_free_call_frame(old_execute_data);
1948
1949        zend_attach_symbol_table(execute_data);
1950        if (UNEXPECTED(EG(exception) != NULL)) {
1951            zend_throw_exception_internal(NULL);
1952            HANDLE_EXCEPTION_LEAVE();
1953        }
1954
1955        LOAD_OPLINE();
1956        ZEND_VM_INC_OPCODE();
1957        ZEND_VM_LEAVE();
1958    } else {
1959        if (call_kind == ZEND_CALL_TOP_FUNCTION) {
1960            i_free_compiled_variables(execute_data);
1961            if (UNEXPECTED(EX(symbol_table) != NULL)) {
1962                zend_clean_and_cache_symbol_table(EX(symbol_table));
1963            }
1964            zend_vm_stack_free_extra_args(execute_data);
1965            EG(current_execute_data) = EX(prev_execute_data);
1966            if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
1967                OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
1968            }
1969        } else /* if (call_kind == ZEND_CALL_TOP_CODE) */ {
1970            zend_array *symbol_table = EX(symbol_table);
1971
1972            zend_detach_symbol_table(execute_data);
1973            old_execute_data = EX(prev_execute_data);
1974            while (old_execute_data) {
1975                if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) {
1976                    if (old_execute_data->symbol_table == symbol_table) {
1977                        zend_attach_symbol_table(old_execute_data);
1978                    }
1979                    break;
1980                }
1981                old_execute_data = old_execute_data->prev_execute_data;
1982            }
1983            EG(current_execute_data) = EX(prev_execute_data);
1984        }
1985        zend_vm_stack_free_call_frame(execute_data);
1986
1987        ZEND_VM_RETURN();
1988    }
1989}
1990
1991ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
1992{
1993    USE_OPLINE
1994
1995    ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
1996    ZEND_VM_CONTINUE();
1997}
1998
1999ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, ANY)
2000{
2001    USE_OPLINE
2002    zend_free_op free_op1;
2003    zval *val;
2004
2005    SAVE_OPLINE();
2006    val = GET_OP1_ZVAL_PTR(BP_VAR_R);
2007
2008    if (Z_TYPE_P(val) == IS_TRUE) {
2009        ZEND_VM_SET_OPCODE(opline + 1);
2010        ZEND_VM_CONTINUE();
2011    } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
2012        if (OP1_TYPE == IS_CV) {
2013            ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
2014        } else {
2015            ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
2016            ZEND_VM_CONTINUE();
2017        }
2018    }
2019
2020    if (i_zend_is_true(val)) {
2021        opline++;
2022    } else {
2023        opline = OP_JMP_ADDR(opline, opline->op2);
2024    }
2025    FREE_OP1();
2026    if (UNEXPECTED(EG(exception) != NULL)) {
2027        HANDLE_EXCEPTION();
2028    }
2029    ZEND_VM_JMP(opline);
2030}
2031
2032ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, ANY)
2033{
2034    USE_OPLINE
2035    zend_free_op free_op1;
2036    zval *val;
2037
2038    SAVE_OPLINE();
2039    val = GET_OP1_ZVAL_PTR(BP_VAR_R);
2040
2041    if (Z_TYPE_P(val) == IS_TRUE) {
2042        ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
2043        ZEND_VM_CONTINUE();
2044    } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
2045        if (OP1_TYPE == IS_CV) {
2046            ZEND_VM_NEXT_OPCODE();
2047        } else {
2048            ZEND_VM_SET_OPCODE(opline + 1);
2049            ZEND_VM_CONTINUE();
2050        }
2051    }
2052
2053    if (i_zend_is_true(val)) {
2054        opline = OP_JMP_ADDR(opline, opline->op2);
2055    } else {
2056        opline++;
2057    }
2058    FREE_OP1();
2059    if (UNEXPECTED(EG(exception) != NULL)) {
2060        HANDLE_EXCEPTION();
2061    }
2062    ZEND_VM_JMP(opline);
2063}
2064
2065ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, ANY)
2066{
2067    USE_OPLINE
2068    zend_free_op free_op1;
2069    zval *val;
2070
2071    SAVE_OPLINE();
2072    val = GET_OP1_ZVAL_PTR(BP_VAR_R);
2073
2074    if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) {
2075        ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
2076        ZEND_VM_CONTINUE();
2077    } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
2078        if (OP1_TYPE == IS_CV) {
2079            ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
2080        } else {
2081            ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
2082            ZEND_VM_CONTINUE();
2083        }
2084    }
2085
2086    if (i_zend_is_true(val)) {
2087        opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
2088    } else {
2089        opline = OP_JMP_ADDR(opline, opline->op2);
2090    }
2091    FREE_OP1();
2092    if (UNEXPECTED(EG(exception) != NULL)) {
2093        HANDLE_EXCEPTION();
2094    }
2095    ZEND_VM_JMP(opline);
2096}
2097
2098ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, ANY)
2099{
2100    USE_OPLINE
2101    zend_free_op free_op1;
2102    zval *val;
2103    int ret;
2104
2105    SAVE_OPLINE();
2106    val = GET_OP1_ZVAL_PTR(BP_VAR_R);
2107
2108    if (Z_TYPE_P(val) == IS_TRUE) {
2109        ZVAL_TRUE(EX_VAR(opline->result.var));
2110        ZEND_VM_SET_OPCODE(opline + 1);
2111        ZEND_VM_CONTINUE();
2112    } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
2113        ZVAL_FALSE(EX_VAR(opline->result.var));
2114        if (OP1_TYPE == IS_CV) {
2115            ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
2116        } else {
2117            ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
2118            ZEND_VM_CONTINUE();
2119        }
2120    }
2121
2122    ret = i_zend_is_true(val);
2123    FREE_OP1();
2124    if (ret) {
2125        ZVAL_TRUE(EX_VAR(opline->result.var));
2126        opline++;
2127    } else {
2128        ZVAL_FALSE(EX_VAR(opline->result.var));
2129        opline = OP_JMP_ADDR(opline, opline->op2);
2130    }
2131    if (UNEXPECTED(EG(exception) != NULL)) {
2132        HANDLE_EXCEPTION();
2133    }
2134    ZEND_VM_JMP(opline);
2135}
2136
2137ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, ANY)
2138{
2139    USE_OPLINE
2140    zend_free_op free_op1;
2141    zval *val;
2142    int ret;
2143
2144    SAVE_OPLINE();
2145    val = GET_OP1_ZVAL_PTR(BP_VAR_R);
2146
2147    if (Z_TYPE_P(val) == IS_TRUE) {
2148        ZVAL_TRUE(EX_VAR(opline->result.var));
2149        ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
2150        ZEND_VM_CONTINUE();
2151    } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
2152        ZVAL_FALSE(EX_VAR(opline->result.var));
2153        if (OP1_TYPE == IS_CV) {
2154            ZEND_VM_NEXT_OPCODE();
2155        } else {
2156            ZEND_VM_SET_OPCODE(opline + 1);
2157            ZEND_VM_CONTINUE();
2158        }
2159    }
2160    ret = i_zend_is_true(val);
2161    FREE_OP1();
2162    if (ret) {
2163        ZVAL_TRUE(EX_VAR(opline->result.var));
2164        opline = OP_JMP_ADDR(opline, opline->op2);
2165    } else {
2166        ZVAL_FALSE(EX_VAR(opline->result.var));
2167        opline++;
2168    }
2169    if (UNEXPECTED(EG(exception) != NULL)) {
2170        HANDLE_EXCEPTION();
2171    }
2172    ZEND_VM_JMP(opline);
2173}
2174
2175ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY)
2176{
2177    USE_OPLINE
2178
2179    SAVE_OPLINE();
2180    zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
2181    CHECK_EXCEPTION();
2182    ZEND_VM_NEXT_OPCODE();
2183}
2184
2185ZEND_VM_HANDLER(127, ZEND_FE_FREE, TMPVAR, ANY)
2186{
2187    zval *var;
2188    USE_OPLINE
2189
2190    SAVE_OPLINE();
2191    var = EX_VAR(opline->op1.var);
2192    if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
2193        zend_hash_iterator_del(Z_FE_ITER_P(var));
2194    }
2195    zval_ptr_dtor_nogc(var);
2196    CHECK_EXCEPTION();
2197    ZEND_VM_NEXT_OPCODE();
2198}
2199
2200ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP|UNUSED, CONST)
2201{
2202    USE_OPLINE
2203    zval *str = EX_VAR(opline->result.var);
2204
2205    SAVE_OPLINE();
2206
2207    if (OP1_TYPE == IS_UNUSED) {
2208        /* Initialize for erealloc in add_char_to_string */
2209        ZVAL_EMPTY_STRING(str);
2210    }
2211
2212    add_char_to_string(str, str, EX_CONSTANT(opline->op2));
2213
2214    /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
2215    /*CHECK_EXCEPTION();*/
2216    ZEND_VM_NEXT_OPCODE();
2217}
2218
2219ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP|UNUSED, CONST)
2220{
2221    USE_OPLINE
2222    zval *str = EX_VAR(opline->result.var);
2223
2224    SAVE_OPLINE();
2225
2226    if (OP1_TYPE == IS_UNUSED) {
2227        /* Initialize for erealloc in add_string_to_string */
2228        ZVAL_EMPTY_STRING(str);
2229    }
2230
2231    add_string_to_string(str, str, EX_CONSTANT(opline->op2));
2232
2233    /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
2234    /*CHECK_EXCEPTION();*/
2235    ZEND_VM_NEXT_OPCODE();
2236}
2237
2238ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP|UNUSED, TMPVAR|CV)
2239{
2240    USE_OPLINE
2241    zend_free_op free_op2;
2242    zval *str = EX_VAR(opline->result.var);
2243    zval *var;
2244    zval var_copy;
2245    int use_copy = 0;
2246
2247    SAVE_OPLINE();
2248    var = GET_OP2_ZVAL_PTR(BP_VAR_R);
2249
2250    if (OP1_TYPE == IS_UNUSED) {
2251        /* Initialize for erealloc in add_string_to_string */
2252        ZVAL_EMPTY_STRING(str);
2253    }
2254
2255    if (Z_TYPE_P(var) != IS_STRING) {
2256        use_copy = zend_make_printable_zval(var, &var_copy);
2257
2258        if (use_copy) {
2259            var = &var_copy;
2260        }
2261    }
2262    add_string_to_string(str, str, var);
2263
2264    if (use_copy) {
2265        zend_string_release(Z_STR_P(var));
2266    }
2267    /* original comment, possibly problematic:
2268     * FREE_OP is missing intentionally here - we're always working on the same temporary variable
2269     * (Zeev):  I don't think it's problematic, we only use variables
2270     * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
2271     * string offsets or overloaded objects
2272     */
2273    FREE_OP2();
2274
2275    CHECK_EXCEPTION();
2276    ZEND_VM_NEXT_OPCODE();
2277}
2278
2279ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV)
2280{
2281    USE_OPLINE
2282
2283    SAVE_OPLINE();
2284    if (EG(exception)) {
2285        zend_exception_save();
2286    }
2287    if (OP2_TYPE == IS_UNUSED) {
2288        Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->extended_value);
2289        CHECK_EXCEPTION();
2290        ZEND_VM_NEXT_OPCODE();
2291    } else {
2292        zend_free_op free_op2;
2293        zval *class_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
2294
2295ZEND_VM_C_LABEL(try_class_name):
2296        if (OP2_TYPE == IS_CONST) {
2297            if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) {
2298                Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
2299            } else {
2300                Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value);
2301                CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var)));
2302            }
2303        } else if (Z_TYPE_P(class_name) == IS_OBJECT) {
2304            Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name);
2305        } else if (Z_TYPE_P(class_name) == IS_STRING) {
2306            Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->extended_value);
2307        } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) {
2308            class_name = Z_REFVAL_P(class_name);
2309            ZEND_VM_C_GOTO(try_class_name);
2310        } else {
2311            if (UNEXPECTED(EG(exception) != NULL)) {
2312                HANDLE_EXCEPTION();
2313            }
2314            zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
2315        }
2316
2317        FREE_OP2();
2318        CHECK_EXCEPTION();
2319        ZEND_VM_NEXT_OPCODE();
2320    }
2321}
2322
2323ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
2324{
2325    USE_OPLINE
2326    zval *function_name;
2327    zend_free_op free_op1, free_op2;
2328    zval *object;
2329    zend_function *fbc;
2330    zend_class_entry *called_scope;
2331    zend_object *obj;
2332
2333    SAVE_OPLINE();
2334
2335    function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
2336
2337    if (OP2_TYPE != IS_CONST && UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
2338        do {
2339            if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(function_name)) {
2340                function_name = Z_REFVAL_P(function_name);
2341                if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
2342                    break;
2343                }
2344            }
2345            if (UNEXPECTED(EG(exception) != NULL)) {
2346                HANDLE_EXCEPTION();
2347            }
2348            zend_error_noreturn(E_ERROR, "Method name must be a string");
2349        } while (0);
2350    }
2351
2352    object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
2353
2354    do {
2355        if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
2356            uint32_t nesting = 1;
2357
2358            if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
2359                object = Z_REFVAL_P(object);
2360                if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
2361                    break;
2362                }
2363            }
2364
2365            if (UNEXPECTED(EG(exception) != NULL)) {
2366                FREE_OP2();
2367                HANDLE_EXCEPTION();
2368            }
2369
2370            zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s",  Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
2371            FREE_OP2();
2372            FREE_OP1();
2373
2374            if (EG(exception) != NULL) {
2375                HANDLE_EXCEPTION();
2376            }
2377
2378            /* No exception raised: Skip over arguments until fcall opcode with correct
2379             * nesting level. Return NULL (except when return value unused) */
2380            do {
2381                opline++;
2382                if (opline->opcode == ZEND_INIT_FCALL ||
2383                    opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
2384                    opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
2385                    opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
2386                    opline->opcode == ZEND_INIT_METHOD_CALL ||
2387                    opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
2388                    opline->opcode == ZEND_INIT_USER_CALL ||
2389                    opline->opcode == ZEND_NEW
2390                ) {
2391                    nesting++;
2392                } else if (opline->opcode == ZEND_DO_FCALL ||
2393                           opline->opcode == ZEND_DO_ICALL ||
2394                           opline->opcode == ZEND_DO_UCALL ||
2395                           opline->opcode == ZEND_DO_FCALL_BY_NAME) {
2396                    nesting--;
2397                }
2398            } while (nesting);
2399
2400            if (RETURN_VALUE_USED(opline)) {
2401                ZVAL_NULL(EX_VAR(opline->result.var));
2402            }
2403
2404            /* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
2405            if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
2406                opline++;
2407            }
2408            ZEND_VM_JMP(++opline);
2409        }
2410    } while (0);
2411
2412    obj = Z_OBJ_P(object);
2413    called_scope = obj->ce;
2414
2415    if (OP2_TYPE != IS_CONST ||
2416        UNEXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
2417        zend_object *orig_obj = obj;
2418
2419        if (UNEXPECTED(obj->handlers->get_method == NULL)) {
2420            zend_error_noreturn(E_ERROR, "Object does not support method calls");
2421        }
2422
2423        /* First, locate the function. */
2424        fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
2425        if (UNEXPECTED(fbc == NULL)) {
2426            zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
2427        }
2428        if (OP2_TYPE == IS_CONST &&
2429            EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
2430            EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
2431            EXPECTED(obj == orig_obj)) {
2432            CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
2433        }
2434    }
2435
2436    if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
2437        obj = NULL;
2438    } else {
2439        GC_REFCOUNT(obj)++; /* For $this pointer */
2440    }
2441
2442    EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
2443        fbc, opline->extended_value, called_scope, obj, EX(call));
2444
2445    FREE_OP2();
2446    FREE_OP1();
2447
2448    CHECK_EXCEPTION();
2449    ZEND_VM_NEXT_OPCODE();
2450}
2451
2452ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSED|CV)
2453{
2454    USE_OPLINE
2455    zval *function_name;
2456    zend_class_entry *ce;
2457    zend_object *object;
2458    zend_function *fbc;
2459
2460    SAVE_OPLINE();
2461
2462    if (OP1_TYPE == IS_CONST) {
2463        /* no function found. try a static method in class */
2464        if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
2465            ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
2466        } else {
2467            ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
2468            if (UNEXPECTED(EG(exception) != NULL)) {
2469                HANDLE_EXCEPTION();
2470            }
2471            if (UNEXPECTED(ce == NULL)) {
2472                zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
2473            }
2474            CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
2475        }
2476    } else {
2477        ce = Z_CE_P(EX_VAR(opline->op1.var));
2478    }
2479
2480    if (OP1_TYPE == IS_CONST &&
2481        OP2_TYPE == IS_CONST &&
2482        CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
2483        fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
2484    } else if (OP1_TYPE != IS_CONST &&
2485               OP2_TYPE == IS_CONST &&
2486               (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
2487        /* do nothing */
2488    } else if (OP2_TYPE != IS_UNUSED) {
2489        zend_free_op free_op2;
2490
2491        function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
2492        if (OP2_TYPE != IS_CONST) {
2493            if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
2494                if (UNEXPECTED(EG(exception) != NULL)) {
2495                    HANDLE_EXCEPTION();
2496                }
2497                zend_error_noreturn(E_ERROR, "Function name must be a string");
2498            }
2499        }
2500
2501        if (ce->get_static_method) {
2502            fbc = ce->get_static_method(ce, Z_STR_P(function_name));
2503        } else {
2504            fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((OP2_TYPE == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
2505        }
2506        if (UNEXPECTED(fbc == NULL)) {
2507            zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
2508        }
2509        if (OP2_TYPE == IS_CONST &&
2510            EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
2511            EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
2512            if (OP1_TYPE == IS_CONST) {
2513                CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
2514            } else {
2515                CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
2516            }
2517        }
2518        if (OP2_TYPE != IS_CONST) {
2519            FREE_OP2();
2520        }
2521    } else {
2522        if (UNEXPECTED(ce->constructor == NULL)) {
2523            zend_error_noreturn(E_ERROR, "Cannot call constructor");
2524        }
2525        if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
2526            zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
2527        }
2528        fbc = ce->constructor;
2529    }
2530
2531    object = NULL;
2532    if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
2533        if (Z_OBJ(EX(This))) {
2534            object = Z_OBJ(EX(This));
2535            GC_REFCOUNT(object)++;
2536        }
2537        if (!object ||
2538            !instanceof_function(object->ce, ce)) {
2539            /* We are calling method of the other (incompatible) class,
2540               but passing $this. This is done for compatibility with php-4. */
2541            if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2542                zend_error(
2543                    object ? E_DEPRECATED : E_STRICT,
2544                    "Non-static method %s::%s() should not be called statically%s",
2545                    fbc->common.scope->name->val, fbc->common.function_name->val,
2546                    object ? ", assuming $this from incompatible context" : "");
2547            } else {
2548                /* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
2549                zend_error_noreturn(
2550                    E_ERROR,
2551                    "Non-static method %s::%s() cannot be called statically%s",
2552                    fbc->common.scope->name->val, fbc->common.function_name->val,
2553                    object ? ", assuming $this from incompatible context" : "");
2554            }
2555        }
2556    }
2557
2558    if (OP1_TYPE != IS_CONST) {
2559        /* previous opcode is ZEND_FETCH_CLASS */
2560        if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
2561            ce = EX(called_scope);
2562        }
2563    }
2564
2565    EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
2566        fbc, opline->extended_value, ce, object, EX(call));
2567
2568    if (OP2_TYPE == IS_UNUSED) {
2569        EX(call)->return_value = NULL;
2570    }
2571
2572    CHECK_EXCEPTION();
2573    ZEND_VM_NEXT_OPCODE();
2574}
2575
2576ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST)
2577{
2578    USE_OPLINE
2579    zend_function *fbc;
2580    zval *function_name, *func;
2581
2582    if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
2583        fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
2584    } else {
2585        function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
2586        if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
2587            SAVE_OPLINE();
2588            zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
2589        } else {
2590            fbc = Z_FUNC_P(func);
2591            CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
2592        }
2593    }
2594    EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
2595        fbc, opline->extended_value, NULL, NULL, EX(call));
2596
2597    /*CHECK_EXCEPTION();*/
2598    ZEND_VM_NEXT_OPCODE();
2599}
2600
2601ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV)
2602{
2603    USE_OPLINE
2604    zend_function *fbc;
2605    zval *function_name, *func;
2606    zend_string *lcname;
2607    zend_free_op free_op2;
2608    zend_class_entry *called_scope;
2609    zend_object *object;
2610
2611    SAVE_OPLINE();
2612    function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
2613
2614ZEND_VM_C_LABEL(try_function_name):
2615    if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
2616        if (Z_STRVAL_P(function_name)[0] == '\\') {
2617            lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
2618            zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
2619        } else {
2620            lcname = zend_string_tolower(Z_STR_P(function_name));
2621        }
2622        if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
2623            zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
2624        }
2625        zend_string_release(lcname);
2626        FREE_OP2();
2627
2628        fbc = Z_FUNC_P(func);
2629        called_scope = NULL;
2630        object = NULL;
2631    } else if (OP2_TYPE != IS_CONST &&
2632        EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
2633        Z_OBJ_HANDLER_P(function_name, get_closure) &&
2634        Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) {
2635        if (object) {
2636            GC_REFCOUNT(object)++;
2637        }
2638        if (OP2_TYPE == IS_VAR && (fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
2639            /* Delay closure destruction until its invocation */
2640            fbc->common.prototype = (zend_function*)Z_OBJ_P(free_op2);
2641        } else if (OP2_TYPE == IS_CV) {
2642            FREE_OP2();
2643        }
2644    } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
2645            zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
2646        zval *obj;
2647        zval *method;
2648        obj = zend_hash_index_find(Z_ARRVAL_P(function_name), 0);
2649        method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1);
2650
2651        if (!obj || !method) {
2652            zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
2653        }
2654
2655        ZVAL_DEREF(obj);
2656        if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
2657            zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
2658        }
2659
2660        ZVAL_DEREF(method);
2661        if (Z_TYPE_P(method) != IS_STRING) {
2662            zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
2663        }
2664
2665        if (Z_TYPE_P(obj) == IS_STRING) {
2666            object = NULL;
2667            called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0);
2668            if (UNEXPECTED(called_scope == NULL)) {
2669                CHECK_EXCEPTION();
2670                ZEND_VM_NEXT_OPCODE();
2671            }
2672
2673            if (called_scope->get_static_method) {
2674                fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
2675            } else {
2676                fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
2677            }
2678            if (UNEXPECTED(fbc == NULL)) {
2679                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
2680            }
2681            if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
2682                if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2683                    zend_error(E_STRICT,
2684                        "Non-static method %s::%s() should not be called statically",
2685                        fbc->common.scope->name->val, fbc->common.function_name->val);
2686                } else {
2687                    zend_error_noreturn(
2688                        E_ERROR,
2689                        "Non-static method %s::%s() cannot be called statically",
2690                        fbc->common.scope->name->val, fbc->common.function_name->val);
2691                }
2692            }
2693        } else {
2694            called_scope = Z_OBJCE_P(obj);
2695            object = Z_OBJ_P(obj);
2696
2697            fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
2698            if (UNEXPECTED(fbc == NULL)) {
2699                zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method));
2700            }
2701
2702            if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
2703                object = NULL;
2704            } else {
2705                GC_REFCOUNT(object)++; /* For $this pointer */
2706            }
2707        }
2708        FREE_OP2();
2709    } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
2710        function_name = Z_REFVAL_P(function_name);
2711        ZEND_VM_C_GOTO(try_function_name);
2712    } else {
2713        if (UNEXPECTED(EG(exception) != NULL)) {
2714            HANDLE_EXCEPTION();
2715        }
2716        zend_error_noreturn(E_ERROR, "Function name must be a string");
2717        ZEND_VM_CONTINUE(); /* Never reached */
2718    }
2719    EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
2720        fbc, opline->extended_value, called_scope, object, EX(call));
2721
2722    CHECK_EXCEPTION();
2723    ZEND_VM_NEXT_OPCODE();
2724}
2725
2726ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
2727{
2728    USE_OPLINE
2729    zend_free_op free_op2;
2730    zval *function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
2731    zend_fcall_info_cache fcc;
2732    char *error = NULL;
2733    zend_function *func;
2734    zend_class_entry *called_scope;
2735    zend_object *object;
2736
2737    if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
2738        if (error) {
2739            efree(error);
2740        }
2741        func = fcc.function_handler;
2742        if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
2743            /* Delay closure destruction until its invocation */
2744            func->common.prototype = (zend_function*)Z_OBJ_P(function_name);
2745            Z_ADDREF_P(function_name);
2746        }
2747        called_scope = fcc.called_scope;
2748        object = fcc.object;
2749        if (object) {
2750            GC_REFCOUNT(object)++; /* For $this pointer */
2751        } else if (func->common.scope &&
2752                   !(func->common.fn_flags & ZEND_ACC_STATIC)) {
2753            if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2754                zend_error(E_STRICT,
2755                "Non-static method %s::%s() should not be called statically",
2756                func->common.scope->name->val, func->common.function_name->val);
2757            } else {
2758                zend_error_noreturn(
2759                    E_ERROR,
2760                    "Non-static method %s::%s() cannot be called statically",
2761                    func->common.scope->name->val, func->common.function_name->val);
2762            }
2763        }
2764    } else {
2765        zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
2766        efree(error);
2767        func = (zend_function*)&zend_pass_function;
2768        called_scope = NULL;
2769        object = NULL;
2770    }
2771
2772    EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
2773        func, opline->extended_value, called_scope, object, EX(call));
2774
2775    FREE_OP2();
2776    CHECK_EXCEPTION();
2777    ZEND_VM_NEXT_OPCODE();
2778}
2779
2780ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
2781{
2782    USE_OPLINE
2783    zval *func_name;
2784    zval *func;
2785    zend_function *fbc;
2786
2787    func_name = EX_CONSTANT(opline->op2) + 1;
2788    if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
2789        fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
2790    } else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
2791        func_name++;
2792        if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
2793            SAVE_OPLINE();
2794            zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
2795        } else {
2796            fbc = Z_FUNC_P(func);
2797            CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
2798        }
2799    } else {
2800        fbc = Z_FUNC_P(func);
2801        CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
2802    }
2803
2804    EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
2805        fbc, opline->extended_value, NULL, NULL, EX(call));
2806
2807    ZEND_VM_NEXT_OPCODE();
2808}
2809
2810ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
2811{
2812    USE_OPLINE
2813    zend_free_op free_op2;
2814    zval *fname = GET_OP2_ZVAL_PTR(BP_VAR_R);
2815    zval *func;
2816    zend_function *fbc;
2817
2818    if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
2819        fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
2820    } else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
2821        SAVE_OPLINE();
2822        zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
2823    } else {
2824        fbc = Z_FUNC_P(func);
2825        CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
2826    }
2827
2828    EX(call) = zend_vm_stack_push_call_frame_ex(
2829        opline->op1.num, ZEND_CALL_NESTED_FUNCTION,
2830        fbc, opline->extended_value, NULL, NULL, EX(call));
2831
2832    FREE_OP2();
2833
2834    ZEND_VM_NEXT_OPCODE();
2835}
2836
2837ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY)
2838{
2839    USE_OPLINE
2840    zend_execute_data *call = EX(call);
2841    zend_function *fbc = call->func;
2842    zval *ret;
2843
2844    SAVE_OPLINE();
2845    EX(call) = call->prev_execute_data;
2846
2847    LOAD_OPLINE();
2848
2849    call->called_scope = EX(called_scope);
2850    Z_OBJ(call->This) = Z_OBJ(EX(This));
2851
2852    call->prev_execute_data = execute_data;
2853    EG(current_execute_data) = call;
2854
2855    ret = EX_VAR(opline->result.var);
2856    ZVAL_NULL(ret);
2857    Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
2858
2859    fbc->internal_function.handler(call, ret);
2860
2861    ZEND_ASSERT(
2862        !call->func ||
2863        !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
2864        zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
2865
2866    EG(current_execute_data) = call->prev_execute_data;
2867    zend_vm_stack_free_args(call);
2868    zend_vm_stack_free_call_frame(call);
2869
2870    if (!RETURN_VALUE_USED(opline)) {
2871        zval_ptr_dtor(EX_VAR(opline->result.var));
2872    }
2873
2874    if (UNEXPECTED(EG(exception) != NULL)) {
2875        zend_throw_exception_internal(NULL);
2876        if (RETURN_VALUE_USED(opline)) {
2877            zval_ptr_dtor(EX_VAR(opline->result.var));
2878        }
2879        HANDLE_EXCEPTION();
2880    }
2881
2882    ZEND_VM_NEXT_OPCODE();
2883}
2884
2885ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY)
2886{
2887    USE_OPLINE
2888    zend_execute_data *call = EX(call);
2889    zend_function *fbc = call->func;
2890    zval *ret;
2891
2892    SAVE_OPLINE();
2893    EX(call) = call->prev_execute_data;
2894
2895    LOAD_OPLINE();
2896
2897    EG(scope) = NULL;
2898    ret = NULL;
2899    call->symbol_table = NULL;
2900    if (RETURN_VALUE_USED(opline)) {
2901        ret = EX_VAR(opline->result.var);
2902        ZVAL_NULL(ret);
2903        Z_VAR_FLAGS_P(ret) = 0;
2904    }
2905
2906    call->prev_execute_data = execute_data;
2907    i_init_func_execute_data(call, &fbc->op_array, ret, 0);
2908
2909    ZEND_VM_ENTER();
2910}
2911
2912ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
2913{
2914    USE_OPLINE
2915    zend_execute_data *call = EX(call);
2916    zend_function *fbc = call->func;
2917    zval *ret;
2918
2919    SAVE_OPLINE();
2920    EX(call) = call->prev_execute_data;
2921
2922    LOAD_OPLINE();
2923
2924    if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
2925        EG(scope) = NULL;
2926        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
2927            if (RETURN_VALUE_USED(opline)) {
2928                zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var));
2929            } else {
2930                zend_vm_stack_free_args(call);
2931            }
2932
2933            zend_vm_stack_free_call_frame(call);
2934        } else {
2935            ret = NULL;
2936            call->symbol_table = NULL;
2937            if (RETURN_VALUE_USED(opline)) {
2938                ret = EX_VAR(opline->result.var);
2939                ZVAL_NULL(ret);
2940                Z_VAR_FLAGS_P(ret) = 0;
2941            }
2942
2943            call->prev_execute_data = execute_data;
2944            i_init_func_execute_data(call, &fbc->op_array, ret, 0);
2945
2946            ZEND_VM_ENTER();
2947        }
2948        EG(scope) = EX(func)->op_array.scope;
2949    } else {
2950        ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
2951
2952        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
2953            zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
2954                fbc->common.scope ? fbc->common.scope->name->val : "",
2955                fbc->common.scope ? "::" : "",
2956                fbc->common.function_name->val);
2957            if (UNEXPECTED(EG(exception) != NULL)) {
2958                HANDLE_EXCEPTION();
2959            }
2960        }
2961
2962        call->called_scope = EX(called_scope);
2963        Z_OBJ(call->This) = Z_OBJ(EX(This));
2964
2965        call->prev_execute_data = execute_data;
2966        EG(current_execute_data) = call;
2967
2968        if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
2969            uint32_t i;
2970            uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
2971            zval *p = ZEND_CALL_ARG(call, 1);
2972
2973            for (i = 0; i < num_args; ++i) {
2974                zend_verify_internal_arg_type(fbc, i + 1, p);
2975                p++;
2976            }
2977            if (UNEXPECTED(EG(exception) != NULL)) {
2978                EG(current_execute_data) = call->prev_execute_data;
2979                zend_vm_stack_free_args(call);
2980                zend_vm_stack_free_call_frame(call);
2981                zend_throw_exception_internal(NULL);
2982                HANDLE_EXCEPTION();
2983            }
2984        }
2985
2986        ret = EX_VAR(opline->result.var);
2987        ZVAL_NULL(ret);
2988        Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
2989
2990        fbc->internal_function.handler(call, ret);
2991
2992        ZEND_ASSERT(
2993            !call->func ||
2994            !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
2995            zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
2996
2997        EG(current_execute_data) = call->prev_execute_data;
2998        zend_vm_stack_free_args(call);
2999        zend_vm_stack_free_call_frame(call);
3000
3001        if (!RETURN_VALUE_USED(opline)) {
3002            zval_ptr_dtor(EX_VAR(opline->result.var));
3003        }
3004    }
3005
3006    if (UNEXPECTED(EG(exception) != NULL)) {
3007        zend_throw_exception_internal(NULL);
3008        if (RETURN_VALUE_USED(opline)) {
3009            zval_ptr_dtor(EX_VAR(opline->result.var));
3010        }
3011        HANDLE_EXCEPTION();
3012    }
3013    ZEND_VM_NEXT_OPCODE();
3014}
3015
3016ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
3017{
3018    USE_OPLINE
3019    zend_execute_data *call = EX(call);
3020    zend_function *fbc = call->func;
3021    zend_object *object = Z_OBJ(call->This);
3022    zval *ret;
3023
3024    SAVE_OPLINE();
3025    EX(call) = call->prev_execute_data;
3026    if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
3027        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
3028            zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
3029        }
3030        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
3031            zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
3032                fbc->common.scope ? fbc->common.scope->name->val : "",
3033                fbc->common.scope ? "::" : "",
3034                fbc->common.function_name->val);
3035            if (UNEXPECTED(EG(exception) != NULL)) {
3036                HANDLE_EXCEPTION();
3037            }
3038        }
3039    }
3040
3041    LOAD_OPLINE();
3042
3043    if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
3044        EG(scope) = fbc->common.scope;
3045        if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
3046            if (RETURN_VALUE_USED(opline)) {
3047                zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var));
3048            } else {
3049                zend_vm_stack_free_args(call);
3050            }
3051
3052            zend_vm_stack_free_call_frame(call);
3053        } else {
3054            ret = NULL;
3055            call->symbol_table = NULL;
3056            if (RETURN_VALUE_USED(opline)) {
3057                ret = EX_VAR(opline->result.var);
3058                ZVAL_NULL(ret);
3059                Z_VAR_FLAGS_P(ret) = 0;
3060            }
3061
3062            call->prev_execute_data = execute_data;
3063            i_init_func_execute_data(call, &fbc->op_array, ret, 1);
3064
3065            if (EXPECTED(zend_execute_ex == execute_ex)) {
3066                ZEND_VM_ENTER();
3067            } else {
3068                ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
3069                zend_execute_ex(call);
3070            }
3071        }
3072    } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) {
3073        int should_change_scope = 0;
3074
3075        if (fbc->common.scope) {
3076            should_change_scope = 1;
3077            /* TODO: we don't set scope if we call an object method ??? */
3078            /* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
3079#if 1
3080            EG(scope) = object ? NULL : fbc->common.scope;
3081#else
3082            EG(scope) = fbc->common.scope;
3083#endif
3084        } else {
3085            call->called_scope = EX(called_scope);
3086            Z_OBJ(call->This) = Z_OBJ(EX(This));
3087        }
3088
3089        call->prev_execute_data = execute_data;
3090        EG(current_execute_data) = call;
3091
3092        if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
3093            uint32_t i;
3094            uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
3095            zval *p = ZEND_CALL_ARG(call, 1);
3096
3097            for (i = 0; i < num_args; ++i) {
3098                zend_verify_internal_arg_type(fbc, i + 1, p);
3099                p++;
3100            }
3101            if (UNEXPECTED(EG(exception) != NULL)) {
3102                EG(current_execute_data) = call->prev_execute_data;
3103                zend_vm_stack_free_args(call);
3104                zend_vm_stack_free_call_frame(call);
3105                if (RETURN_VALUE_USED(opline)) {
3106                    ZVAL_UNDEF(EX_VAR(opline->result.var));
3107                }
3108                if (UNEXPECTED(should_change_scope)) {
3109                    ZEND_VM_C_GOTO(fcall_end_change_scope);
3110                } else {
3111                    ZEND_VM_C_GOTO(fcall_end);
3112                }
3113            }
3114        }
3115
3116        ret = EX_VAR(opline->result.var);
3117        ZVAL_NULL(ret);
3118        Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
3119
3120        if (!zend_execute_internal) {
3121            /* saves one function call if zend_execute_internal is not used */
3122            fbc->internal_function.handler(call, ret);
3123        } else {
3124            zend_execute_internal(call, ret);
3125        }
3126
3127        ZEND_ASSERT(
3128            !call->func ||
3129            !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
3130            zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
3131
3132        EG(current_execute_data) = call->prev_execute_data;
3133        zend_vm_stack_free_args(call);
3134        zend_vm_stack_free_call_frame(call);
3135
3136        if (!RETURN_VALUE_USED(opline)) {
3137            zval_ptr_dtor(EX_VAR(opline->result.var));
3138        }
3139
3140        if (UNEXPECTED(should_change_scope)) {
3141            ZEND_VM_C_GOTO(fcall_end_change_scope);
3142        } else {
3143            ZEND_VM_C_GOTO(fcall_end);
3144        }
3145    } else { /* ZEND_OVERLOADED_FUNCTION */
3146        EG(scope) = fbc->common.scope;
3147
3148        ZVAL_NULL(EX_VAR(opline->result.var));
3149
3150        /* Not sure what should be done here if it's a static method */
3151        if (EXPECTED(object != NULL)) {
3152            call->prev_execute_data = execute_data;
3153            EG(current_execute_data) = call;
3154            object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var));
3155            EG(current_execute_data) = call->prev_execute_data;
3156        } else {
3157            zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
3158        }
3159
3160        zend_vm_stack_free_args(call);
3161
3162        zend_vm_stack_free_call_frame(call);
3163
3164        if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
3165            zend_string_release(fbc->common.function_name);
3166        }
3167        efree(fbc);
3168
3169        if (!RETURN_VALUE_USED(opline)) {
3170            zval_ptr_dtor(EX_VAR(opline->result.var));
3171        } else {
3172//???           Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
3173//???           Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
3174            Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0;
3175        }
3176    }
3177
3178ZEND_VM_C_LABEL(fcall_end_change_scope):
3179    if (object) {
3180        if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
3181            if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
3182                GC_REFCOUNT(object)--;
3183            }
3184            if (GC_REFCOUNT(object) == 1) {
3185                zend_object_store_ctor_failed(object);
3186            }
3187        }
3188        OBJ_RELEASE(object);
3189    }
3190    EG(scope) = EX(func)->op_array.scope;
3191
3192ZEND_VM_C_LABEL(fcall_end):
3193    if (UNEXPECTED(EG(exception) != NULL)) {
3194        zend_throw_exception_internal(NULL);
3195        if (RETURN_VALUE_USED(opline)) {
3196            zval_ptr_dtor(EX_VAR(opline->result.var));
3197        }
3198        HANDLE_EXCEPTION();
3199    }
3200
3201    ZEND_VM_NEXT_OPCODE();
3202}
3203
3204ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
3205{
3206#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
3207    USE_OPLINE
3208#endif
3209    SAVE_OPLINE();
3210    if (OP1_TYPE == IS_UNUSED) {
3211        zend_verify_missing_return_type(EX(func));
3212    } else {
3213        zval *retval_ptr;
3214        zend_free_op free_op1;
3215
3216        retval_ptr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
3217        zend_verify_return_type(EX(func), retval_ptr);
3218    }
3219    CHECK_EXCEPTION();
3220    ZEND_VM_NEXT_OPCODE();
3221}
3222
3223ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
3224{
3225    USE_OPLINE
3226    zval *retval_ptr;
3227    zend_free_op free_op1;
3228
3229    SAVE_OPLINE();
3230    retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
3231
3232    if (!EX(return_value)) {
3233        FREE_OP1();
3234    } else {
3235        if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
3236            ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
3237            if (OP1_TYPE == IS_CONST) {
3238                if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
3239                    zval_copy_ctor_func(EX(return_value));
3240                }
3241            }
3242        } else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_ISREF_P(retval_ptr)) {
3243            ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
3244            FREE_OP1_IF_VAR();
3245        } else {
3246            ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
3247            if (OP1_TYPE == IS_CV) {
3248                if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
3249            }
3250        }
3251    }
3252    ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
3253}
3254
3255ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
3256{
3257    USE_OPLINE
3258    zval *retval_ptr;
3259    zend_free_op free_op1;
3260
3261    SAVE_OPLINE();
3262
3263    do {
3264        if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR ||
3265            (OP1_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) {
3266            /* Not supposed to happen, but we'll allow it */
3267            zend_error(E_NOTICE, "Only variable references should be returned by reference");
3268
3269            retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
3270            if (!EX(return_value)) {
3271                if (OP1_TYPE == IS_TMP_VAR) {
3272                    FREE_OP1();
3273                }
3274            } else {
3275                ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
3276                Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
3277                if (OP1_TYPE != IS_TMP_VAR) {
3278                    zval_opt_copy_ctor_no_imm(EX(return_value));
3279                }
3280            }
3281            break;
3282        }
3283
3284        retval_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
3285
3286        if (OP1_TYPE == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
3287            zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
3288        }
3289
3290        if (OP1_TYPE == IS_VAR) {
3291            if (retval_ptr == &EG(uninitialized_zval) ||
3292                (opline->extended_value == ZEND_RETURNS_FUNCTION &&
3293                 !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) {
3294                zend_error(E_NOTICE, "Only variable references should be returned by reference");
3295                if (EX(return_value)) {
3296                    ZVAL_NEW_REF(EX(return_value), retval_ptr);
3297                    Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
3298                    if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
3299                }
3300                break;
3301            }
3302        }
3303
3304        if (EX(return_value)) {
3305            ZVAL_MAKE_REF(retval_ptr);
3306            Z_ADDREF_P(retval_ptr);
3307            ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
3308            Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
3309        }
3310    } while (0);
3311
3312    FREE_OP1_VAR_PTR();
3313    ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
3314}
3315
3316ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY)
3317{
3318    /* The generator object is stored in EX(return_value) */
3319    zend_generator *generator = (zend_generator *) EX(return_value);
3320
3321    /* Close the generator to free up resources */
3322    zend_generator_close(generator, 1);
3323
3324    /* Pass execution back to handling code */
3325    ZEND_VM_RETURN();
3326}
3327
3328ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
3329{
3330    USE_OPLINE
3331    zval *value;
3332    zend_free_op free_op1;
3333
3334    SAVE_OPLINE();
3335    value = GET_OP1_ZVAL_PTR(BP_VAR_R);
3336
3337    do {
3338        if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
3339            if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
3340                value = Z_REFVAL_P(value);
3341                if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
3342                    break;
3343                }
3344            }
3345            if (UNEXPECTED(EG(exception) != NULL)) {
3346                HANDLE_EXCEPTION();
3347            }
3348            zend_error_noreturn(E_ERROR, "Can only throw objects");
3349        }
3350    } while (0);
3351
3352    zend_exception_save();
3353    if (OP1_TYPE != IS_TMP_VAR) {
3354        if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
3355    }
3356
3357    zend_throw_exception_object(value);
3358    zend_exception_restore();
3359    FREE_OP1_IF_VAR();
3360    HANDLE_EXCEPTION();
3361}
3362
3363ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
3364{
3365    USE_OPLINE
3366    zend_class_entry *ce, *catch_ce;
3367    zend_object *exception;
3368
3369    SAVE_OPLINE();
3370    /* Check whether an exception has been thrown, if not, jump over code */
3371    zend_exception_restore();
3372    if (EG(exception) == NULL) {
3373        ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
3374        ZEND_VM_CONTINUE(); /* CHECK_ME */
3375    }
3376    if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
3377        catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
3378    } else {
3379        catch_ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
3380
3381        CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), catch_ce);
3382    }
3383    ce = EG(exception)->ce;
3384
3385#ifdef HAVE_DTRACE
3386    if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
3387        DTRACE_EXCEPTION_CAUGHT((char *)ce->name);
3388    }
3389#endif /* HAVE_DTRACE */
3390
3391    if (ce != catch_ce) {
3392        if (!catch_ce || !instanceof_function(ce, catch_ce)) {
3393            if (opline->result.num) {
3394                zend_throw_exception_internal(NULL);
3395                HANDLE_EXCEPTION();
3396            }
3397            ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
3398            ZEND_VM_CONTINUE(); /* CHECK_ME */
3399        }
3400    }
3401
3402    exception = EG(exception);
3403    zval_ptr_dtor(EX_VAR(opline->op2.var));
3404    ZVAL_OBJ(EX_VAR(opline->op2.var), EG(exception));
3405    if (UNEXPECTED(EG(exception) != exception)) {
3406        GC_REFCOUNT(EG(exception))++;
3407        HANDLE_EXCEPTION();
3408    } else {
3409        EG(exception) = NULL;
3410        ZEND_VM_NEXT_OPCODE();
3411    }
3412}
3413
3414ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
3415{
3416    USE_OPLINE
3417    zval *value, *arg;
3418    zend_free_op free_op1;
3419
3420    SAVE_OPLINE();
3421    value = GET_OP1_ZVAL_PTR(BP_VAR_R);
3422    arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3423    ZVAL_COPY_VALUE(arg, value);
3424    if (OP1_TYPE == IS_CONST) {
3425        if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
3426            zval_copy_ctor_func(arg);
3427        }
3428    }
3429    ZEND_VM_NEXT_OPCODE();
3430}
3431
3432ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, ANY)
3433{
3434    USE_OPLINE
3435    zval *value, *arg;
3436    zend_free_op free_op1;
3437
3438    SAVE_OPLINE();
3439    if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
3440        zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
3441    }
3442    value = GET_OP1_ZVAL_PTR(BP_VAR_R);
3443    arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3444    ZVAL_COPY_VALUE(arg, value);
3445    if (OP1_TYPE == IS_CONST) {
3446        if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
3447            zval_copy_ctor_func(arg);
3448        }
3449    }
3450    ZEND_VM_NEXT_OPCODE();
3451}
3452
3453ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, ANY)
3454{
3455    USE_OPLINE
3456    zval *varptr, *arg;
3457    zend_free_op free_op1;
3458
3459    varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
3460    arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3461    if (Z_ISREF_P(varptr)) {
3462        ZVAL_COPY(arg, Z_REFVAL_P(varptr));
3463        FREE_OP1();
3464    } else {
3465        ZVAL_COPY_VALUE(arg, varptr);
3466        if (OP1_TYPE == IS_CV) {
3467            if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
3468        }
3469    }
3470    ZEND_VM_NEXT_OPCODE();
3471}
3472
3473ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR|CV, ANY)
3474{
3475    USE_OPLINE
3476    zend_free_op free_op1;
3477    zval *varptr, *arg;
3478
3479    SAVE_OPLINE();
3480
3481    if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) {
3482        if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
3483            ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_VAR);
3484        }
3485    }
3486
3487    varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
3488    if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
3489         (Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) &&
3490        (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) {
3491
3492        ZVAL_MAKE_REF(varptr);
3493        if (OP1_TYPE == IS_CV) {
3494            Z_ADDREF_P(varptr);
3495        }
3496    } else {
3497        if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
3498            !(opline->extended_value & ZEND_ARG_SEND_SILENT) :
3499            !ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
3500            zend_error(E_STRICT, "Only variables should be passed by reference");
3501        }
3502    }
3503
3504    arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3505    ZVAL_COPY_VALUE(arg, varptr);
3506
3507    CHECK_EXCEPTION();
3508    ZEND_VM_NEXT_OPCODE();
3509}
3510
3511ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
3512{
3513    USE_OPLINE
3514    zend_free_op free_op1;
3515    zval *varptr, *arg;
3516
3517    SAVE_OPLINE();
3518    varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
3519
3520    if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == NULL)) {
3521        zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
3522    }
3523
3524    arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3525    if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
3526        ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
3527        ZEND_VM_NEXT_OPCODE();
3528    }
3529
3530    if (Z_ISREF_P(varptr)) {
3531        Z_ADDREF_P(varptr);
3532        ZVAL_COPY_VALUE(arg, varptr);
3533    } else if (OP1_TYPE == IS_VAR &&
3534        UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
3535        ZVAL_NEW_REF(arg, varptr);
3536    } else {
3537        ZVAL_NEW_REF(arg, varptr);
3538        Z_ADDREF_P(arg);
3539        ZVAL_REF(varptr, Z_REF_P(arg));
3540    }
3541
3542    FREE_OP1_VAR_PTR();
3543    ZEND_VM_NEXT_OPCODE();
3544}
3545
3546ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, ANY)
3547{
3548    USE_OPLINE
3549    zval *varptr, *arg;
3550    zend_free_op free_op1;
3551
3552    if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
3553        ZEND_VM_DISPATCH_TO_HANDLER(ZEND_SEND_REF);
3554    }
3555    varptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
3556    arg = ZEND_CALL_VAR(EX(call), opline->result.var);
3557    if (Z_ISREF_P(varptr)) {
3558        ZVAL_COPY(arg, Z_REFVAL_P(varptr));
3559        FREE_OP1();
3560    } else {
3561        ZVAL_COPY_VALUE(arg, varptr);
3562        if (OP1_TYPE == IS_CV) {
3563            if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
3564        }
3565    }
3566    ZEND_VM_NEXT_OPCODE();
3567}
3568
3569ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
3570{
3571    USE_OPLINE
3572    zend_free_op free_op1;
3573    zval *args;
3574    int arg_num;
3575    SAVE_OPLINE();
3576
3577    args = GET_OP1_ZVAL_PTR(BP_VAR_R);
3578    arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1;
3579
3580ZEND_VM_C_LABEL(send_again):
3581    switch (Z_TYPE_P(args)) {
3582        case IS_ARRAY: {
3583            HashTable *ht = Z_ARRVAL_P(args);
3584            zval *arg, *top;
3585            zend_string *name;
3586
3587            zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
3588
3589            if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
3590                uint32_t i;
3591                int separate = 0;
3592
3593                /* check if any of arguments are going to be passed by reference */
3594                for (i = 0; i < zend_hash_num_elements(ht); i++) {
3595                    if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
3596                        separate = 1;
3597                        break;
3598                    }
3599                }
3600                if (separate) {
3601                    zval_copy_ctor(args);
3602                    ht = Z_ARRVAL_P(args);
3603                }
3604            }
3605
3606            ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
3607                if (name) {
3608                    zend_error(E_RECOVERABLE_ERROR, "Cannot unpack array with string keys");
3609                    FREE_OP1();
3610                    CHECK_EXCEPTION();
3611                    ZEND_VM_NEXT_OPCODE();
3612                }
3613
3614                top = ZEND_CALL_ARG(EX(call), arg_num);
3615                if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
3616                    if (!Z_IMMUTABLE_P(args)) {
3617                        ZVAL_MAKE_REF(arg);
3618                        Z_ADDREF_P(arg);
3619                        ZVAL_REF(top, Z_REF_P(arg));
3620                    } else {
3621                        ZVAL_DUP(top, arg);
3622                    }
3623                } else if (Z_ISREF_P(arg)) {
3624                    ZVAL_COPY(top, Z_REFVAL_P(arg));
3625                } else {
3626                    ZVAL_COPY(top, arg);
3627                }
3628
3629                ZEND_CALL_NUM_ARGS(EX(call))++;
3630                arg_num++;
3631            } ZEND_HASH_FOREACH_END();
3632
3633            break;
3634        }
3635        case IS_OBJECT: {
3636            zend_class_entry *ce = Z_OBJCE_P(args);
3637            zend_object_iterator *iter;
3638
3639            if (!ce || !ce->get_iterator) {
3640                zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
3641                break;
3642            }
3643
3644            iter = ce->get_iterator(ce, args, 0);
3645            if (UNEXPECTED(!iter)) {
3646                FREE_OP1();
3647                if (!EG(exception)) {
3648                    zend_throw_exception_ex(
3649                        NULL, 0, "Object of type %s did not create an Iterator", ce->name->val
3650                    );
3651                }
3652                HANDLE_EXCEPTION();
3653            }
3654
3655            if (iter->funcs->rewind) {
3656                iter->funcs->rewind(iter);
3657                if (UNEXPECTED(EG(exception) != NULL)) {
3658                    ZEND_VM_C_GOTO(unpack_iter_dtor);
3659                }
3660            }
3661
3662            for (; iter->funcs->valid(iter) == SUCCESS; ++arg_num) {
3663                zval *arg, *top;
3664
3665                if (UNEXPECTED(EG(exception) != NULL)) {
3666                    ZEND_VM_C_GOTO(unpack_iter_dtor);
3667                }
3668
3669                arg = iter->funcs->get_current_data(iter);
3670                if (UNEXPECTED(EG(exception) != NULL)) {
3671                    ZEND_VM_C_GOTO(unpack_iter_dtor);
3672                }
3673
3674                if (iter->funcs->get_current_key) {
3675                    zval key;
3676                    iter->funcs->get_current_key(iter, &key);
3677                    if (UNEXPECTED(EG(exception) != NULL)) {
3678                        ZEND_VM_C_GOTO(unpack_iter_dtor);
3679                    }
3680
3681                    if (Z_TYPE(key) == IS_STRING) {
3682                        zend_error(E_RECOVERABLE_ERROR,
3683                            "Cannot unpack Traversable with string keys");
3684                        zend_string_release(Z_STR(key));
3685                        ZEND_VM_C_GOTO(unpack_iter_dtor);
3686                    }
3687
3688                    zval_dtor(&key);
3689                }
3690
3691                if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
3692                    zend_error(
3693                        E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
3694                        " by unpacking a Traversable, passing by-value instead", arg_num,
3695                        EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
3696                        EX(call)->func->common.scope ? "::" : "",
3697                        EX(call)->func->common.function_name->val
3698                    );
3699                }
3700
3701                if (Z_ISREF_P(arg)) {
3702                    ZVAL_DUP(arg, Z_REFVAL_P(arg));
3703                } else {
3704                    if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
3705                }
3706
3707                zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1);
3708                top = ZEND_CALL_ARG(EX(call), arg_num);
3709                ZVAL_COPY_VALUE(top, arg);
3710                ZEND_CALL_NUM_ARGS(EX(call))++;
3711
3712                iter->funcs->move_forward(iter);
3713                if (UNEXPECTED(EG(exception) != NULL)) {
3714                    ZEND_VM_C_GOTO(unpack_iter_dtor);
3715                }
3716            }
3717
3718ZEND_VM_C_LABEL(unpack_iter_dtor):
3719            zend_iterator_dtor(iter);
3720            break;
3721        }
3722        case IS_REFERENCE:
3723            args = Z_REFVAL_P(args);
3724            ZEND_VM_C_GOTO(send_again);
3725            break;
3726        default:
3727            zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
3728    }
3729
3730    FREE_OP1();
3731    CHECK_EXCEPTION();
3732    ZEND_VM_NEXT_OPCODE();
3733}
3734
3735ZEND_VM_HANDLER(119, ZEND_SEND_ARRAY, ANY, ANY)
3736{
3737    USE_OPLINE
3738    zend_free_op free_op1;
3739    zval *args;
3740    SAVE_OPLINE();
3741
3742    args = GET_OP1_ZVAL_PTR(BP_VAR_R);
3743
3744    if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) {
3745        if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(args)) {
3746            args = Z_REFVAL_P(args);
3747            if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
3748                ZEND_VM_C_GOTO(send_array);
3749            }
3750        }
3751        zend_error(E_WARNING, "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
3752        if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
3753            OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
3754        }
3755        if (Z_OBJ(EX(call)->This)) {
3756            OBJ_RELEASE(Z_OBJ(EX(call)->This));
3757        }
3758        EX(call)->func = (zend_function*)&zend_pass_function;
3759        EX(call)->called_scope = NULL;
3760        Z_OBJ(EX(call)->This) = NULL;
3761    } else {
3762        uint32_t arg_num;
3763        HashTable *ht;
3764        zval *arg, *param, tmp;
3765
3766ZEND_VM_C_LABEL(send_array):
3767        ht = Z_ARRVAL_P(args);
3768        zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht));
3769
3770        if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
3771            int separate = 0;
3772
3773            /* check if any of arguments are going to be passed by reference */
3774            for (arg_num = 0; arg_num < zend_hash_num_elements(ht); arg_num++) {
3775                if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + 1)) {
3776                    separate = 1;
3777                    break;
3778                }
3779            }
3780            if (separate) {
3781                zval_copy_ctor(args);
3782                ht = Z_ARRVAL_P(args);
3783            }
3784        }
3785
3786        arg_num = 1;
3787        param = ZEND_CALL_ARG(EX(call), 1);
3788        ZEND_HASH_FOREACH_VAL(ht, arg) {
3789            if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
3790                // TODO: Scalar values don't have reference counters anymore.
3791                // They are assumed to be 1, and they may be easily passed by
3792                // reference now. However, previously scalars with refcount==1
3793                // might be passed and with refcount>1 might not. We can support
3794                // only single behavior ???
3795#if 0
3796                if (Z_REFCOUNTED_P(arg) &&
3797                    // This solution breaks the following test (omit warning message) ???
3798                    // Zend/tests/bug61273.phpt
3799                    // ext/reflection/tests/bug42976.phpt
3800                    // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
3801#else
3802                if (!Z_REFCOUNTED_P(arg) ||
3803                    // This solution breaks the following test (emit warning message) ???
3804                    // ext/pdo_sqlite/tests/pdo_005.phpt
3805#endif
3806                    (!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
3807
3808                    if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
3809
3810                        zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
3811                            arg_num,
3812                            EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
3813                            EX(call)->func->common.scope ? "::" : "",
3814                            EX(call)->func->common.function_name->val);
3815
3816                        if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
3817                            OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
3818                        }
3819                        if (Z_OBJ(EX(call)->This)) {
3820                            OBJ_RELEASE(Z_OBJ(EX(call)->This));
3821                        }
3822                        EX(call)->func = (zend_function*)&zend_pass_function;
3823                        EX(call)->called_scope = NULL;
3824                        Z_OBJ(EX(call)->This) = NULL;
3825
3826                        break;
3827                    }
3828
3829                    if (Z_REFCOUNTED_P(arg)) {
3830                        Z_DELREF_P(arg);
3831                    }
3832                    ZVAL_DUP(&tmp, arg);
3833                    ZVAL_NEW_REF(arg, &tmp);
3834                    Z_ADDREF_P(arg);
3835                } else if (!Z_ISREF_P(arg)) {
3836                    ZVAL_NEW_REF(arg, arg);
3837                    Z_ADDREF_P(arg);
3838                } else if (Z_REFCOUNTED_P(arg)) {
3839                    Z_ADDREF_P(arg);
3840                }
3841                ZVAL_COPY_VALUE(param, arg);
3842            } else if (Z_ISREF_P(arg) &&
3843                   /* don't separate references for __call */
3844                   (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
3845                ZVAL_DUP(param, Z_REFVAL_P(arg));
3846            } else {
3847                ZVAL_COPY(param, arg);
3848            }
3849            ZEND_CALL_NUM_ARGS(EX(call))++;
3850            arg_num++;
3851            param++;
3852        } ZEND_HASH_FOREACH_END();
3853    }
3854    FREE_OP1();
3855    CHECK_EXCEPTION();
3856    ZEND_VM_NEXT_OPCODE();
3857}
3858
3859ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
3860{
3861    USE_OPLINE
3862    zval *arg, *param, tmp;
3863    zend_free_op free_op1;
3864
3865    arg = GET_OP1_ZVAL_PTR(BP_VAR_R);
3866    param = ZEND_CALL_VAR(EX(call), opline->result.var);
3867
3868    if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
3869        // TODO: Scalar values don't have reference counters anymore.
3870        // They are assumed to be 1, and they may be easily passed by
3871        // reference now. However, previously scalars with refcount==1
3872        // might be passed and with refcount>1 might not. We can support
3873        // only single behavior ???
3874#if 0
3875        if (Z_REFCOUNTED_P(arg) &&
3876            // This solution breaks the following test (omit warning message) ???
3877            // Zend/tests/bug61273.phpt
3878            // ext/reflection/tests/bug42976.phpt
3879            // ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
3880#else
3881        if (!Z_REFCOUNTED_P(arg) ||
3882            // This solution breaks the following test (emit warning message) ???
3883            // ext/pdo_sqlite/tests/pdo_005.phpt
3884#endif
3885            (!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
3886
3887            if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
3888
3889                zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
3890                    opline->op2.num,
3891                    EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
3892                    EX(call)->func->common.scope ? "::" : "",
3893                    EX(call)->func->common.function_name->val);
3894
3895                if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
3896                    OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
3897                }
3898                if (Z_OBJ(EX(call)->This)) {
3899                    OBJ_RELEASE(Z_OBJ(EX(call)->This));
3900                }
3901                ZVAL_UNDEF(param);
3902                EX(call)->func = (zend_function*)&zend_pass_function;
3903                EX(call)->called_scope = NULL;
3904                Z_OBJ(EX(call)->This) = NULL;
3905
3906                FREE_OP1();
3907                CHECK_EXCEPTION();
3908                ZEND_VM_NEXT_OPCODE();
3909            }
3910
3911            if (Z_REFCOUNTED_P(arg)) {
3912                Z_DELREF_P(arg);
3913            }
3914            ZVAL_DUP(&tmp, arg);
3915            ZVAL_NEW_REF(arg, &tmp);
3916            Z_ADDREF_P(arg);
3917        } else if (!Z_ISREF_P(arg)) {
3918            ZVAL_NEW_REF(arg, arg);
3919            Z_ADDREF_P(arg);
3920        } else if (Z_REFCOUNTED_P(arg)) {
3921            Z_ADDREF_P(arg);
3922        }
3923        ZVAL_COPY_VALUE(param, arg);
3924    } else if (Z_ISREF_P(arg) &&
3925               /* don't separate references for __call */
3926               (EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
3927        ZVAL_DUP(param, Z_REFVAL_P(arg));
3928    } else {
3929        ZVAL_COPY(param, arg);
3930    }
3931
3932    FREE_OP1();
3933    CHECK_EXCEPTION();
3934    ZEND_VM_NEXT_OPCODE();
3935}
3936
3937ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
3938{
3939    USE_OPLINE
3940    uint32_t arg_num = opline->op1.num;
3941
3942    SAVE_OPLINE();
3943    if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
3944        zend_verify_missing_arg(execute_data, arg_num);
3945        CHECK_EXCEPTION();
3946    } else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
3947        zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
3948
3949        zend_verify_arg_type(EX(func), arg_num, param, NULL);
3950        CHECK_EXCEPTION();
3951    }
3952
3953    ZEND_VM_NEXT_OPCODE();
3954}
3955
3956ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
3957{
3958    USE_OPLINE
3959    uint32_t arg_num = opline->op1.num;
3960    zval *param;
3961
3962    SAVE_OPLINE();
3963    param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
3964    if (arg_num > EX_NUM_ARGS()) {
3965        ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2));
3966        if (Z_OPT_CONSTANT_P(param)) {
3967            zval_update_constant(param, 0);
3968        } else {
3969            /* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
3970            if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
3971                zval_copy_ctor_func(param);
3972            }
3973        }
3974    }
3975
3976    if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
3977        zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2));
3978    }
3979
3980    CHECK_EXCEPTION();
3981    ZEND_VM_NEXT_OPCODE();
3982}
3983
3984ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
3985{
3986    USE_OPLINE
3987    uint32_t arg_num = opline->op1.num;
3988    uint32_t arg_count = EX_NUM_ARGS();
3989    zval *params;
3990
3991    SAVE_OPLINE();
3992
3993    params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
3994
3995    if (arg_num <= arg_count) {
3996        zval *param;
3997
3998        array_init_size(params, arg_count - arg_num + 1);
3999        zend_hash_real_init(Z_ARRVAL_P(params), 1);
4000        ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(params)) {
4001            param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
4002            if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
4003                do {
4004                    zend_verify_arg_type(EX(func), arg_num, param, NULL);
4005                    if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
4006                    ZEND_HASH_FILL_ADD(param);
4007                    param++;
4008                } while (++arg_num <= arg_count);
4009            } else {
4010                do {
4011                    if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
4012                    ZEND_HASH_FILL_ADD(param);
4013                    param++;
4014                } while (++arg_num <= arg_count);
4015            }
4016        } ZEND_HASH_FILL_END();
4017    } else {
4018        array_init(params);
4019    }
4020
4021    CHECK_EXCEPTION();
4022    ZEND_VM_NEXT_OPCODE();
4023}
4024
4025ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
4026{
4027    USE_OPLINE
4028    zval *val;
4029    zend_free_op free_op1;
4030
4031    SAVE_OPLINE();
4032    val = GET_OP1_ZVAL_PTR(BP_VAR_R);
4033    if (Z_TYPE_P(val) == IS_TRUE) {
4034        ZVAL_TRUE(EX_VAR(opline->result.var));
4035    } else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
4036        ZVAL_FALSE(EX_VAR(opline->result.var));
4037    } else {
4038        ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val));
4039        FREE_OP1();
4040        CHECK_EXCEPTION();
4041    }
4042    ZEND_VM_NEXT_OPCODE();
4043}
4044
4045ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
4046{
4047    USE_OPLINE
4048    zend_brk_cont_element *el;
4049
4050    SAVE_OPLINE();
4051    el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
4052                       &EX(func)->op_array, execute_data);
4053    ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
4054}
4055
4056ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
4057{
4058    USE_OPLINE
4059    zend_brk_cont_element *el;
4060
4061    SAVE_OPLINE();
4062    el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
4063                       &EX(func)->op_array, execute_data);
4064    ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
4065}
4066
4067ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
4068{
4069    zend_op *brk_opline;
4070    USE_OPLINE
4071    zend_brk_cont_element *el;
4072
4073    SAVE_OPLINE();
4074    el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->extended_value,
4075                       &EX(func)->op_array, execute_data);
4076
4077    brk_opline = EX(func)->op_array.opcodes + el->brk;
4078
4079    if (brk_opline->opcode == ZEND_FREE) {
4080        if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
4081            zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
4082        }
4083    } else if (brk_opline->opcode == ZEND_FE_FREE) {
4084        if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
4085            zval *var = EX_VAR(brk_opline->op1.var);
4086            if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
4087                zend_hash_iterator_del(Z_FE_ITER_P(var));
4088            }
4089            zval_ptr_dtor_nogc(var);
4090        }
4091    }
4092    ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
4093}
4094
4095ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
4096{
4097    USE_OPLINE
4098    zend_free_op free_op1, free_op2;
4099    zval *result = EX_VAR(opline->result.var);
4100
4101    SAVE_OPLINE();
4102    fast_equal_function(result,
4103         GET_OP1_ZVAL_PTR(BP_VAR_R),
4104         GET_OP2_ZVAL_PTR(BP_VAR_R));
4105
4106    FREE_OP2();
4107    CHECK_EXCEPTION();
4108    ZEND_VM_NEXT_OPCODE();
4109}
4110
4111ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
4112{
4113    USE_OPLINE
4114    zval object_zval;
4115    zend_function *constructor;
4116    zend_class_entry *ce;
4117
4118    SAVE_OPLINE();
4119    if (OP1_TYPE == IS_CONST) {
4120        if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
4121            ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
4122        } else {
4123            ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0);
4124            if (UNEXPECTED(ce == NULL)) {
4125                CHECK_EXCEPTION();
4126                ZEND_VM_NEXT_OPCODE();
4127            }
4128            CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
4129        }
4130    } else {
4131        ce = Z_CE_P(EX_VAR(opline->op1.var));
4132    }
4133    if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
4134        if (ce->ce_flags & ZEND_ACC_INTERFACE) {
4135            zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
4136        } else if (ce->ce_flags & ZEND_ACC_TRAIT) {
4137            zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
4138        } else {
4139            zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
4140        }
4141    }
4142    object_init_ex(&object_zval, ce);
4143    constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval));
4144
4145    if (constructor == NULL) {
4146        if (EXPECTED(RETURN_VALUE_USED(opline))) {
4147            ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
4148        } else {
4149            OBJ_RELEASE(Z_OBJ(object_zval));
4150        }
4151        ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
4152    } else {
4153        /* We are not handling overloaded classes right now */
4154        EX(call) = zend_vm_stack_push_call_frame(
4155                ZEND_CALL_FUNCTION | ZEND_CALL_CTOR |
4156                (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED),
4157            constructor,
4158            opline->extended_value,
4159            ce,
4160            Z_OBJ(object_zval),
4161            EX(call));
4162
4163        if (EXPECTED(RETURN_VALUE_USED(opline))) {
4164            ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
4165            EX(call)->return_value = EX_VAR(opline->result.var);
4166        } else {
4167            EX(call)->return_value = NULL;
4168        }
4169
4170        CHECK_EXCEPTION();
4171        ZEND_VM_NEXT_OPCODE();
4172    }
4173}
4174
4175ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
4176{
4177    USE_OPLINE
4178    zend_free_op free_op1;
4179    zval *obj;
4180    zend_class_entry *ce;
4181    zend_function *clone;
4182    zend_object_clone_obj_t clone_call;
4183
4184    SAVE_OPLINE();
4185    obj = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
4186
4187    do {
4188        if (OP1_TYPE == IS_CONST ||
4189            (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
4190            if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
4191                obj = Z_REFVAL_P(obj);
4192                if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
4193                    break;
4194                }
4195            }
4196            if (UNEXPECTED(EG(exception) != NULL)) {
4197                HANDLE_EXCEPTION();
4198            }
4199            zend_error_noreturn(E_ERROR, "__clone method called on non-object");
4200        }
4201    } while (0);
4202
4203    ce = Z_OBJCE_P(obj);
4204    clone = ce ? ce->clone : NULL;
4205    clone_call =  Z_OBJ_HT_P(obj)->clone_obj;
4206    if (UNEXPECTED(clone_call == NULL)) {
4207        if (ce) {
4208            zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val);
4209        } else {
4210            zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object");
4211        }
4212    }
4213
4214    if (ce && clone) {
4215        if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
4216            /* Ensure that if we're calling a private function, we're allowed to do so.
4217             */
4218            if (UNEXPECTED(ce != EG(scope))) {
4219                zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
4220            }
4221        } else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
4222            /* Ensure that if we're calling a protected function, we're allowed to do so.
4223             */
4224            if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
4225                zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
4226            }
4227        }
4228    }
4229
4230    if (EXPECTED(EG(exception) == NULL)) {
4231        ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
4232        if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
4233            OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
4234        }
4235    }
4236    FREE_OP1();
4237    CHECK_EXCEPTION();
4238    ZEND_VM_NEXT_OPCODE();
4239}
4240
4241ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
4242{
4243    USE_OPLINE
4244
4245    SAVE_OPLINE();
4246    if (OP1_TYPE == IS_UNUSED) {
4247        zend_constant *c;
4248        zval *retval;
4249
4250        if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
4251            c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
4252        } else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
4253            if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
4254                char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
4255                if (!actual) {
4256                    ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2))));
4257                } else {
4258                    actual++;
4259                    ZVAL_STRINGL(EX_VAR(opline->result.var),
4260                            actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
4261                }
4262                /* non-qualified constant - allow text substitution */
4263                zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
4264                        Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
4265                CHECK_EXCEPTION();
4266                ZEND_VM_NEXT_OPCODE();
4267            } else {
4268                zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
4269            }
4270        } else {
4271            CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
4272        }
4273        retval = EX_VAR(opline->result.var);
4274        ZVAL_COPY_VALUE(retval, &c->value);
4275        if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
4276            if (Z_OPT_COPYABLE_P(retval)) {
4277                zval_copy_ctor_func(retval);
4278            } else {
4279                Z_ADDREF_P(retval);
4280            }
4281        }
4282    } else {
4283        /* class constant */
4284        zend_class_entry *ce;
4285        zval *value;
4286
4287        if (OP1_TYPE == IS_CONST) {
4288            if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
4289                value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
4290                ZVAL_DEREF(value);
4291                ZVAL_DUP(EX_VAR(opline->result.var), value);
4292                ZEND_VM_C_GOTO(constant_fetch_end);
4293            } else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
4294                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
4295            } else {
4296                ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0);
4297                if (UNEXPECTED(EG(exception) != NULL)) {
4298                    HANDLE_EXCEPTION();
4299                }
4300                if (UNEXPECTED(ce == NULL)) {
4301                    zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
4302                }
4303                CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
4304            }
4305        } else {
4306            ce = Z_CE_P(EX_VAR(opline->op1.var));
4307            if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
4308                ZVAL_DEREF(value);
4309                ZVAL_DUP(EX_VAR(opline->result.var), value);
4310                ZEND_VM_C_GOTO(constant_fetch_end);
4311            }
4312        }
4313
4314        if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
4315            ZVAL_DEREF(value);
4316            if (Z_CONSTANT_P(value)) {
4317                EG(scope) = ce;
4318                zval_update_constant(value, 1);
4319                EG(scope) = EX(func)->op_array.scope;
4320            }
4321            if (OP1_TYPE == IS_CONST) {
4322                CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
4323            } else {
4324                CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
4325            }
4326            ZVAL_DUP(EX_VAR(opline->result.var), value);
4327        } else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
4328            /* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
4329            ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
4330        } else {
4331            zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
4332        }
4333    }
4334ZEND_VM_C_LABEL(constant_fetch_end):
4335    CHECK_EXCEPTION();
4336    ZEND_VM_NEXT_OPCODE();
4337}
4338
4339ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|CV)
4340{
4341    USE_OPLINE
4342    zend_free_op free_op1;
4343    zval *expr_ptr, new_expr;
4344
4345    SAVE_OPLINE();
4346    if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) &&
4347        (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
4348        expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
4349        if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
4350            zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
4351        }
4352        ZVAL_MAKE_REF(expr_ptr);
4353        Z_ADDREF_P(expr_ptr);
4354        FREE_OP1_VAR_PTR();
4355    } else {
4356        expr_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4357        if (OP1_TYPE == IS_TMP_VAR) {
4358            ZVAL_COPY_VALUE(&new_expr, expr_ptr);
4359            expr_ptr = &new_expr;
4360        } else if (OP1_TYPE == IS_CONST) {
4361            if (!Z_IMMUTABLE_P(expr_ptr)) {
4362                ZVAL_DUP(&new_expr, expr_ptr);
4363                expr_ptr = &new_expr;
4364            }
4365        } else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_ISREF_P(expr_ptr)) {
4366            expr_ptr = Z_REFVAL_P(expr_ptr);
4367            if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
4368            FREE_OP1_IF_VAR();
4369        } else if (OP1_TYPE == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
4370            Z_ADDREF_P(expr_ptr);
4371        }
4372    }
4373
4374    if (OP2_TYPE != IS_UNUSED) {
4375        zend_free_op free_op2;
4376        zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
4377        zend_string *str;
4378        zend_ulong hval;
4379
4380ZEND_VM_C_LABEL(add_again):
4381        switch (Z_TYPE_P(offset)) {
4382            case IS_DOUBLE:
4383                hval = zend_dval_to_lval(Z_DVAL_P(offset));
4384                ZEND_VM_C_GOTO(num_index);
4385            case IS_LONG:
4386                hval = Z_LVAL_P(offset);
4387ZEND_VM_C_LABEL(num_index):
4388                zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
4389                break;
4390            case IS_STRING:
4391                str = Z_STR_P(offset);
4392                if (OP2_TYPE != IS_CONST) {
4393                    if (ZEND_HANDLE_NUMERIC(str, hval)) {
4394                        ZEND_VM_C_GOTO(num_index);
4395                    }
4396                }
4397ZEND_VM_C_LABEL(str_index):
4398                zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
4399                break;
4400            case IS_NULL:
4401                str = STR_EMPTY_ALLOC();
4402                ZEND_VM_C_GOTO(str_index);
4403            case IS_FALSE:
4404                hval = 0;
4405                ZEND_VM_C_GOTO(num_index);
4406            case IS_TRUE:
4407                hval = 1;
4408                ZEND_VM_C_GOTO(num_index);
4409            case IS_REFERENCE:
4410                offset = Z_REFVAL_P(offset);
4411                ZEND_VM_C_GOTO(add_again);
4412                break;
4413            default:
4414                zend_error(E_WARNING, "Illegal offset type");
4415                zval_ptr_dtor(expr_ptr);
4416                /* do nothing */
4417                break;
4418        }
4419        FREE_OP2();
4420    } else {
4421        zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
4422    }
4423    CHECK_EXCEPTION();
4424    ZEND_VM_NEXT_OPCODE();
4425}
4426
4427ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
4428{
4429    zval *array;
4430    uint32_t size;
4431    USE_OPLINE
4432
4433    array = EX_VAR(opline->result.var);
4434    if (OP1_TYPE != IS_UNUSED) {
4435        size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
4436    } else {
4437        size = 0;
4438    }
4439    ZVAL_NEW_ARR(array);
4440    zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
4441
4442    if (OP1_TYPE != IS_UNUSED) {
4443        /* Explicitly initialize array as not-packed if flag is set */
4444        if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
4445            zend_hash_real_init(Z_ARRVAL_P(array), 0);
4446        }
4447    }
4448
4449    if (OP1_TYPE == IS_UNUSED) {
4450        ZEND_VM_NEXT_OPCODE();
4451#if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)
4452    } else {
4453        ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT);
4454#endif
4455    }
4456}
4457
4458ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
4459{
4460    USE_OPLINE
4461    zend_free_op free_op1;
4462    zval *expr;
4463    zval *result = EX_VAR(opline->result.var);
4464
4465    SAVE_OPLINE();
4466    expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
4467
4468    switch (opline->extended_value) {
4469        case IS_NULL:
4470            /* This code is taken from convert_to_null. However, it does not seems very useful,
4471             * because a conversion to null always results in the same value. This could only
4472             * be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */
4473#if 0
4474            if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
4475                ZVAL_DEREF(expr);
4476            }
4477            if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) {
4478                if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL) == SUCCESS) {
4479                    break;
4480                }
4481            }
4482#endif
4483
4484            ZVAL_NULL(result);
4485            break;
4486        case _IS_BOOL:
4487            ZVAL_BOOL(result, zend_is_true(expr));
4488            break;
4489        case IS_LONG:
4490            ZVAL_LONG(result, zval_get_long(expr));
4491            break;
4492        case IS_DOUBLE:
4493            ZVAL_DOUBLE(result, zval_get_double(expr));
4494            break;
4495        case IS_STRING:
4496            ZVAL_STR(result, zval_get_string(expr));
4497            break;
4498        default:
4499            if (OP1_TYPE & (IS_VAR|IS_CV)) {
4500                ZVAL_DEREF(expr);
4501            }
4502            /* If value is already of correct type, return it directly */
4503            if (Z_TYPE_P(expr) == opline->extended_value) {
4504                ZVAL_COPY_VALUE(result, expr);
4505                if (OP1_TYPE == IS_CONST) {
4506                    if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
4507                        zval_copy_ctor_func(result);
4508                    }
4509                } else if (OP1_TYPE != IS_TMP_VAR) {
4510                    if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
4511                }
4512
4513                FREE_OP1_IF_VAR();
4514                CHECK_EXCEPTION();
4515                ZEND_VM_NEXT_OPCODE();
4516            }
4517
4518            if (opline->extended_value == IS_ARRAY) {
4519                if (Z_TYPE_P(expr) != IS_OBJECT) {
4520                    ZVAL_NEW_ARR(result);
4521                    zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
4522                    if (Z_TYPE_P(expr) != IS_NULL) {
4523                        expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
4524                        if (OP1_TYPE == IS_CONST) {
4525                            if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
4526                                zval_copy_ctor_func(expr);
4527                            }
4528                        } else {
4529                            if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
4530                        }
4531                    }
4532                } else {
4533                    ZVAL_COPY_VALUE(result, expr);
4534                    Z_ADDREF_P(result);
4535                    convert_to_array(result);
4536                }
4537            } else {
4538                if (Z_TYPE_P(expr) != IS_ARRAY) {
4539                    object_init(result);
4540                    if (Z_TYPE_P(expr) != IS_NULL) {
4541                        expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
4542                        if (OP1_TYPE == IS_CONST) {
4543                            if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
4544                                zval_copy_ctor_func(expr);
4545                            }
4546                        } else {
4547                            if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
4548                        }
4549                    }
4550                } else {
4551                    ZVAL_COPY_VALUE(result, expr);
4552                    zval_opt_copy_ctor(result);
4553                    convert_to_object(result);
4554                }
4555            }
4556    }
4557
4558    FREE_OP1();
4559    CHECK_EXCEPTION();
4560    ZEND_VM_NEXT_OPCODE();
4561}
4562
4563ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY)
4564{
4565    USE_OPLINE
4566    zend_op_array *new_op_array=NULL;
4567    zend_free_op free_op1;
4568    zval *inc_filename;
4569    zval tmp_inc_filename;
4570    zend_bool failure_retval=0;
4571
4572    SAVE_OPLINE();
4573    inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R);
4574
4575    ZVAL_UNDEF(&tmp_inc_filename);
4576    if (Z_TYPE_P(inc_filename) != IS_STRING) {
4577        ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
4578        inc_filename = &tmp_inc_filename;
4579    }
4580
4581    if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
4582        if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
4583            zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
4584        } else {
4585            zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
4586        }
4587    } else {
4588        switch (opline->extended_value) {
4589            case ZEND_INCLUDE_ONCE:
4590            case ZEND_REQUIRE_ONCE: {
4591                    zend_file_handle file_handle;
4592                    zend_string *resolved_path;
4593
4594                    resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename));
4595                    if (resolved_path) {
4596                        failure_retval = zend_hash_exists(&EG(included_files), resolved_path);
4597                    } else {
4598                        resolved_path = zend_string_copy(Z_STR_P(inc_filename));
4599                    }
4600
4601                    if (failure_retval) {
4602                        /* do nothing, file already included */
4603                    } else if (SUCCESS == zend_stream_open(resolved_path->val, &file_handle)) {
4604
4605                        if (!file_handle.opened_path) {
4606                            file_handle.opened_path = zend_string_copy(resolved_path);
4607                        }
4608
4609                        if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path)) {
4610                            new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE));
4611                            zend_destroy_file_handle(&file_handle);
4612                        } else {
4613                            zend_file_handle_dtor(&file_handle);
4614                            failure_retval=1;
4615                        }
4616                    } else {
4617                        if (opline->extended_value == ZEND_INCLUDE_ONCE) {
4618                            zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
4619                        } else {
4620                            zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
4621                        }
4622                    }
4623                    zend_string_release(resolved_path);
4624                }
4625                break;
4626            case ZEND_INCLUDE:
4627            case ZEND_REQUIRE:
4628                new_op_array = compile_filename(opline->extended_value, inc_filename);
4629                break;
4630            case ZEND_EVAL: {
4631                    char *eval_desc = zend_make_compiled_string_description("eval()'d code");
4632
4633                    new_op_array = zend_compile_string(inc_filename, eval_desc);
4634                    efree(eval_desc);
4635                }
4636                break;
4637            EMPTY_SWITCH_DEFAULT_CASE()
4638        }
4639    }
4640    if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
4641        zend_string_release(Z_STR(tmp_inc_filename));
4642    }
4643    FREE_OP1();
4644    if (UNEXPECTED(EG(exception) != NULL)) {
4645        HANDLE_EXCEPTION();
4646    } else if (EXPECTED(new_op_array != NULL)) {
4647        zval *return_value = NULL;
4648        zend_execute_data *call;
4649
4650        if (RETURN_VALUE_USED(opline)) {
4651            return_value = EX_VAR(opline->result.var);
4652        }
4653
4654        new_op_array->scope = EG(scope); /* ??? */
4655
4656        call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE,
4657            (zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL);
4658
4659        if (EX(symbol_table)) {
4660            call->symbol_table = EX(symbol_table);
4661        } else {
4662            call->symbol_table = zend_rebuild_symbol_table();
4663        }
4664
4665        call->prev_execute_data = execute_data;
4666        i_init_code_execute_data(call, new_op_array, return_value);
4667        if (EXPECTED(zend_execute_ex == execute_ex)) {
4668            ZEND_VM_ENTER();
4669        } else {
4670            ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
4671            zend_execute_ex(call);
4672        }
4673
4674        destroy_op_array(new_op_array);
4675        efree_size(new_op_array, sizeof(zend_op_array));
4676        if (UNEXPECTED(EG(exception) != NULL)) {
4677            zend_throw_exception_internal(NULL);
4678            HANDLE_EXCEPTION();
4679        }
4680
4681    } else if (RETURN_VALUE_USED(opline)) {
4682        ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval);
4683    }
4684    ZEND_VM_NEXT_OPCODE();
4685}
4686
4687ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
4688{
4689    USE_OPLINE
4690    zval tmp, *varname;
4691    HashTable *target_symbol_table;
4692    zend_free_op free_op1;
4693
4694    SAVE_OPLINE();
4695    if (OP1_TYPE == IS_CV &&
4696        OP2_TYPE == IS_UNUSED &&
4697        (opline->extended_value & ZEND_QUICK_SET)) {
4698        zval *var = EX_VAR(opline->op1.var);
4699
4700        if (Z_REFCOUNTED_P(var)) {
4701            zend_refcounted *garbage = Z_COUNTED_P(var);
4702
4703            if (!--GC_REFCOUNT(garbage)) {
4704                ZVAL_UNDEF(var);
4705                _zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
4706            } else {
4707                GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
4708                ZVAL_UNDEF(var);
4709            }
4710        } else {
4711            ZVAL_UNDEF(var);
4712        }
4713        CHECK_EXCEPTION();
4714        ZEND_VM_NEXT_OPCODE();
4715    }
4716
4717    varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
4718
4719    ZVAL_UNDEF(&tmp);
4720    if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
4721        ZVAL_STR(&tmp, zval_get_string(varname));
4722        varname = &tmp;
4723    }
4724
4725    if (OP2_TYPE != IS_UNUSED) {
4726        zend_class_entry *ce;
4727
4728        if (OP2_TYPE == IS_CONST) {
4729            if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
4730                ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
4731            } else {
4732                ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
4733                if (UNEXPECTED(EG(exception) != NULL)) {
4734                    if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
4735                        zend_string_release(Z_STR(tmp));
4736                    }
4737                    FREE_OP1();
4738                    HANDLE_EXCEPTION();
4739                }
4740                if (UNEXPECTED(ce == NULL)) {
4741                    zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
4742                }
4743                CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
4744            }
4745        } else {
4746            ce = Z_CE_P(EX_VAR(opline->op2.var));
4747        }
4748        zend_std_unset_static_property(ce, Z_STR_P(varname));
4749    } else {
4750        target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
4751        zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
4752    }
4753
4754    if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
4755        zend_string_release(Z_STR(tmp));
4756    }
4757    FREE_OP1();
4758    CHECK_EXCEPTION();
4759    ZEND_VM_NEXT_OPCODE();
4760}
4761
4762ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV)
4763{
4764    USE_OPLINE
4765    zend_free_op free_op1, free_op2;
4766    zval *container;
4767    zval *offset;
4768    zend_ulong hval;
4769
4770    SAVE_OPLINE();
4771    container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
4772    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
4773        zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
4774    }
4775    offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
4776
4777ZEND_VM_C_LABEL(unset_dim_again):
4778    if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
4779        HashTable *ht;
4780
4781ZEND_VM_C_LABEL(offset_again):
4782        SEPARATE_ARRAY(container);
4783        ht = Z_ARRVAL_P(container);
4784        switch (Z_TYPE_P(offset)) {
4785            case IS_DOUBLE:
4786                hval = zend_dval_to_lval(Z_DVAL_P(offset));
4787                zend_hash_index_del(ht, hval);
4788                break;
4789            case IS_LONG:
4790                hval = Z_LVAL_P(offset);
4791ZEND_VM_C_LABEL(num_index_dim):
4792                zend_hash_index_del(ht, hval);
4793                break;
4794            case IS_STRING:
4795                if (OP2_TYPE != IS_CONST) {
4796                    if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
4797                        ZEND_VM_C_GOTO(num_index_dim);
4798                    }
4799                }
4800                if (ht == &EG(symbol_table)) {
4801                    zend_delete_global_variable(Z_STR_P(offset));
4802                } else {
4803                    zend_hash_del(ht, Z_STR_P(offset));
4804                }
4805                break;
4806            case IS_NULL:
4807                zend_hash_del(ht, STR_EMPTY_ALLOC());
4808                break;
4809            case IS_FALSE:
4810                hval = 0;
4811                ZEND_VM_C_GOTO(num_index_dim);
4812            case IS_TRUE:
4813                hval = 1;
4814                ZEND_VM_C_GOTO(num_index_dim);
4815            case IS_RESOURCE:
4816                hval = Z_RES_HANDLE_P(offset);
4817                ZEND_VM_C_GOTO(num_index_dim);
4818            case IS_REFERENCE:
4819                offset = Z_REFVAL_P(offset);
4820                ZEND_VM_C_GOTO(offset_again);
4821                break;
4822            default:
4823                zend_error(E_WARNING, "Illegal offset type in unset");
4824                break;
4825        }
4826        FREE_OP2();
4827    } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
4828        if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
4829            zend_error_noreturn(E_ERROR, "Cannot use object as array");
4830        }
4831//???       if (OP2_TYPE == IS_CONST) {
4832//???           zval_copy_ctor(offset);
4833//???       }
4834        Z_OBJ_HT_P(container)->unset_dimension(container, offset);
4835        FREE_OP2();
4836    } else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) {
4837        container = Z_REFVAL_P(container);
4838        ZEND_VM_C_GOTO(unset_dim_again);
4839    } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
4840        zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
4841        ZEND_VM_CONTINUE(); /* bailed out before */
4842    } else {
4843        FREE_OP2();
4844    }
4845    FREE_OP1_VAR_PTR();
4846    CHECK_EXCEPTION();
4847    ZEND_VM_NEXT_OPCODE();
4848}
4849
4850ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
4851{
4852    USE_OPLINE
4853    zend_free_op free_op1, free_op2;
4854    zval *container;
4855    zval *offset;
4856
4857    SAVE_OPLINE();
4858    container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
4859    if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
4860        zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
4861    }
4862    offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
4863
4864    do {
4865        if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
4866            if (Z_ISREF_P(container)) {
4867                container = Z_REFVAL_P(container);
4868                if (Z_TYPE_P(container) != IS_OBJECT) {
4869                    break;
4870                }
4871            } else {
4872                break;
4873            }
4874        }
4875        if (Z_OBJ_HT_P(container)->unset_property) {
4876            Z_OBJ_HT_P(container)->unset_property(container, offset, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
4877        } else {
4878            zend_error(E_NOTICE, "Trying to unset property of non-object");
4879        }
4880    } while (0);
4881
4882    FREE_OP2();
4883    FREE_OP1_VAR_PTR();
4884    CHECK_EXCEPTION();
4885    ZEND_VM_NEXT_OPCODE();
4886}
4887
4888ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, ANY)
4889{
4890    USE_OPLINE
4891    zend_free_op free_op1;
4892    zval *array_ptr, *result;
4893    HashTable *fe_ht;
4894
4895    SAVE_OPLINE();
4896
4897    array_ptr = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
4898    if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) {
4899        result = EX_VAR(opline->result.var);
4900        ZVAL_COPY_VALUE(result, array_ptr);
4901        if (OP1_TYPE != IS_TMP_VAR && Z_OPT_REFCOUNTED_P(result)) {
4902            Z_ADDREF_P(array_ptr);
4903        }
4904        Z_FE_POS_P(result) = 0;
4905
4906        FREE_OP1_IF_VAR();
4907        CHECK_EXCEPTION();
4908        ZEND_VM_NEXT_OPCODE();
4909    } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
4910        if (!Z_OBJCE_P(array_ptr)->get_iterator) {
4911            HashPosition pos = 0;
4912            Bucket *p;
4913
4914            result = EX_VAR(opline->result.var);
4915            ZVAL_COPY_VALUE(result, array_ptr);
4916            if (OP1_TYPE != IS_TMP_VAR) {
4917                Z_ADDREF_P(array_ptr);
4918            }
4919            fe_ht = Z_OBJPROP_P(array_ptr);
4920            pos = 0;
4921            while (1) {
4922                if (pos >= fe_ht->nNumUsed) {
4923                    FREE_OP1_IF_VAR();
4924                    Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
4925                    ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
4926                }
4927                p = fe_ht->arData + pos;
4928                if ((Z_TYPE(p->val) != IS_UNDEF &&
4929                     (Z_TYPE(p->val) != IS_INDIRECT ||
4930                      Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) &&
4931                    (!p->key ||
4932                     zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) {
4933                    break;
4934                }
4935                pos++;
4936            }
4937            Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos);
4938
4939            FREE_OP1_IF_VAR();
4940            CHECK_EXCEPTION();
4941            ZEND_VM_NEXT_OPCODE();
4942        } else {
4943            zend_class_entry *ce = Z_OBJCE_P(array_ptr);
4944            zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 0);
4945            zend_bool is_empty;
4946
4947            if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) {
4948                FREE_OP1();
4949                if (!EG(exception)) {
4950                    zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val);
4951                }
4952                zend_throw_exception_internal(NULL);
4953                HANDLE_EXCEPTION();
4954            }
4955
4956            iter->index = 0;
4957            if (iter->funcs->rewind) {
4958                iter->funcs->rewind(iter);
4959                if (UNEXPECTED(EG(exception) != NULL)) {
4960                    OBJ_RELEASE(&iter->std);
4961                    FREE_OP1();
4962                    HANDLE_EXCEPTION();
4963                }
4964            }
4965
4966            is_empty = iter->funcs->valid(iter) != SUCCESS;
4967
4968            if (UNEXPECTED(EG(exception) != NULL)) {
4969                OBJ_RELEASE(&iter->std);
4970                FREE_OP1();
4971                HANDLE_EXCEPTION();
4972            }
4973            iter->index = -1; /* will be set to 0 before using next handler */
4974
4975            ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std);
4976            Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
4977
4978            FREE_OP1();
4979            if (is_empty) {
4980                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
4981            } else {
4982                CHECK_EXCEPTION();
4983                ZEND_VM_NEXT_OPCODE();
4984            }
4985        }
4986    } else {
4987        zend_error(E_WARNING, "Invalid argument supplied for foreach()");
4988        ZVAL_UNDEF(EX_VAR(opline->result.var));
4989        Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
4990        FREE_OP1();
4991        ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
4992    }
4993}
4994
4995ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY)
4996{
4997    USE_OPLINE
4998    zend_free_op free_op1;
4999    zval *array_ptr, *array_ref;
5000    HashTable *fe_ht;
5001    HashPosition pos = 0;
5002    Bucket *p;
5003
5004    SAVE_OPLINE();
5005
5006    if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
5007        array_ref = array_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_R);
5008        if (Z_ISREF_P(array_ref)) {
5009            array_ptr = Z_REFVAL_P(array_ref);
5010        }
5011    } else {
5012        array_ref = array_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
5013    }
5014
5015    if (EXPECTED(Z_TYPE_P(array_ptr) == IS_ARRAY)) {
5016        if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
5017            if (array_ptr == array_ref) {
5018                ZVAL_NEW_REF(array_ref, array_ref);
5019                array_ptr = Z_REFVAL_P(array_ref);
5020            }
5021            Z_ADDREF_P(array_ref);
5022            ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
5023        } else {
5024            array_ptr = EX_VAR(opline->result.var);
5025            ZVAL_COPY_VALUE(array_ptr, array_ref);
5026        }
5027        if (OP1_TYPE == IS_CONST) {
5028            zval_copy_ctor_func(array_ptr);
5029        } else {
5030            SEPARATE_ARRAY(array_ptr);
5031        }
5032        fe_ht = Z_ARRVAL_P(array_ptr);
5033        while (1) {
5034            if (pos >= fe_ht->nNumUsed) {
5035                FREE_OP1_VAR_PTR();
5036                Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
5037                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
5038            }
5039            p = fe_ht->arData + pos;
5040            if (Z_TYPE(p->val) != IS_UNDEF &&
5041                (Z_TYPE(p->val) != IS_INDIRECT ||
5042                 Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) {
5043                break;
5044            }
5045            pos++;
5046        }
5047        Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos);
5048
5049        FREE_OP1_VAR_PTR();
5050        CHECK_EXCEPTION();
5051        ZEND_VM_NEXT_OPCODE();
5052    } else if (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(array_ptr) == IS_OBJECT)) {
5053        if (!Z_OBJCE_P(array_ptr)->get_iterator) {
5054            if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
5055                if (array_ptr == array_ref) {
5056                    ZVAL_NEW_REF(array_ref, array_ref);
5057                    array_ptr = Z_REFVAL_P(array_ref);
5058                }
5059                Z_ADDREF_P(array_ref);
5060                ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
5061            } else {
5062                array_ptr = EX_VAR(opline->result.var);
5063                ZVAL_COPY_VALUE(array_ptr, array_ref);
5064            }
5065            fe_ht = Z_OBJPROP_P(array_ptr);
5066            while (1) {
5067                if (pos >= fe_ht->nNumUsed) {
5068                    FREE_OP1_VAR_PTR();
5069                    Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
5070                    ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
5071                }
5072                p = fe_ht->arData + pos;
5073                if ((Z_TYPE(p->val) != IS_UNDEF &&
5074                     (Z_TYPE(p->val) != IS_INDIRECT ||
5075                      Z_TYPE_P(Z_INDIRECT(p->val)) != IS_UNDEF)) &&
5076                    (!p->key ||
5077                     zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS)) {
5078                    break;
5079                }
5080                pos++;
5081            }
5082            Z_FE_ITER_P(EX_VAR(opline->result.var)) = zend_hash_iterator_add(fe_ht, pos);
5083
5084            FREE_OP1_VAR_PTR();
5085            CHECK_EXCEPTION();
5086            ZEND_VM_NEXT_OPCODE();
5087        } else {
5088            zend_class_entry *ce = Z_OBJCE_P(array_ptr);
5089            zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, 1);
5090            zend_bool is_empty;
5091
5092            if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) {
5093                if (OP1_TYPE == IS_VAR) {
5094                    FREE_OP1_VAR_PTR();
5095                } else {
5096                    FREE_OP1();
5097                }
5098                if (!EG(exception)) {
5099                    zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val);
5100                }
5101                zend_throw_exception_internal(NULL);
5102                HANDLE_EXCEPTION();
5103            }
5104
5105            iter->index = 0;
5106            if (iter->funcs->rewind) {
5107                iter->funcs->rewind(iter);
5108                if (UNEXPECTED(EG(exception) != NULL)) {
5109                    OBJ_RELEASE(&iter->std);
5110                    if (OP1_TYPE == IS_VAR) {
5111                        FREE_OP1_VAR_PTR();
5112                    } else {
5113                        FREE_OP1();
5114                    }
5115                    HANDLE_EXCEPTION();
5116                }
5117            }
5118
5119            is_empty = iter->funcs->valid(iter) != SUCCESS;
5120
5121            if (UNEXPECTED(EG(exception) != NULL)) {
5122                OBJ_RELEASE(&iter->std);
5123                if (OP1_TYPE == IS_VAR) {
5124                    FREE_OP1_VAR_PTR();
5125                } else {
5126                    FREE_OP1();
5127                }
5128                HANDLE_EXCEPTION();
5129            }
5130            iter->index = -1; /* will be set to 0 before using next handler */
5131
5132            ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std);
5133            Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
5134
5135            if (OP1_TYPE == IS_VAR) {
5136                FREE_OP1_VAR_PTR();
5137            } else {
5138                FREE_OP1();
5139            }
5140            if (is_empty) {
5141                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
5142            } else {
5143                CHECK_EXCEPTION();
5144                ZEND_VM_NEXT_OPCODE();
5145            }
5146        }
5147    } else {
5148        zend_error(E_WARNING, "Invalid argument supplied for foreach()");
5149        ZVAL_UNDEF(EX_VAR(opline->result.var));
5150        Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
5151        if (OP1_TYPE == IS_VAR) {
5152            FREE_OP1_VAR_PTR();
5153        } else {
5154            FREE_OP1();
5155        }
5156        ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
5157    }
5158}
5159
5160ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY)
5161{
5162    USE_OPLINE
5163    zend_free_op free_op1;
5164    zval *array;
5165    zval *value;
5166    HashTable *fe_ht;
5167    HashPosition pos;
5168    Bucket *p;
5169
5170    array = EX_VAR(opline->op1.var);
5171    SAVE_OPLINE();
5172    if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
5173        fe_ht = Z_ARRVAL_P(array);
5174        pos = Z_FE_POS_P(EX_VAR(opline->op1.var));
5175        while (1) {
5176            if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
5177                /* reached end of iteration */
5178                ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
5179            }
5180            p = fe_ht->arData + pos;
5181            value = &p->val;
5182            if (Z_TYPE_P(value) == IS_UNDEF) {
5183                pos++;
5184                continue;
5185            } else if (Z_TYPE_P(value) == IS_INDIRECT) {
5186                value = Z_INDIRECT_P(value);
5187                if (Z_TYPE_P(value) == IS_UNDEF) {
5188                    pos++;
5189                    continue;
5190                }
5191            }
5192            break;
5193        }
5194        if (opline->extended_value) {
5195            if (!p->key) {
5196                ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h);
5197            } else {
5198                ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key);
5199            }
5200        }
5201        ZVAL_COPY(EX_VAR(opline->result.var), value);
5202        Z_FE_POS_P(EX_VAR(opline->op1.var)) = pos + 1;
5203        ZEND_VM_INC_OPCODE();
5204        ZEND_VM_NEXT_OPCODE();
5205    } else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
5206        zend_object_iterator *iter;
5207
5208        if ((iter = zend_iterator_unwrap(array)) == NULL) {
5209            /* plain object */
5210
5211            fe_ht = Z_OBJPROP_P(array);
5212            pos = zend_hash_iterator_pos(Z_FE_ITER_P(EX_VAR(opline->op1.var)), fe_ht);
5213            while (1) {
5214                if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
5215                    /* reached end of iteration */
5216                    ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
5217                }
5218
5219                p = fe_ht->arData + pos;
5220                value = &p->val;
5221                if (Z_TYPE_P(value) == IS_UNDEF) {
5222                    pos++;
5223                    continue;
5224                } else if (Z_TYPE_P(value) == IS_INDIRECT) {
5225                    value = Z_INDIRECT_P(value);
5226                    if (Z_TYPE_P(value) == IS_UNDEF) {
5227                        pos++;
5228                        continue;
5229                    }
5230                }
5231                if (!p->key ||
5232                    zend_check_property_access(Z_OBJ_P(array), p->key) == SUCCESS) {
5233                    break;
5234                }
52