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