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