php-internal-docs 8.4.8
Unofficial docs for php/php-src
Loading...
Searching...
No Matches
zend_execute.c
Go to the documentation of this file.
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#define ZEND_INTENSIVE_DEBUGGING 0
22
23#include <stdio.h>
24#include <signal.h>
25
26#include "zend.h"
27#include "zend_compile.h"
28#include "zend_execute.h"
29#include "zend_API.h"
30#include "zend_ptr_stack.h"
31#include "zend_constants.h"
32#include "zend_extensions.h"
33#include "zend_ini.h"
34#include "zend_exceptions.h"
35#include "zend_interfaces.h"
36#include "zend_closures.h"
37#include "zend_generators.h"
38#include "zend_vm.h"
39#include "zend_dtrace.h"
40#include "zend_inheritance.h"
41#include "zend_type_info.h"
42#include "zend_smart_str.h"
43#include "zend_observer.h"
44#include "zend_system_id.h"
45#include "zend_call_stack.h"
46#include "zend_attributes.h"
48
49/* Virtual current working directory support */
50#include "zend_virtual_cwd.h"
51
52#ifdef HAVE_GCC_GLOBAL_REGS
53# if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
54# define ZEND_VM_FP_GLOBAL_REG "%esi"
55# define ZEND_VM_IP_GLOBAL_REG "%edi"
56# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
57# define ZEND_VM_FP_GLOBAL_REG "%r14"
58# define ZEND_VM_IP_GLOBAL_REG "%r15"
59# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
60# define ZEND_VM_FP_GLOBAL_REG "r14"
61# define ZEND_VM_IP_GLOBAL_REG "r15"
62# elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
63# define ZEND_VM_FP_GLOBAL_REG "r14"
64# define ZEND_VM_IP_GLOBAL_REG "r15"
65# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__aarch64__)
66# define ZEND_VM_FP_GLOBAL_REG "x27"
67# define ZEND_VM_IP_GLOBAL_REG "x28"
68#elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__riscv) && __riscv_xlen == 64
69# define ZEND_VM_FP_GLOBAL_REG "x18"
70# define ZEND_VM_IP_GLOBAL_REG "x19"
71# endif
72#endif
73
74#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
75# pragma GCC diagnostic ignored "-Wvolatile-register-var"
76 register zend_execute_data* volatile execute_data __asm__(ZEND_VM_FP_GLOBAL_REG);
77# pragma GCC diagnostic warning "-Wvolatile-register-var"
78#endif
79
80#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
81# define EXECUTE_DATA_D void
82# define EXECUTE_DATA_C
83# define EXECUTE_DATA_DC
84# define EXECUTE_DATA_CC
85# define NO_EXECUTE_DATA_CC
86#else
87# define EXECUTE_DATA_D zend_execute_data* execute_data
88# define EXECUTE_DATA_C execute_data
89# define EXECUTE_DATA_DC , EXECUTE_DATA_D
90# define EXECUTE_DATA_CC , EXECUTE_DATA_C
91# define NO_EXECUTE_DATA_CC , NULL
92#endif
93
94#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
95# define OPLINE_D void
96# define OPLINE_C
97# define OPLINE_DC
98# define OPLINE_CC
99#else
100# define OPLINE_D const zend_op* opline
101# define OPLINE_C opline
102# define OPLINE_DC , OPLINE_D
103# define OPLINE_CC , OPLINE_C
104#endif
105
106#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
107# pragma GCC diagnostic ignored "-Wvolatile-register-var"
108 register const zend_op* volatile opline __asm__(ZEND_VM_IP_GLOBAL_REG);
109# pragma GCC diagnostic warning "-Wvolatile-register-var"
110#else
111#endif
112
113#define _CONST_CODE 0
114#define _TMP_CODE 1
115#define _VAR_CODE 2
116#define _UNUSED_CODE 3
117#define _CV_CODE 4
118
119typedef int (ZEND_FASTCALL *incdec_t)(zval *);
120
121#define get_zval_ptr(op_type, node, type) _get_zval_ptr(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
122#define get_zval_ptr_deref(op_type, node, type) _get_zval_ptr_deref(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
123#define get_zval_ptr_undef(op_type, node, type) _get_zval_ptr_undef(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
124#define get_op_data_zval_ptr_r(op_type, node) _get_op_data_zval_ptr_r(op_type, node EXECUTE_DATA_CC OPLINE_CC)
125#define get_op_data_zval_ptr_deref_r(op_type, node) _get_op_data_zval_ptr_deref_r(op_type, node EXECUTE_DATA_CC OPLINE_CC)
126#define get_zval_ptr_ptr(op_type, node, type) _get_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC)
127#define get_zval_ptr_ptr_undef(op_type, node, type) _get_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC)
128#define get_obj_zval_ptr(op_type, node, type) _get_obj_zval_ptr(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
129#define get_obj_zval_ptr_undef(op_type, node, type) _get_obj_zval_ptr_undef(op_type, node, type EXECUTE_DATA_CC OPLINE_CC)
130#define get_obj_zval_ptr_ptr(op_type, node, type) _get_obj_zval_ptr_ptr(op_type, node, type EXECUTE_DATA_CC)
131
132#define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED)
133
134static ZEND_FUNCTION(pass)
135{
136}
137
138ZEND_BEGIN_ARG_INFO_EX(zend_pass_function_arg_info, 0, 0, 0)
140
142 ZEND_INTERNAL_FUNCTION, /* type */
143 {0, 0, 0}, /* arg_flags */
144 0, /* fn_flags */
145 NULL, /* name */
146 NULL, /* scope */
147 NULL, /* prototype */
148 0, /* num_args */
149 0, /* required_num_args */
150 (zend_internal_arg_info *) zend_pass_function_arg_info + 1, /* arg_info */
151 NULL, /* attributes */
152 NULL, /* run_time_cache */
153 NULL, /* doc_comment */
154 0, /* T */
155 NULL, /* prop_info */
156 ZEND_FN(pass), /* handler */
157 NULL, /* module */
158 NULL, /* frameless_function_infos */
159 {NULL,NULL,NULL,NULL} /* reserved */
160};
161
162#define FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_var) do { \
163 zval *__container_to_free = EX_VAR(free_var); \
164 if (UNEXPECTED(Z_REFCOUNTED_P(__container_to_free))) { \
165 zend_refcounted *__ref = Z_COUNTED_P(__container_to_free); \
166 if (UNEXPECTED(!GC_DELREF(__ref))) { \
167 zval *__zv = EX_VAR(opline->result.var); \
168 if (EXPECTED(Z_TYPE_P(__zv) == IS_INDIRECT)) { \
169 ZVAL_COPY(__zv, Z_INDIRECT_P(__zv)); \
170 } \
171 rc_dtor_func(__ref); \
172 } \
173 } \
174} while (0)
175
176#define FREE_OP(type, var) \
177 if ((type) & (IS_TMP_VAR|IS_VAR)) { \
178 zval_ptr_dtor_nogc(EX_VAR(var)); \
179 }
180
181#define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
182
183#define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
184
185#define ZEND_VM_STACK_PAGE_SIZE (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
186
187#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size, page_size) \
188 (((size) + ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval) \
189 + ((page_size) - 1)) & ~((page_size) - 1))
190
192{
193 EG(vm_stack_page_size) = ZEND_VM_STACK_PAGE_SIZE;
194 EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
195 EG(vm_stack_top) = EG(vm_stack)->top;
196 EG(vm_stack_end) = EG(vm_stack)->end;
197}
198
199ZEND_API void zend_vm_stack_init_ex(size_t page_size)
200{
201 /* page_size must be a power of 2 */
202 ZEND_ASSERT(page_size > 0 && (page_size & (page_size - 1)) == 0);
203 EG(vm_stack_page_size) = page_size;
204 EG(vm_stack) = zend_vm_stack_new_page(page_size, NULL);
205 EG(vm_stack_top) = EG(vm_stack)->top;
206 EG(vm_stack_end) = EG(vm_stack)->end;
207}
208
210{
211 zend_vm_stack stack = EG(vm_stack);
212
213 while (stack != NULL) {
214 zend_vm_stack p = stack->prev;
215 efree(stack);
216 stack = p;
217 }
218}
219
221{
222 zend_vm_stack stack;
223 void *ptr;
224
225 stack = EG(vm_stack);
226 stack->top = EG(vm_stack_top);
227 EG(vm_stack) = stack = zend_vm_stack_new_page(
228 EXPECTED(size < EG(vm_stack_page_size) - (ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval))) ?
229 EG(vm_stack_page_size) : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size, EG(vm_stack_page_size)),
230 stack);
231 ptr = stack->top;
232 EG(vm_stack_top) = (void*)(((char*)ptr) + size);
233 EG(vm_stack_end) = stack->end;
234 return ptr;
235}
236
238{
239 return EX_VAR(var);
240}
241
243{
244 #if defined(HAVE_GCC_GLOBAL_REGS)
245 return 1;
246 #else
247 return 0;
248 #endif
249}
250
251static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var EXECUTE_DATA_DC)
252{
253 zval *ret = EX_VAR(var);
254
256
257 return ret;
258}
259
260static zend_always_inline zval *_get_zval_ptr_var(uint32_t var EXECUTE_DATA_DC)
261{
262 zval *ret = EX_VAR(var);
263
264 return ret;
265}
266
267static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var EXECUTE_DATA_DC)
268{
269 zval *ret = EX_VAR(var);
270
272 return ret;
273}
274
275static zend_never_inline ZEND_COLD zval* zval_undefined_cv(uint32_t var EXECUTE_DATA_DC)
276{
277 if (EXPECTED(EG(exception) == NULL)) {
279 zend_error_unchecked(E_WARNING, "Undefined variable $%S", cv);
280 }
281 return &EG(uninitialized_zval);
282}
283
285{
286 return zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
287}
288
290{
291 return zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
292}
293
294#define ZVAL_UNDEFINED_OP1() _zval_undefined_op1(EXECUTE_DATA_C)
295#define ZVAL_UNDEFINED_OP2() _zval_undefined_op2(EXECUTE_DATA_C)
296
297static zend_never_inline ZEND_COLD zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type EXECUTE_DATA_DC)
298{
299 switch (type) {
300 case BP_VAR_R:
301 case BP_VAR_UNSET:
302 ptr = zval_undefined_cv(var EXECUTE_DATA_CC);
303 break;
304 case BP_VAR_IS:
305 ptr = &EG(uninitialized_zval);
306 break;
307 case BP_VAR_RW:
308 zval_undefined_cv(var EXECUTE_DATA_CC);
310 case BP_VAR_W:
311 ZVAL_NULL(ptr);
312 break;
313 }
314 return ptr;
315}
316
317static zend_always_inline zval *_get_zval_ptr_cv(uint32_t var, int type EXECUTE_DATA_DC)
318{
319 zval *ret = EX_VAR(var);
320
321 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
322 if (type == BP_VAR_W) {
323 ZVAL_NULL(ret);
324 } else {
325 return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
326 }
327 }
328 return ret;
329}
330
331static zend_always_inline zval *_get_zval_ptr_cv_deref(uint32_t var, int type EXECUTE_DATA_DC)
332{
333 zval *ret = EX_VAR(var);
334
335 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
336 if (type == BP_VAR_W) {
337 ZVAL_NULL(ret);
338 return ret;
339 } else {
340 return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
341 }
342 }
344 return ret;
345}
346
347static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
348{
349 zval *ret = EX_VAR(var);
350
351 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
352 return zval_undefined_cv(var EXECUTE_DATA_CC);
353 }
354 return ret;
355}
356
357static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
358{
359 zval *ret = EX_VAR(var);
360
361 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
362 return zval_undefined_cv(var EXECUTE_DATA_CC);
363 }
365 return ret;
366}
367
368static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
369{
370 zval *ret = EX_VAR(var);
371
372 return ret;
373}
374
375static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
376{
377 zval *ret = EX_VAR(var);
378
379 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
380 zval_undefined_cv(var EXECUTE_DATA_CC);
381 ZVAL_NULL(ret);
382 return ret;
383 }
384 return ret;
385}
386
387static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
388{
389 zval *ret = EX_VAR(var);
390
391 if (Z_TYPE_P(ret) == IS_UNDEF) {
392 ZVAL_NULL(ret);
393 }
394 return ret;
395}
396
397static zend_always_inline zval *_get_zval_ptr_tmpvarcv(int op_type, znode_op node, int type EXECUTE_DATA_DC)
398{
399 if (op_type & (IS_TMP_VAR|IS_VAR)) {
400 if (op_type == IS_TMP_VAR) {
401 return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
402 } else {
403 ZEND_ASSERT(op_type == IS_VAR);
404 return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC);
405 }
406 } else {
407 ZEND_ASSERT(op_type == IS_CV);
408 return _get_zval_ptr_cv_deref(node.var, type EXECUTE_DATA_CC);
409 }
410}
411
412static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC)
413{
414 if (op_type & (IS_TMP_VAR|IS_VAR)) {
415 if (!ZEND_DEBUG || op_type == IS_VAR) {
416 return _get_zval_ptr_var(node.var EXECUTE_DATA_CC);
417 } else {
418 ZEND_ASSERT(op_type == IS_TMP_VAR);
419 return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
420 }
421 } else {
422 if (op_type == IS_CONST) {
423 return RT_CONSTANT(opline, node);
424 } else if (op_type == IS_CV) {
425 return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
426 } else {
427 return NULL;
428 }
429 }
430}
431
432static zend_always_inline zval *_get_op_data_zval_ptr_r(int op_type, znode_op node EXECUTE_DATA_DC OPLINE_DC)
433{
434 if (op_type & (IS_TMP_VAR|IS_VAR)) {
435 if (!ZEND_DEBUG || op_type == IS_VAR) {
436 return _get_zval_ptr_var(node.var EXECUTE_DATA_CC);
437 } else {
438 ZEND_ASSERT(op_type == IS_TMP_VAR);
439 return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
440 }
441 } else {
442 if (op_type == IS_CONST) {
443 return RT_CONSTANT(opline + 1, node);
444 } else if (op_type == IS_CV) {
445 return _get_zval_ptr_cv_BP_VAR_R(node.var EXECUTE_DATA_CC);
446 } else {
447 return NULL;
448 }
449 }
450}
451
452static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_zval_ptr_deref(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC)
453{
454 if (op_type & (IS_TMP_VAR|IS_VAR)) {
455 if (op_type == IS_TMP_VAR) {
456 return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
457 } else {
458 ZEND_ASSERT(op_type == IS_VAR);
459 return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC);
460 }
461 } else {
462 if (op_type == IS_CONST) {
463 return RT_CONSTANT(opline, node);
464 } else if (op_type == IS_CV) {
465 return _get_zval_ptr_cv_deref(node.var, type EXECUTE_DATA_CC);
466 } else {
467 return NULL;
468 }
469 }
470}
471
472static zend_always_inline ZEND_ATTRIBUTE_UNUSED zval *_get_op_data_zval_ptr_deref_r(int op_type, znode_op node EXECUTE_DATA_DC OPLINE_DC)
473{
474 if (op_type & (IS_TMP_VAR|IS_VAR)) {
475 if (op_type == IS_TMP_VAR) {
476 return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
477 } else {
478 ZEND_ASSERT(op_type == IS_VAR);
479 return _get_zval_ptr_var_deref(node.var EXECUTE_DATA_CC);
480 }
481 } else {
482 if (op_type == IS_CONST) {
483 return RT_CONSTANT(opline + 1, node);
484 } else if (op_type == IS_CV) {
485 return _get_zval_ptr_cv_deref_BP_VAR_R(node.var EXECUTE_DATA_CC);
486 } else {
487 return NULL;
488 }
489 }
490}
491
492static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, int type EXECUTE_DATA_DC OPLINE_DC)
493{
494 if (op_type & (IS_TMP_VAR|IS_VAR)) {
495 if (!ZEND_DEBUG || op_type == IS_VAR) {
496 return _get_zval_ptr_var(node.var EXECUTE_DATA_CC);
497 } else {
498 ZEND_ASSERT(op_type == IS_TMP_VAR);
499 return _get_zval_ptr_tmp(node.var EXECUTE_DATA_CC);
500 }
501 } else {
502 if (op_type == IS_CONST) {
503 return RT_CONSTANT(opline, node);
504 } else if (op_type == IS_CV) {
505 return EX_VAR(node.var);
506 } else {
507 return NULL;
508 }
509 }
510}
511
512static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var EXECUTE_DATA_DC)
513{
514 zval *ret = EX_VAR(var);
515
516 if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
518 }
519 return ret;
520}
521
522static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC)
523{
524 if (op_type == IS_CV) {
525 return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
526 } else /* if (op_type == IS_VAR) */ {
527 ZEND_ASSERT(op_type == IS_VAR);
528 return _get_zval_ptr_ptr_var(node.var EXECUTE_DATA_CC);
529 }
530}
531
532static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr(int op_type, znode_op op, int type EXECUTE_DATA_DC OPLINE_DC)
533{
534 if (op_type == IS_UNUSED) {
535 return &EX(This);
536 }
537 return get_zval_ptr(op_type, op, type);
538}
539
540static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, int type EXECUTE_DATA_DC OPLINE_DC)
541{
542 if (op_type == IS_UNUSED) {
543 return &EX(This);
544 }
545 return get_zval_ptr_undef(op_type, op, type);
546}
547
548static inline ZEND_ATTRIBUTE_UNUSED zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, int type EXECUTE_DATA_DC)
549{
550 if (op_type == IS_UNUSED) {
551 return &EX(This);
552 }
553 return get_zval_ptr_ptr(op_type, node, type);
554}
555
556static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr, zend_refcounted **garbage_ptr)
557{
558 zend_reference *ref;
559
562 } else if (UNEXPECTED(variable_ptr == value_ptr)) {
563 return;
564 }
565
566 ref = Z_REF_P(value_ptr);
567 GC_ADDREF(ref);
569 *garbage_ptr = Z_COUNTED_P(variable_ptr);
570 }
572}
573
574static zend_never_inline zval* zend_assign_to_typed_property_reference(zend_property_info *prop_info, zval *prop, zval *value_ptr, zend_refcounted **garbage_ptr EXECUTE_DATA_DC)
575{
577 return &EG(uninitialized_zval);
578 }
579 if (Z_ISREF_P(prop)) {
581 }
582 zend_assign_to_variable_reference(prop, value_ptr, garbage_ptr);
584 return prop;
585}
586
587static zend_never_inline ZEND_COLD zval *zend_wrong_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr, zend_refcounted **garbage_ptr OPLINE_DC EXECUTE_DATA_DC)
588{
589 zend_error(E_NOTICE, "Only variables should be assigned by reference");
590 if (UNEXPECTED(EG(exception) != NULL)) {
591 return &EG(uninitialized_zval);
592 }
593
594 /* Use IS_TMP_VAR instead of IS_VAR to avoid ISREF check */
596 return zend_assign_to_variable_ex(variable_ptr, value_ptr, IS_TMP_VAR, EX_USES_STRICT_TYPES(), garbage_ptr);
597}
598
600{
601 const zend_execute_data *execute_data = EG(current_execute_data);
603 const char *param_name = get_function_arg_name(EX(call)->func, arg_num);
604
605 zend_throw_error(NULL, "%s(): Argument #%d%s%s%s could not be passed by reference",
606 ZSTR_VAL(func_name), arg_num, param_name ? " ($" : "", param_name ? param_name : "", param_name ? ")" : ""
607 );
608
609 zend_string_release(func_name);
610}
611
612static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_prop_error(zend_property_info *prop) {
613 zend_string *type_str = zend_type_to_string(prop->type);
615 "Cannot auto-initialize an array inside property %s::$%s of type %s",
616 ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name),
617 ZSTR_VAL(type_str)
618 );
619 zend_string_release(type_str);
620}
621
622static zend_never_inline ZEND_COLD void zend_throw_auto_init_in_ref_error(zend_property_info *prop) {
623 zend_string *type_str = zend_type_to_string(prop->type);
625 "Cannot auto-initialize an array inside a reference held by property %s::$%s of type %s",
626 ZSTR_VAL(prop->ce->name), zend_get_unmangled_property_name(prop->name),
627 ZSTR_VAL(type_str)
628 );
629 zend_string_release(type_str);
630}
631
632static zend_never_inline ZEND_COLD void zend_throw_access_uninit_prop_by_ref_error(
633 zend_property_info *prop) {
635 "Cannot access uninitialized non-nullable property %s::$%s by reference",
636 ZSTR_VAL(prop->ce->name),
637 zend_get_unmangled_property_name(prop->name));
638}
639
640/* this should modify object only if it's empty */
641static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_throw_non_object_error(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC)
642{
643 zend_string *tmp_property_name;
644 zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
645
646 if (opline->opcode == ZEND_PRE_INC_OBJ
647 || opline->opcode == ZEND_PRE_DEC_OBJ
648 || opline->opcode == ZEND_POST_INC_OBJ
649 || opline->opcode == ZEND_POST_DEC_OBJ) {
651 "Attempt to increment/decrement property \"%s\" on %s",
652 ZSTR_VAL(property_name), zend_zval_value_name(object)
653 );
654 } else if (opline->opcode == ZEND_FETCH_OBJ_W
655 || opline->opcode == ZEND_FETCH_OBJ_RW
656 || opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG
657 || opline->opcode == ZEND_ASSIGN_OBJ_REF) {
659 "Attempt to modify property \"%s\" on %s",
660 ZSTR_VAL(property_name), zend_zval_value_name(object)
661 );
662 } else {
664 "Attempt to assign property \"%s\" on %s",
665 ZSTR_VAL(property_name), zend_zval_value_name(object)
666 );
667 }
668 zend_tmp_string_release(tmp_property_name);
669
670 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
671 ZVAL_NULL(EX_VAR(opline->result.var));
672 }
673}
674
675static ZEND_COLD void zend_verify_type_error_common(
676 const zend_function *zf, const zend_arg_info *arg_info, zval *value,
677 const char **fname, const char **fsep, const char **fclass,
678 zend_string **need_msg, const char **given_kind)
679{
680 *fname = ZSTR_VAL(zf->common.function_name);
681 if (zf->common.scope) {
682 *fsep = "::";
683 *fclass = ZSTR_VAL(zf->common.scope->name);
684 } else {
685 *fsep = "";
686 *fclass = "";
687 }
688
689 *need_msg = zend_type_to_string_resolved(arg_info->type, zf->common.scope);
690
691 if (value) {
692 *given_kind = zend_zval_value_name(value);
693 } else {
694 *given_kind = "none";
695 }
696}
697
699 const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *value)
700{
701 zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
702 const char *fname, *fsep, *fclass;
703 zend_string *need_msg;
704 const char *given_msg;
705
706 zend_verify_type_error_common(
707 zf, arg_info, value, &fname, &fsep, &fclass, &need_msg, &given_msg);
708
710 && "Arginfo verification is not performed for internal functions");
711 if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
712 zend_argument_type_error(arg_num, "must be of type %s, %s given, called in %s on line %d",
713 ZSTR_VAL(need_msg), given_msg,
714 ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno
715 );
716 } else {
718 "must be of type %s, %s given", ZSTR_VAL(need_msg), given_msg);
719 }
720
721 zend_string_release(need_msg);
722}
723
724static bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg)
725{
726 zend_long lval;
727 double dval;
728 zend_string *str;
729 bool bval;
730
731 /* Type preference order: int -> float -> string -> bool */
732 if (type_mask & MAY_BE_LONG) {
733 /* For an int|float union type and string value,
734 * determine chosen type by is_numeric_string() semantics. */
735 if ((type_mask & MAY_BE_DOUBLE) && Z_TYPE_P(arg) == IS_STRING) {
736 uint8_t type = is_numeric_str_function(Z_STR_P(arg), &lval, &dval);
737 if (type == IS_LONG) {
738 zend_string_release(Z_STR_P(arg));
739 ZVAL_LONG(arg, lval);
740 return 1;
741 }
742 if (type == IS_DOUBLE) {
743 zend_string_release(Z_STR_P(arg));
745 return 1;
746 }
747 } else if (zend_parse_arg_long_weak(arg, &lval, 0)) {
749 ZVAL_LONG(arg, lval);
750 return 1;
751 } else if (UNEXPECTED(EG(exception))) {
752 return 0;
753 }
754 }
755 if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, 0)) {
758 return 1;
759 }
760 if ((type_mask & MAY_BE_STRING) && zend_parse_arg_str_weak(arg, &str, 0)) {
761 /* on success "arg" is converted to IS_STRING */
762 return 1;
763 }
764 if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval, 0)) {
766 ZVAL_BOOL(arg, bval);
767 return 1;
768 }
769 return 0;
770}
771
772#if ZEND_DEBUG
773static bool can_convert_to_string(const zval *zv) {
774 /* We don't call cast_object here, because this check must be side-effect free. As this
775 * is only used for a sanity check of arginfo/zpp consistency, it's okay if we accept
776 * more than actually allowed here. */
777 if (Z_TYPE_P(zv) == IS_OBJECT) {
778 return Z_OBJ_HT_P(zv)->cast_object != zend_std_cast_object_tostring
779 || Z_OBJCE_P(zv)->__tostring;
780 }
781 return Z_TYPE_P(zv) <= IS_STRING;
782}
783
784/* Used to sanity-check internal arginfo types without performing any actual type conversions. */
785static bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, const zval *arg)
786{
787 zend_long lval;
788 double dval;
789 bool bval;
790
791 /* Pass (uint32_t)-1 as arg_num to indicate to ZPP not to emit any deprecation notice,
792 * this is needed because the version with side effects also uses 0 (e.g. for typed properties) */
793 if ((type_mask & MAY_BE_LONG) && zend_parse_arg_long_weak(arg, &lval, (uint32_t)-1)) {
794 return 1;
795 }
796 if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, (uint32_t)-1)) {
797 return 1;
798 }
799 if ((type_mask & MAY_BE_STRING) && can_convert_to_string(arg)) {
800 return 1;
801 }
802 if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval, (uint32_t)-1)) {
803 return 1;
804 }
805 return 0;
806}
807#endif
808
809ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg)
810{
811 if (UNEXPECTED(strict)) {
812 /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
813 if (!(type_mask & MAY_BE_DOUBLE) || Z_TYPE_P(arg) != IS_LONG) {
814 return 0;
815 }
816 } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
817 /* NULL may be accepted only by nullable hints (this is already checked).
818 * As an exception for internal functions, null is allowed for scalar types in weak mode. */
819 return is_internal_arg
821 }
822#if ZEND_DEBUG
823 if (is_internal_arg) {
824 return zend_verify_weak_scalar_type_hint_no_sideeffect(type_mask, arg);
825 }
826#endif
827 return zend_verify_weak_scalar_type_hint(type_mask, arg);
828}
829
831{
832 zend_string *type_str = zend_type_to_string(c->type);
833
834 zend_type_error("Cannot assign %s to class constant %s::%s of type %s",
836
837 zend_string_release(type_str);
838}
839
841{
842 zend_string *type_str;
843
844 /* we _may_ land here in case reading already errored and runtime cache thus has not been updated (i.e. it contains a valid but unrelated info) */
845 if (EG(exception)) {
846 return;
847 }
848
849 type_str = zend_type_to_string(info->type);
850 zend_type_error("Cannot assign %s to property %s::$%s of type %s",
852 ZSTR_VAL(info->ce->name),
853 zend_get_unmangled_property_name(info->name),
854 ZSTR_VAL(type_str));
855 zend_string_release(type_str);
856}
857
859{
860 /* we _may_ land here in case reading already errored and runtime cache thus has not been updated (i.e. it contains a valid but unrelated info) */
861 if (EG(exception)) {
862 return;
863 }
864
865 zend_string *type_str = zend_type_to_string(info->type);
866 zend_type_error("Value of type %s returned from %s::__get() must be compatible with unset property %s::$%s of type %s",
868 ZSTR_VAL(info->ce->name),
869 ZSTR_VAL(info->ce->name),
870 zend_get_unmangled_property_name(info->name),
871 ZSTR_VAL(type_str));
872 zend_string_release(type_str);
873}
874
876{
877 smart_str msg = {0};
878 if (
879 EG(exception_ignore_args)
880 || smart_str_append_zval(&msg, value, EG(exception_string_param_max_len)) != SUCCESS
881 ) {
882 smart_str_appendl(&msg, "of type ", sizeof("of type ")-1);
883 smart_str_appends(&msg, zend_zval_type_name(value));
884 }
885 smart_str_0(&msg);
886
888 zend_ce_unhandled_match_error, 0, "Unhandled match case %s", ZSTR_VAL(msg.s));
889
890 smart_str_free(&msg);
891}
892
898
900 const char *class_name, const char *prop_name) {
901 zend_throw_error(NULL, "Cannot modify readonly property %s::$%s", class_name, prop_name);
902}
903
905{
906 zend_throw_error(NULL, "Cannot indirectly modify readonly property %s::$%s",
907 ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
908}
909
911{
912 zend_type_error("Cannot use value of type %s as class constant name", zend_get_type_by_const(type));
913}
914
916{
917 zend_throw_error(NULL, "Object was released while assigning to property %s::$%s",
918 ZSTR_VAL(info->ce->name), zend_get_unmangled_property_name(info->name));
919}
920
922 const zend_property_info *prop_info, const char *operation
923) {
925 if (EG(fake_scope)) {
926 scope = EG(fake_scope);
927 } else {
928 scope = zend_get_called_scope(EG(current_execute_data));
929 }
930
931 const char *visibility;
932 if (prop_info->flags & ZEND_ACC_PRIVATE_SET) {
933 visibility = "private(set)";
934 } else {
936 if (prop_info->flags & ZEND_ACC_READONLY) {
937 visibility = "protected(set) readonly";
938 } else {
939 visibility = "protected(set)";
940 }
941 }
942
943 zend_throw_error(NULL, "Cannot %s %s property %s::$%s from %s%s",
944 operation,
945 visibility,
946 ZSTR_VAL(prop_info->ce->name),
947 ZSTR_VAL(prop_info->name),
948 scope ? "scope " : "global scope", scope ? ZSTR_VAL(scope->name) : "");
949}
950
951static const zend_class_entry *resolve_single_class_type(zend_string *name, const zend_class_entry *self_ce) {
952 if (zend_string_equals_literal_ci(name, "self")) {
953 return self_ce;
954 } else if (zend_string_equals_literal_ci(name, "parent")) {
955 return self_ce->parent;
956 } else {
958 }
959}
960
961static zend_always_inline const zend_class_entry *zend_ce_from_type(
962 const zend_class_entry *scope, const zend_type *type) {
965 if (ZSTR_HAS_CE_CACHE(name)) {
967 if (!ce) {
969 }
970 return ce;
971 }
972 return resolve_single_class_type(name, scope);
973}
974
975static bool zend_check_intersection_for_property_or_class_constant_class_type(
976 const zend_class_entry *scope, zend_type_list *intersection_type_list, const zend_class_entry *value_ce)
977{
978 zend_type *list_type;
979
980 ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) {
981 ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
982 const zend_class_entry *ce = zend_ce_from_type(scope, list_type);
983 if (!ce || !instanceof_function(value_ce, ce)) {
984 return false;
985 }
987 return true;
988}
989
990static bool zend_check_and_resolve_property_or_class_constant_class_type(
991 const zend_class_entry *scope, zend_type member_type, const zend_class_entry *value_ce) {
992 if (ZEND_TYPE_HAS_LIST(member_type)) {
993 zend_type *list_type;
994 if (ZEND_TYPE_IS_INTERSECTION(member_type)) {
995 return zend_check_intersection_for_property_or_class_constant_class_type(
996 scope, ZEND_TYPE_LIST(member_type), value_ce);
997 } else {
998 ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(member_type), list_type) {
999 if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1000 if (zend_check_intersection_for_property_or_class_constant_class_type(
1001 scope, ZEND_TYPE_LIST(*list_type), value_ce)) {
1002 return true;
1003 }
1004 continue;
1005 }
1006 ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1007 const zend_class_entry *ce = zend_ce_from_type(scope, list_type);
1008 if (ce && instanceof_function(value_ce, ce)) {
1009 return true;
1010 }
1012
1013 if ((ZEND_TYPE_PURE_MASK(member_type) & MAY_BE_STATIC)) {
1014 return value_ce == scope;
1015 }
1016
1017 return false;
1018 }
1019 } else if ((ZEND_TYPE_PURE_MASK(member_type) & MAY_BE_STATIC) && value_ce == scope) {
1020 return true;
1021 } else if (ZEND_TYPE_HAS_NAME(member_type)) {
1022 const zend_class_entry *ce = zend_ce_from_type(scope, &member_type);
1023 return ce && instanceof_function(value_ce, ce);
1024 }
1025
1026 return false;
1027}
1028
1029static zend_always_inline bool i_zend_check_property_type(const zend_property_info *info, zval *property, bool strict)
1030{
1033 return 1;
1034 }
1035
1037 && zend_check_and_resolve_property_or_class_constant_class_type(info->ce, info->type, Z_OBJCE_P(property))) {
1038 return 1;
1039 }
1040
1041 uint32_t type_mask = ZEND_TYPE_FULL_MASK(info->type);
1043 return zend_verify_scalar_type_hint(type_mask, property, strict, 0);
1044}
1045
1046static zend_always_inline bool i_zend_verify_property_type(const zend_property_info *info, zval *property, bool strict)
1047{
1048 if (i_zend_check_property_type(info, property, strict)) {
1049 return 1;
1050 }
1051
1053 return 0;
1054}
1055
1057 return i_zend_verify_property_type(info, property, strict);
1058}
1059
1060static zend_never_inline zval* zend_assign_to_typed_prop(zend_property_info *info, zval *property_val, zval *value, zend_refcounted **garbage_ptr EXECUTE_DATA_DC)
1061{
1062 zval tmp;
1063
1065 if ((info->flags & ZEND_ACC_READONLY) && !(Z_PROP_FLAG_P(property_val) & IS_PROP_REINITABLE)) {
1067 return &EG(uninitialized_zval);
1068 }
1071 return &EG(uninitialized_zval);
1072 }
1073 }
1074
1076 ZVAL_COPY(&tmp, value);
1077
1078 if (UNEXPECTED(!i_zend_verify_property_type(info, &tmp, EX_USES_STRICT_TYPES()))) {
1079 zval_ptr_dtor(&tmp);
1080 return &EG(uninitialized_zval);
1081 }
1082
1083 Z_PROP_FLAG_P(property_val) &= ~IS_PROP_REINITABLE;
1084
1085 return zend_assign_to_variable_ex(property_val, &tmp, IS_TMP_VAR, EX_USES_STRICT_TYPES(), garbage_ptr);
1086}
1087
1088static zend_always_inline bool zend_value_instanceof_static(zval *zv) {
1089 if (Z_TYPE_P(zv) != IS_OBJECT) {
1090 return 0;
1091 }
1092
1093 zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
1094 if (!called_scope) {
1095 return 0;
1096 }
1097 return instanceof_function(Z_OBJCE_P(zv), called_scope);
1098}
1099
1100/* The cache_slot may only be NULL in debug builds, where arginfo verification of
1101 * internal functions is enabled. Avoid unnecessary checks in release builds. */
1102#if ZEND_DEBUG
1103# define HAVE_CACHE_SLOT (cache_slot != NULL)
1104#else
1105# define HAVE_CACHE_SLOT 1
1106#endif
1107
1108#define PROGRESS_CACHE_SLOT() if (HAVE_CACHE_SLOT) {cache_slot++;}
1109
1110static zend_always_inline zend_class_entry *zend_fetch_ce_from_cache_slot(
1111 void **cache_slot, zend_type *type)
1112{
1113 if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
1114 return (zend_class_entry *) *cache_slot;
1115 }
1116
1118 zend_class_entry *ce;
1119 if (ZSTR_HAS_CE_CACHE(name)) {
1120 ce = ZSTR_GET_CE_CACHE(name);
1121 if (!ce) {
1123 if (UNEXPECTED(!ce)) {
1124 /* Cannot resolve */
1125 return NULL;
1126 }
1127 }
1128 } else {
1131 if (UNEXPECTED(!ce)) {
1132 return NULL;
1133 }
1134 }
1135 if (HAVE_CACHE_SLOT) {
1136 *cache_slot = (void *) ce;
1137 }
1138 return ce;
1139}
1140
1141static bool zend_check_intersection_type_from_cache_slot(zend_type_list *intersection_type_list,
1142 zend_class_entry *arg_ce, void ***cache_slot_ptr)
1143{
1144 void **cache_slot = *cache_slot_ptr;
1145 zend_class_entry *ce;
1146 zend_type *list_type;
1147 bool status = true;
1148 ZEND_TYPE_LIST_FOREACH(intersection_type_list, list_type) {
1149 /* Only check classes if the type might be valid */
1150 if (status) {
1151 ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1152 /* If type is not an instance of one of the types taking part in the
1153 * intersection it cannot be a valid instance of the whole intersection type. */
1154 if (!ce || !instanceof_function(arg_ce, ce)) {
1155 status = false;
1156 }
1157 }
1160 if (HAVE_CACHE_SLOT) {
1161 *cache_slot_ptr = cache_slot;
1162 }
1163 return status;
1164}
1165
1166static zend_always_inline bool zend_check_type_slow(
1167 zend_type *type, zval *arg, zend_reference *ref, void **cache_slot,
1168 bool is_return_type, bool is_internal)
1169{
1170 uint32_t type_mask;
1172 zend_class_entry *ce;
1174 zend_type *list_type;
1176 return zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*type), Z_OBJCE_P(arg), &cache_slot);
1177 } else {
1179 if (ZEND_TYPE_IS_INTERSECTION(*list_type)) {
1180 if (zend_check_intersection_type_from_cache_slot(ZEND_TYPE_LIST(*list_type), Z_OBJCE_P(arg), &cache_slot)) {
1181 return true;
1182 }
1183 /* The cache_slot is progressed in zend_check_intersection_type_from_cache_slot() */
1184 } else {
1185 ZEND_ASSERT(!ZEND_TYPE_HAS_LIST(*list_type));
1186 ce = zend_fetch_ce_from_cache_slot(cache_slot, list_type);
1187 /* Instance of a single type part of a union is sufficient to pass the type check */
1188 if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
1189 return true;
1190 }
1192 }
1194 }
1195 } else {
1196 ce = zend_fetch_ce_from_cache_slot(cache_slot, type);
1197 /* If we have a CE we check if it satisfies the type constraint,
1198 * otherwise it will check if a standard type satisfies it. */
1199 if (ce && instanceof_function(Z_OBJCE_P(arg), ce)) {
1200 return true;
1201 }
1202 }
1203 }
1204
1205 type_mask = ZEND_TYPE_FULL_MASK(*type);
1206 if ((type_mask & MAY_BE_CALLABLE) &&
1208 return 1;
1209 }
1210 if ((type_mask & MAY_BE_STATIC) && zend_value_instanceof_static(arg)) {
1211 return 1;
1212 }
1213 if (ref && ZEND_REF_HAS_TYPE_SOURCES(ref)) {
1214 /* We cannot have conversions for typed refs. */
1215 return 0;
1216 }
1217 if (is_internal && is_return_type) {
1218 /* For internal returns, the type has to match exactly, because we're not
1219 * going to check it for non-debug builds, and there will be no chance to
1220 * apply coercions. */
1221 return 0;
1222 }
1223
1224 return zend_verify_scalar_type_hint(type_mask, arg,
1226 is_internal);
1227
1228 /* Special handling for IS_VOID is not necessary (for return types),
1229 * because this case is already checked at compile-time. */
1230}
1231
1232static zend_always_inline bool zend_check_type(
1233 zend_type *type, zval *arg, void **cache_slot, zend_class_entry *scope,
1234 bool is_return_type, bool is_internal)
1235{
1236 zend_reference *ref = NULL;
1238
1239 if (UNEXPECTED(Z_ISREF_P(arg))) {
1240 ref = Z_REF_P(arg);
1241 arg = Z_REFVAL_P(arg);
1242 }
1243
1245 return 1;
1246 }
1247
1248 return zend_check_type_slow(type, arg, ref, cache_slot, is_return_type, is_internal);
1249}
1250
1252 zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, bool is_return_type)
1253{
1254 return zend_check_type_slow(
1255 type, arg, ref, cache_slot, is_return_type, /* is_internal */ false);
1256}
1257
1258static zend_always_inline bool zend_verify_recv_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, void **cache_slot)
1259{
1260 zend_arg_info *cur_arg_info;
1261
1262 ZEND_ASSERT(arg_num <= zf->common.num_args);
1263 cur_arg_info = &zf->common.arg_info[arg_num-1];
1264
1265 if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1266 && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1267 zend_verify_arg_error(zf, cur_arg_info, arg_num, arg);
1268 return 0;
1269 }
1270
1271 return 1;
1272}
1273
1274static zend_always_inline bool zend_verify_variadic_arg_type(
1275 zend_function *zf, zend_arg_info *arg_info, uint32_t arg_num, zval *arg, void **cache_slot)
1276{
1277 ZEND_ASSERT(ZEND_TYPE_IS_SET(arg_info->type));
1278 if (UNEXPECTED(!zend_check_type(&arg_info->type, arg, cache_slot, zf->common.scope, 0, 0))) {
1279 zend_verify_arg_error(zf, arg_info, arg_num, arg);
1280 return 0;
1281 }
1282
1283 return 1;
1284}
1285
1286static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
1287{
1288 uint32_t i;
1289 uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
1290 zval *arg = ZEND_CALL_ARG(call, 1);
1291
1292 for (i = 0; i < num_args; ++i) {
1293 zend_arg_info *cur_arg_info;
1294 if (EXPECTED(i < fbc->common.num_args)) {
1295 cur_arg_info = &fbc->common.arg_info[i];
1296 } else if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
1297 cur_arg_info = &fbc->common.arg_info[fbc->common.num_args];
1298 } else {
1299 break;
1300 }
1301
1302 if (ZEND_TYPE_IS_SET(cur_arg_info->type)
1303 && UNEXPECTED(!zend_check_type(&cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
1304 return 0;
1305 }
1306 arg++;
1307 }
1308 return 1;
1309}
1310
1311#if ZEND_DEBUG
1312/* Determine whether an internal call should throw, because the passed arguments violate
1313 * an arginfo constraint. This is only checked in debug builds. In release builds, we
1314 * trust that arginfo matches what is enforced by zend_parse_parameters. */
1315ZEND_API bool zend_internal_call_should_throw(zend_function *fbc, zend_execute_data *call)
1316{
1317 if (fbc->internal_function.handler == ZEND_FN(pass) || (fbc->internal_function.fn_flags & ZEND_ACC_FAKE_CLOSURE)) {
1318 /* Be lenient about the special pass function and about fake closures. */
1319 return 0;
1320 }
1321
1322 if (fbc->common.required_num_args > ZEND_CALL_NUM_ARGS(call)) {
1323 /* Required argument not passed. */
1324 return 1;
1325 }
1326
1327 if (fbc->common.num_args < ZEND_CALL_NUM_ARGS(call)
1328 && !(fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
1329 /* Too many arguments passed. For internal functions (unlike userland functions),
1330 * this should always throw. */
1331 return 1;
1332 }
1333
1334 if ((fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) &&
1335 !zend_verify_internal_arg_types(fbc, call)) {
1336 return 1;
1337 }
1338
1339 return 0;
1340}
1341
1342ZEND_API ZEND_COLD void zend_internal_call_arginfo_violation(zend_function *fbc)
1343{
1344 zend_error_noreturn(E_ERROR, "Arginfo / zpp mismatch during call of %s%s%s()",
1345 fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "",
1346 fbc->common.scope ? "::" : "",
1347 ZSTR_VAL(fbc->common.function_name));
1348}
1349
1350#ifndef ZEND_VERIFY_FUNC_INFO
1351# define ZEND_VERIFY_FUNC_INFO 0
1352#endif
1353
1354static void zend_verify_internal_func_info(zend_function *fn, zval *retval) {
1355#if ZEND_VERIFY_FUNC_INFO
1357 uint32_t type_mask = zend_get_internal_func_info(fn, NULL, NULL);
1358 if (!type_mask) {
1359 return;
1360 }
1361
1362 /* Always check refcount of arrays, as immutable arrays are RCN. */
1364 if (!(type_mask & MAY_BE_RC1)) {
1365 zend_error_noreturn(E_CORE_ERROR, "%s() missing rc1", ZSTR_VAL(name));
1366 }
1367 if (Z_REFCOUNT_P(retval) > 1 && !(type_mask & MAY_BE_RCN)) {
1368 zend_error_noreturn(E_CORE_ERROR, "%s() missing rcn", ZSTR_VAL(name));
1369 }
1370 }
1371
1372 uint32_t type = 1u << Z_TYPE_P(retval);
1373 if (!(type_mask & type)) {
1374 zend_error_noreturn(E_CORE_ERROR, "%s() missing type %s",
1376 }
1377
1378 if (Z_TYPE_P(retval) == IS_ARRAY) {
1380 uint32_t num_checked = 0;
1381 zend_string *str;
1382 zval *val;
1384 if (str) {
1385 if (!(type_mask & MAY_BE_ARRAY_KEY_STRING)) {
1387 "%s() missing array_key_string", ZSTR_VAL(name));
1388 }
1389 } else {
1390 if (!(type_mask & MAY_BE_ARRAY_KEY_LONG)) {
1392 "%s() missing array_key_long", ZSTR_VAL(name));
1393 }
1394 }
1395
1396 uint32_t array_type = 1u << (Z_TYPE_P(val) + MAY_BE_ARRAY_SHIFT);
1397 if (!(type_mask & array_type)) {
1399 "%s() missing array element type %s",
1401 }
1402
1403 /* Don't check all elements of large arrays. */
1404 if (++num_checked > 16) {
1405 break;
1406 }
1408 }
1409#endif
1410}
1411#endif
1412
1414{
1416
1417 if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
1418 zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed in %s on line %d and %s %d expected",
1419 EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
1420 EX(func)->common.scope ? "::" : "",
1421 ZSTR_VAL(EX(func)->common.function_name),
1422 EX_NUM_ARGS(),
1423 ZSTR_VAL(ptr->func->op_array.filename),
1424 ptr->opline->lineno,
1425 EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
1426 EX(func)->common.required_num_args);
1427 } else {
1428 zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed and %s %d expected",
1429 EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
1430 EX(func)->common.scope ? "::" : "",
1431 ZSTR_VAL(EX(func)->common.function_name),
1432 EX_NUM_ARGS(),
1433 EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
1434 EX(func)->common.required_num_args);
1435 }
1436}
1437
1439{
1440 const zend_arg_info *arg_info = &zf->common.arg_info[-1];
1441 const char *fname, *fsep, *fclass;
1442 zend_string *need_msg;
1443 const char *given_msg;
1444
1445 zend_verify_type_error_common(
1446 zf, arg_info, value, &fname, &fsep, &fclass, &need_msg, &given_msg);
1447
1448 zend_type_error("%s%s%s(): Return value must be of type %s, %s returned",
1449 fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg);
1450
1451 zend_string_release(need_msg);
1452}
1453
1455{
1457
1458 zend_type_error("%s(): never-returning %s must not implicitly return",
1459 ZSTR_VAL(func_name), zf->common.scope ? "method" : "function");
1460
1461 zend_string_release(func_name);
1462}
1463
1464#if ZEND_DEBUG
1465static ZEND_COLD void zend_verify_internal_return_error(const zend_function *zf, zval *value)
1466{
1467 const zend_arg_info *arg_info = &zf->common.arg_info[-1];
1468 const char *fname, *fsep, *fclass;
1469 zend_string *need_msg;
1470 const char *given_msg;
1471
1472 zend_verify_type_error_common(
1473 zf, arg_info, value, &fname, &fsep, &fclass, &need_msg, &given_msg);
1474
1475 zend_error_noreturn(E_CORE_ERROR, "%s%s%s(): Return value must be of type %s, %s returned",
1476 fclass, fsep, fname, ZSTR_VAL(need_msg), given_msg);
1477}
1478
1479static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, const char *returned_msg, const char *returned_kind)
1480{
1481 const char *fname = ZSTR_VAL(zf->common.function_name);
1482 const char *fsep;
1483 const char *fclass;
1484
1485 if (zf->common.scope) {
1486 fsep = "::";
1487 fclass = ZSTR_VAL(zf->common.scope->name);
1488 } else {
1489 fsep = "";
1490 fclass = "";
1491 }
1492
1493 zend_type_error("%s%s%s() must not return a value, %s%s returned",
1494 fclass, fsep, fname, returned_msg, returned_kind);
1495}
1496
1497ZEND_API bool zend_verify_internal_return_type(zend_function *zf, zval *ret)
1498{
1500
1501 if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) {
1502 if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
1503 zend_verify_void_return_error(zf, zend_zval_value_name(ret), "");
1504 return 0;
1505 }
1506 return 1;
1507 }
1508
1509 if (UNEXPECTED(!zend_check_type(&ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) {
1510 zend_verify_internal_return_error(zf, ret);
1511 return 0;
1512 }
1513
1514 return 1;
1515}
1516#endif
1517
1518static ZEND_COLD void zend_verify_missing_return_type(const zend_function *zf)
1519{
1520 /* VERIFY_RETURN_TYPE is not emitted for "void" functions, so this is always an error. */
1522}
1523
1524static zend_always_inline bool zend_check_class_constant_type(zend_class_constant *c, zval *constant)
1525{
1528 return 1;
1529 }
1530
1532 && zend_check_and_resolve_property_or_class_constant_class_type(c->ce, c->type, Z_OBJCE_P(constant))) {
1533 return 1;
1534 }
1535
1536 uint32_t type_mask = ZEND_TYPE_FULL_MASK(c->type);
1538 return zend_verify_scalar_type_hint(type_mask, constant, true, false);
1539}
1540
1542{
1543 if (!zend_check_class_constant_type(c, constant)) {
1545 return 0;
1546 }
1547
1548 return 1;
1549}
1550
1551static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(const zend_object *object)
1552{
1553 zend_throw_error(NULL, "Cannot use object of type %s as array", ZSTR_VAL(object->ce->name));
1554}
1555
1556static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_access(const zval *offset)
1557{
1559}
1560
1561static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_isset(const zval *offset)
1562{
1564}
1565
1566static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_array_offset_unset(const zval *offset)
1567{
1569}
1570
1571static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_string_offset(const zval *offset, int type)
1572{
1574}
1575
1576static zend_never_inline void zend_assign_to_object_dim(zend_object *obj, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
1577{
1578 obj->handlers->write_dimension(obj, dim, value);
1579
1580 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1581 ZVAL_COPY(EX_VAR(opline->result.var), value);
1582 }
1583}
1584
1585static void frameless_observed_call_copy(zend_execute_data *call, uint32_t arg, zval *zv)
1586{
1587 if (Z_ISUNDEF_P(zv)) {
1589 } else {
1591 }
1592}
1593
1595{
1596 const zend_op *opline = EX(opline);
1597 uint8_t num_args = ZEND_FLF_NUM_ARGS(opline->opcode);
1598 zend_function *fbc = ZEND_FLF_FUNC(opline);
1599 zval *result = EX_VAR(opline->result.var);
1600
1601 zend_execute_data *call = zend_vm_stack_push_call_frame_ex(zend_vm_calc_used_stack(num_args, fbc), ZEND_CALL_NESTED_FUNCTION, fbc, num_args, NULL);
1602 call->prev_execute_data = execute_data;
1603
1604 switch (num_args) {
1605 case 3: frameless_observed_call_copy(call, 2, zend_get_zval_ptr(opline+1, (opline+1)->op1_type, &(opline+1)->op1, execute_data)); ZEND_FALLTHROUGH;
1606 case 2: frameless_observed_call_copy(call, 1, zend_get_zval_ptr(opline, opline->op2_type, &opline->op2, execute_data)); ZEND_FALLTHROUGH;
1607 case 1: frameless_observed_call_copy(call, 0, zend_get_zval_ptr(opline, opline->op1_type, &opline->op1, execute_data));
1608 }
1609
1610 EG(current_execute_data) = call;
1611
1613 fbc->internal_function.handler(call, result);
1614 zend_observer_fcall_end(call, result);
1615
1616 EG(current_execute_data) = execute_data;
1617
1618 if (UNEXPECTED(EG(exception) != NULL)) {
1619 zend_rethrow_exception(execute_data);
1620 }
1621
1622 zend_vm_stack_free_args(call);
1623
1624 uint32_t call_info = ZEND_CALL_INFO(call);
1626 zend_vm_stack_free_call_frame_ex(call_info, call);
1627 } else {
1628 EG(vm_stack_top) = (zval*)call;
1629 }
1630}
1631
1632
1633static zend_always_inline int zend_binary_op(zval *ret, zval *op1, zval *op2 OPLINE_DC)
1634{
1635 static const binary_op_type zend_binary_ops[] = {
1648 };
1649 /* size_t cast makes GCC to better optimize 64-bit PIC code */
1650 size_t opcode = (size_t)opline->extended_value;
1651
1652 return zend_binary_ops[opcode - ZEND_ADD](ret, op1, op2);
1653}
1654
1655static zend_never_inline void zend_binary_assign_op_obj_dim(zend_object *obj, zval *property OPLINE_DC EXECUTE_DATA_DC)
1656{
1657 zval *value;
1658 zval *z;
1659 zval rv, res;
1660
1661 GC_ADDREF(obj);
1663 property = ZVAL_UNDEFINED_OP2();
1664 }
1665 value = get_op_data_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1);
1666 if ((z = obj->handlers->read_dimension(obj, property, BP_VAR_R, &rv)) != NULL) {
1667
1668 if (zend_binary_op(&res, z, value OPLINE_CC) == SUCCESS) {
1669 obj->handlers->write_dimension(obj, property, &res);
1670 }
1671 if (z == &rv) {
1672 zval_ptr_dtor(&rv);
1673 }
1674 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1675 ZVAL_COPY(EX_VAR(opline->result.var), &res);
1676 }
1678 } else {
1679 zend_use_object_as_array(obj);
1680 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1681 ZVAL_NULL(EX_VAR(opline->result.var));
1682 }
1683 }
1684 FREE_OP((opline+1)->op1_type, (opline+1)->op1.var);
1685 if (UNEXPECTED(GC_DELREF(obj) == 0)) {
1687 }
1688}
1689
1690static zend_never_inline void zend_binary_assign_op_typed_ref(zend_reference *ref, zval *value OPLINE_DC EXECUTE_DATA_DC)
1691{
1692 zval z_copy;
1693
1694 /* Make sure that in-place concatenation is used if the LHS is a string. */
1695 if (opline->extended_value == ZEND_CONCAT && Z_TYPE(ref->val) == IS_STRING) {
1696 concat_function(&ref->val, &ref->val, value);
1697 ZEND_ASSERT(Z_TYPE(ref->val) == IS_STRING && "Concat should return string");
1698 return;
1699 }
1700
1701 zend_binary_op(&z_copy, &ref->val, value OPLINE_CC);
1703 zval_ptr_dtor(&ref->val);
1704 ZVAL_COPY_VALUE(&ref->val, &z_copy);
1705 } else {
1706 zval_ptr_dtor(&z_copy);
1707 }
1708}
1709
1710static zend_never_inline void zend_binary_assign_op_typed_prop(zend_property_info *prop_info, zval *zptr, zval *value OPLINE_DC EXECUTE_DATA_DC)
1711{
1712 zval z_copy;
1713
1714 /* Make sure that in-place concatenation is used if the LHS is a string. */
1715 if (opline->extended_value == ZEND_CONCAT && Z_TYPE_P(zptr) == IS_STRING) {
1716 concat_function(zptr, zptr, value);
1717 ZEND_ASSERT(Z_TYPE_P(zptr) == IS_STRING && "Concat should return string");
1718 return;
1719 }
1720
1721 zend_binary_op(&z_copy, zptr, value OPLINE_CC);
1723 zval_ptr_dtor(zptr);
1724 ZVAL_COPY_VALUE(zptr, &z_copy);
1725 } else {
1726 zval_ptr_dtor(&z_copy);
1727 }
1728}
1729
1730static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type EXECUTE_DATA_DC)
1731{
1733
1734try_again:
1735 switch(Z_TYPE_P(dim)) {
1736 case IS_LONG:
1737 return Z_LVAL_P(dim);
1738 case IS_STRING:
1739 {
1740 bool trailing_data = false;
1741 /* For BC reasons we allow errors so that we can warn on leading numeric string */
1742 if (IS_LONG == is_numeric_string_ex(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL,
1743 /* allow errors */ true, NULL, &trailing_data)) {
1744 if (UNEXPECTED(trailing_data) && type != BP_VAR_UNSET) {
1745 zend_error(E_WARNING, "Illegal string offset \"%s\"", Z_STRVAL_P(dim));
1746 }
1747 return offset;
1748 }
1749 zend_illegal_string_offset(dim, type);
1750 return 0;
1751 }
1752 case IS_UNDEF:
1755 case IS_DOUBLE:
1756 case IS_NULL:
1757 case IS_FALSE:
1758 case IS_TRUE:
1759 zend_error(E_WARNING, "String offset cast occurred");
1760 break;
1761 case IS_REFERENCE:
1762 dim = Z_REFVAL_P(dim);
1763 goto try_again;
1764 default:
1765 zend_illegal_string_offset(dim, type);
1766 return 0;
1767 }
1768
1769 return zval_get_long_func(dim, /* is_strict */ false);
1770}
1771
1773{
1774 const char *msg = NULL;
1775 const zend_execute_data *execute_data = EG(current_execute_data);
1776 const zend_op *opline = execute_data->opline;
1777
1778 if (UNEXPECTED(EG(exception) != NULL)) {
1779 return;
1780 }
1781
1782 switch (opline->opcode) {
1783 case ZEND_ASSIGN_DIM_OP:
1784 msg = "Cannot use assign-op operators with string offsets";
1785 break;
1786 case ZEND_FETCH_LIST_W:
1787 msg = "Cannot create references to/from string offsets";
1788 break;
1789 case ZEND_FETCH_DIM_W:
1790 case ZEND_FETCH_DIM_RW:
1793 switch (opline->extended_value) {
1794 case ZEND_FETCH_DIM_REF:
1795 msg = "Cannot create references to/from string offsets";
1796 break;
1797 case ZEND_FETCH_DIM_DIM:
1798 msg = "Cannot use string offset as an array";
1799 break;
1800 case ZEND_FETCH_DIM_OBJ:
1801 msg = "Cannot use string offset as an object";
1802 break;
1804 msg = "Cannot increment/decrement string offsets";
1805 break;
1807 }
1808 break;
1810 }
1811 ZEND_ASSERT(msg != NULL);
1812 zend_throw_error(NULL, "%s", msg);
1813}
1814
1815ZEND_COLD static zend_result ZEND_FASTCALL get_deprecation_suffix_from_attribute(HashTable *attributes, zend_class_entry* scope, zend_string **message_suffix)
1816{
1817 *message_suffix = ZSTR_EMPTY_ALLOC();
1818
1819 if (!attributes) {
1820 return SUCCESS;
1821 }
1822
1823 zend_attribute *deprecated = zend_get_attribute_str(attributes, "deprecated", sizeof("deprecated")-1);
1824
1825 if (!deprecated) {
1826 return SUCCESS;
1827 }
1828
1829 if (deprecated->argc == 0) {
1830 return SUCCESS;
1831 }
1832
1834
1835 zend_string *message = ZSTR_EMPTY_ALLOC();
1836 zend_string *since = ZSTR_EMPTY_ALLOC();
1837
1838 zval obj;
1839 ZVAL_UNDEF(&obj);
1840 zval *z;
1841
1842 /* Construct the Deprecated object to correctly handle parameter processing. */
1843 if (FAILURE == zend_get_attribute_object(&obj, zend_ce_deprecated, deprecated, scope, NULL)) {
1844 goto out;
1845 }
1846
1847 /* Extract the $message property. */
1848 z = zend_read_property_ex(zend_ce_deprecated, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_MESSAGE), false, NULL);
1849 ZEND_ASSERT(z != &EG(uninitialized_zval));
1850 if (Z_TYPE_P(z) == IS_STRING) {
1851 message = zend_string_copy(Z_STR_P(z));
1852 }
1853
1854 /* Extract the $since property. */
1855 z = zend_read_property_ex(zend_ce_deprecated, Z_OBJ_P(&obj), ZSTR_KNOWN(ZEND_STR_SINCE), false, NULL);
1856 ZEND_ASSERT(z != &EG(uninitialized_zval));
1857 if (Z_TYPE_P(z) == IS_STRING) {
1858 since = zend_string_copy(Z_STR_P(z));
1859 }
1860
1861 /* Construct the suffix. */
1862 *message_suffix = zend_strpprintf_unchecked(
1863 0,
1864 "%s%S%s%S",
1865 ZSTR_LEN(since) > 0 ? " since " : "",
1866 since,
1867 ZSTR_LEN(message) > 0 ? ", " : "",
1868 message
1869 );
1870
1871 result = SUCCESS;
1872
1873 out:
1874
1875 zend_string_release(since);
1876 zend_string_release(message);
1877 zval_ptr_dtor(&obj);
1878
1879 return result;
1880}
1881
1883{
1884 zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
1885
1886 if (get_deprecation_suffix_from_attribute(fbc->common.attributes, fbc->common.scope, &message_suffix) == FAILURE) {
1887 return;
1888 }
1889
1891
1892 if (fbc->common.scope) {
1893 zend_error_unchecked(code, "Method %s::%s() is deprecated%S",
1894 ZSTR_VAL(fbc->common.scope->name),
1895 ZSTR_VAL(fbc->common.function_name),
1896 message_suffix
1897 );
1898 } else {
1899 zend_error_unchecked(code, "Function %s() is deprecated%S",
1900 ZSTR_VAL(fbc->common.function_name),
1901 message_suffix
1902 );
1903 }
1904
1905 zend_string_release(message_suffix);
1906}
1907
1909{
1910 zend_string *message_suffix = ZSTR_EMPTY_ALLOC();
1911
1912 if (get_deprecation_suffix_from_attribute(c->attributes, c->ce, &message_suffix) == FAILURE) {
1913 return;
1914 }
1915
1917 char *type = (ZEND_CLASS_CONST_FLAGS(c) & ZEND_CLASS_CONST_IS_CASE) ? "Enum case" : "Constant";
1918
1919 zend_error_unchecked(code, "%s %s::%s is deprecated%S",
1920 type,
1921 ZSTR_VAL(c->ce->name),
1922 ZSTR_VAL(constant_name),
1923 message_suffix
1924 );
1925
1926 zend_string_release(message_suffix);
1927}
1928
1930{
1931 zend_error(E_DEPRECATED, "Automatic conversion of false to array is deprecated");
1932}
1933
1934static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
1935{
1936 zend_uchar c;
1937 size_t string_len;
1939 zend_string *s;
1940
1941 /* separate string */
1942 if (Z_REFCOUNTED_P(str) && Z_REFCOUNT_P(str) == 1) {
1943 s = Z_STR_P(str);
1944 } else {
1945 s = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
1946 ZSTR_H(s) = ZSTR_H(Z_STR_P(str));
1947 if (Z_REFCOUNTED_P(str)) {
1948 GC_DELREF(Z_STR_P(str));
1949 }
1950 ZVAL_NEW_STR(str, s);
1951 }
1952
1953 if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
1954 offset = Z_LVAL_P(dim);
1955 } else {
1956 /* The string may be destroyed while throwing the notice.
1957 * Temporarily increase the refcount to detect this situation. */
1958 GC_ADDREF(s);
1959 offset = zend_check_string_offset(dim, BP_VAR_W EXECUTE_DATA_CC);
1960 if (UNEXPECTED(GC_DELREF(s) == 0)) {
1961 zend_string_efree(s);
1962 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1963 ZVAL_NULL(EX_VAR(opline->result.var));
1964 }
1965 return;
1966 }
1967 /* Illegal offset assignment */
1968 if (UNEXPECTED(EG(exception) != NULL)) {
1969 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1970 ZVAL_UNDEF(EX_VAR(opline->result.var));
1971 }
1972 return;
1973 }
1974 }
1975
1976 if (UNEXPECTED(offset < -(zend_long)ZSTR_LEN(s))) {
1977 /* Error on negative offset */
1978 zend_error(E_WARNING, "Illegal string offset " ZEND_LONG_FMT, offset);
1979 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1980 ZVAL_NULL(EX_VAR(opline->result.var));
1981 }
1982 return;
1983 }
1984
1985 if (offset < 0) { /* Handle negative offset */
1987 }
1988
1990 zend_string *tmp;
1991
1992 /* The string may be destroyed while throwing the notice.
1993 * Temporarily increase the refcount to detect this situation. */
1994 GC_ADDREF(s);
1995 if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
1996 zval_undefined_cv((opline+1)->op1.var EXECUTE_DATA_CC);
1997 }
1998 /* Convert to string, just the time to pick the 1st byte */
2000 if (UNEXPECTED(GC_DELREF(s) == 0)) {
2001 zend_string_efree(s);
2002 if (tmp) {
2003 zend_string_release_ex(tmp, 0);
2004 }
2005 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2006 ZVAL_NULL(EX_VAR(opline->result.var));
2007 }
2008 return;
2009 }
2010 if (UNEXPECTED(!tmp)) {
2011 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2012 ZVAL_UNDEF(EX_VAR(opline->result.var));
2013 }
2014 return;
2015 }
2016
2017 string_len = ZSTR_LEN(tmp);
2018 c = (zend_uchar)ZSTR_VAL(tmp)[0];
2019 zend_string_release_ex(tmp, 0);
2020 } else {
2021 string_len = Z_STRLEN_P(value);
2022 c = (zend_uchar)Z_STRVAL_P(value)[0];
2023 }
2024
2025 if (UNEXPECTED(string_len != 1)) {
2026 if (string_len == 0) {
2027 /* Error on empty input string */
2028 zend_throw_error(NULL, "Cannot assign an empty string to a string offset");
2029 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2030 ZVAL_NULL(EX_VAR(opline->result.var));
2031 }
2032 return;
2033 }
2034
2035 /* The string may be destroyed while throwing the notice.
2036 * Temporarily increase the refcount to detect this situation. */
2037 GC_ADDREF(s);
2038 zend_error(E_WARNING, "Only the first byte will be assigned to the string offset");
2039 if (UNEXPECTED(GC_DELREF(s) == 0)) {
2040 zend_string_efree(s);
2041 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2042 ZVAL_NULL(EX_VAR(opline->result.var));
2043 }
2044 return;
2045 }
2046 /* Illegal offset assignment */
2047 if (UNEXPECTED(EG(exception) != NULL)) {
2048 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2049 ZVAL_UNDEF(EX_VAR(opline->result.var));
2050 }
2051 return;
2052 }
2053 }
2054
2055 if ((size_t)offset >= ZSTR_LEN(s)) {
2056 /* Extend string if needed */
2057 zend_long old_len = ZSTR_LEN(s);
2058 ZVAL_NEW_STR(str, zend_string_extend(s, (size_t)offset + 1, 0));
2059 memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
2060 Z_STRVAL_P(str)[offset+1] = 0;
2061 } else {
2062 zend_string_forget_hash_val(Z_STR_P(str));
2063 }
2064
2065 Z_STRVAL_P(str)[offset] = c;
2066
2067 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2068 /* Return the new character */
2069 ZVAL_CHAR(EX_VAR(opline->result.var), c);
2070 }
2071}
2072
2073static zend_property_info *zend_get_prop_not_accepting_double(zend_reference *ref)
2074{
2075 zend_property_info *prop;
2077 if (!(ZEND_TYPE_FULL_MASK(prop->type) & MAY_BE_DOUBLE)) {
2078 return prop;
2079 }
2081 return NULL;
2082}
2083
2084static ZEND_COLD zend_long zend_throw_incdec_ref_error(
2086{
2087 zend_string *type_str = zend_type_to_string(error_prop->type);
2088 if (ZEND_IS_INCREMENT(opline->opcode)) {
2090 "Cannot increment a reference held by property %s::$%s of type %s past its maximal value",
2091 ZSTR_VAL(error_prop->ce->name),
2092 zend_get_unmangled_property_name(error_prop->name),
2093 ZSTR_VAL(type_str));
2094 zend_string_release(type_str);
2095 return ZEND_LONG_MAX;
2096 } else {
2098 "Cannot decrement a reference held by property %s::$%s of type %s past its minimal value",
2099 ZSTR_VAL(error_prop->ce->name),
2100 zend_get_unmangled_property_name(error_prop->name),
2101 ZSTR_VAL(type_str));
2102 zend_string_release(type_str);
2103 return ZEND_LONG_MIN;
2104 }
2105}
2106
2107static ZEND_COLD zend_long zend_throw_incdec_prop_error(zend_property_info *prop OPLINE_DC) {
2108 zend_string *type_str = zend_type_to_string(prop->type);
2109 if (ZEND_IS_INCREMENT(opline->opcode)) {
2110 zend_type_error("Cannot increment property %s::$%s of type %s past its maximal value",
2111 ZSTR_VAL(prop->ce->name),
2112 zend_get_unmangled_property_name(prop->name),
2113 ZSTR_VAL(type_str));
2114 zend_string_release(type_str);
2115 return ZEND_LONG_MAX;
2116 } else {
2117 zend_type_error("Cannot decrement property %s::$%s of type %s past its minimal value",
2118 ZSTR_VAL(prop->ce->name),
2119 zend_get_unmangled_property_name(prop->name),
2120 ZSTR_VAL(type_str));
2121 zend_string_release(type_str);
2122 return ZEND_LONG_MIN;
2123 }
2124}
2125
2126static void zend_incdec_typed_ref(zend_reference *ref, zval *copy OPLINE_DC EXECUTE_DATA_DC)
2127{
2128 zval tmp;
2129 zval *var_ptr = &ref->val;
2130
2131 if (!copy) {
2132 copy = &tmp;
2133 }
2134
2136
2137 if (ZEND_IS_INCREMENT(opline->opcode)) {
2139 } else {
2141 }
2142
2144 zend_property_info *error_prop = zend_get_prop_not_accepting_double(ref);
2145 if (UNEXPECTED(error_prop)) {
2146 zend_long val = zend_throw_incdec_ref_error(ref, error_prop OPLINE_CC);
2148 }
2153 } else if (copy == &tmp) {
2154 zval_ptr_dtor(&tmp);
2155 }
2156}
2157
2158static void zend_incdec_typed_prop(zend_property_info *prop_info, zval *var_ptr, zval *copy OPLINE_DC EXECUTE_DATA_DC)
2159{
2160 zval tmp;
2161
2162 if (!copy) {
2163 copy = &tmp;
2164 }
2165
2167
2168 if (ZEND_IS_INCREMENT(opline->opcode)) {
2170 } else {
2172 }
2173
2176 zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
2178 }
2183 } else if (copy == &tmp) {
2184 zval_ptr_dtor(&tmp);
2185 }
2186}
2187
2188static void zend_pre_incdec_property_zval(zval *prop, zend_property_info *prop_info OPLINE_DC EXECUTE_DATA_DC)
2189{
2190 if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
2191 if (ZEND_IS_INCREMENT(opline->opcode)) {
2192 fast_long_increment_function(prop);
2193 } else {
2194 fast_long_decrement_function(prop);
2195 }
2196 if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && prop_info
2198 zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
2199 ZVAL_LONG(prop, val);
2200 }
2201 } else {
2202 do {
2203 if (Z_ISREF_P(prop)) {
2204 zend_reference *ref = Z_REF_P(prop);
2205 prop = Z_REFVAL_P(prop);
2207 zend_incdec_typed_ref(ref, NULL OPLINE_CC EXECUTE_DATA_CC);
2208 break;
2209 }
2210 }
2211
2212 if (prop_info) {
2213 zend_incdec_typed_prop(prop_info, prop, NULL OPLINE_CC EXECUTE_DATA_CC);
2214 } else if (ZEND_IS_INCREMENT(opline->opcode)) {
2215 increment_function(prop);
2216 } else {
2217 decrement_function(prop);
2218 }
2219 } while (0);
2220 }
2221 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2222 ZVAL_COPY(EX_VAR(opline->result.var), prop);
2223 }
2224}
2225
2226static void zend_post_incdec_property_zval(zval *prop, zend_property_info *prop_info OPLINE_DC EXECUTE_DATA_DC)
2227{
2228 if (EXPECTED(Z_TYPE_P(prop) == IS_LONG)) {
2229 ZVAL_LONG(EX_VAR(opline->result.var), Z_LVAL_P(prop));
2230 if (ZEND_IS_INCREMENT(opline->opcode)) {
2231 fast_long_increment_function(prop);
2232 } else {
2233 fast_long_decrement_function(prop);
2234 }
2235 if (UNEXPECTED(Z_TYPE_P(prop) != IS_LONG) && prop_info
2237 zend_long val = zend_throw_incdec_prop_error(prop_info OPLINE_CC);
2238 ZVAL_LONG(prop, val);
2239 }
2240 } else {
2241 if (Z_ISREF_P(prop)) {
2242 zend_reference *ref = Z_REF_P(prop);
2243 prop = Z_REFVAL_P(prop);
2244 if (ZEND_REF_HAS_TYPE_SOURCES(ref)) {
2245 zend_incdec_typed_ref(ref, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
2246 return;
2247 }
2248 }
2249
2250 if (prop_info) {
2251 zend_incdec_typed_prop(prop_info, prop, EX_VAR(opline->result.var) OPLINE_CC EXECUTE_DATA_CC);
2252 } else {
2253 ZVAL_COPY(EX_VAR(opline->result.var), prop);
2254 if (ZEND_IS_INCREMENT(opline->opcode)) {
2255 increment_function(prop);
2256 } else {
2257 decrement_function(prop);
2258 }
2259 }
2260 }
2261}
2262
2263static zend_never_inline void zend_post_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot OPLINE_DC EXECUTE_DATA_DC)
2264{
2265 zval rv;
2266 zval *z;
2267 zval z_copy;
2268
2269 GC_ADDREF(object);
2270 z =object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv);
2271 if (UNEXPECTED(EG(exception))) {
2272 OBJ_RELEASE(object);
2273 ZVAL_UNDEF(EX_VAR(opline->result.var));
2274 return;
2275 }
2276
2277 ZVAL_COPY_DEREF(&z_copy, z);
2278 ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
2279 if (ZEND_IS_INCREMENT(opline->opcode)) {
2280 increment_function(&z_copy);
2281 } else {
2282 decrement_function(&z_copy);
2283 }
2284 object->handlers->write_property(object, name, &z_copy, cache_slot);
2285 OBJ_RELEASE(object);
2286 zval_ptr_dtor(&z_copy);
2287 if (z == &rv) {
2288 zval_ptr_dtor(z);
2289 }
2290}
2291
2292static zend_never_inline void zend_pre_incdec_overloaded_property(zend_object *object, zend_string *name, void **cache_slot OPLINE_DC EXECUTE_DATA_DC)
2293{
2294 zval rv;
2295 zval *z;
2296 zval z_copy;
2297
2298 GC_ADDREF(object);
2299 z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv);
2300 if (UNEXPECTED(EG(exception))) {
2301 OBJ_RELEASE(object);
2302 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2303 ZVAL_NULL(EX_VAR(opline->result.var));
2304 }
2305 return;
2306 }
2307
2308 ZVAL_COPY_DEREF(&z_copy, z);
2309 if (ZEND_IS_INCREMENT(opline->opcode)) {
2310 increment_function(&z_copy);
2311 } else {
2312 decrement_function(&z_copy);
2313 }
2314 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2315 ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
2316 }
2317 object->handlers->write_property(object, name, &z_copy, cache_slot);
2318 OBJ_RELEASE(object);
2319 zval_ptr_dtor(&z_copy);
2320 if (z == &rv) {
2321 zval_ptr_dtor(z);
2322 }
2323}
2324
2325static zend_never_inline void zend_assign_op_overloaded_property(zend_object *object, zend_string *name, void **cache_slot, zval *value OPLINE_DC EXECUTE_DATA_DC)
2326{
2327 zval *z;
2328 zval rv, res;
2329
2330 GC_ADDREF(object);
2331 z = object->handlers->read_property(object, name, BP_VAR_R, cache_slot, &rv);
2332 if (UNEXPECTED(EG(exception))) {
2333 OBJ_RELEASE(object);
2334 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2335 ZVAL_UNDEF(EX_VAR(opline->result.var));
2336 }
2337 return;
2338 }
2339 if (zend_binary_op(&res, z, value OPLINE_CC) == SUCCESS) {
2340 object->handlers->write_property(object, name, &res, cache_slot);
2341 }
2342 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
2343 ZVAL_COPY(EX_VAR(opline->result.var), &res);
2344 }
2345 if (z == &rv) {
2346 zval_ptr_dtor(z);
2347 }
2349 OBJ_RELEASE(object);
2350}
2351
2352/* Utility Functions for Extensions */
2353static void zend_extension_statement_handler(const zend_extension *extension, zend_execute_data *frame)
2354{
2355 if (extension->statement_handler) {
2356 extension->statement_handler(frame);
2357 }
2358}
2359
2360
2361static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_execute_data *frame)
2362{
2363 if (extension->fcall_begin_handler) {
2364 extension->fcall_begin_handler(frame);
2365 }
2366}
2367
2368
2369static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_execute_data *frame)
2370{
2371 if (extension->fcall_end_handler) {
2372 extension->fcall_end_handler(frame);
2373 }
2374}
2375
2376
2377static zend_always_inline HashTable *zend_get_target_symbol_table(int fetch_type EXECUTE_DATA_DC)
2378{
2379 HashTable *ht;
2380
2381 if (EXPECTED(fetch_type & (ZEND_FETCH_GLOBAL_LOCK | ZEND_FETCH_GLOBAL))) {
2382 ht = &EG(symbol_table);
2383 } else {
2384 ZEND_ASSERT(fetch_type & ZEND_FETCH_LOCAL);
2387 }
2388 ht = EX(symbol_table);
2389 }
2390 return ht;
2391}
2392
2393static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_offset(zend_long lval)
2394{
2395 zend_error(E_WARNING, "Undefined array key " ZEND_LONG_FMT, lval);
2396}
2397
2398static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_index(const zend_string *offset)
2399{
2400 zend_error(E_WARNING, "Undefined array key \"%s\"", ZSTR_VAL(offset));
2401}
2402
2404{
2405 /* The array may be destroyed while throwing the notice.
2406 * Temporarily increase the refcount to detect this situation. */
2407 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2408 GC_ADDREF(ht);
2409 }
2410 zend_undefined_offset(lval);
2411 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2412 if (!GC_REFCOUNT(ht)) {
2414 }
2415 return NULL;
2416 }
2417 if (EG(exception)) {
2418 return NULL;
2419 }
2420 return zend_hash_index_add_new(ht, lval, &EG(uninitialized_zval));
2421}
2422
2424{
2425 zval *retval;
2426
2427 /* The array may be destroyed while throwing the notice.
2428 * Temporarily increase the refcount to detect this situation. */
2429 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2430 GC_ADDREF(ht);
2431 }
2432 /* Key may be released while throwing the undefined index warning. */
2433 zend_string_addref(offset);
2434 zend_undefined_index(offset);
2435 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2436 if (!GC_REFCOUNT(ht)) {
2438 }
2439 retval = NULL;
2440 } else if (EG(exception)) {
2441 retval = NULL;
2442 } else {
2443 retval = zend_hash_add_new(ht, offset, &EG(uninitialized_zval));
2444 }
2445 zend_string_release(offset);
2446 return retval;
2447}
2448
2449static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method)
2450{
2451 zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(method));
2452}
2453
2454static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_invalid_method_call(zval *object, zval *function_name)
2455{
2456 zend_throw_error(NULL, "Call to a member function %s() on %s",
2457 Z_STRVAL_P(function_name), zend_zval_value_name(object));
2458}
2459
2460static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_non_static_method_call(const zend_function *fbc)
2461{
2464 "Non-static method %s::%s() cannot be called statically",
2465 ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
2466}
2467
2469{
2470 const char *arg_name = get_function_arg_name(func, arg_num);
2471
2472 zend_error(E_WARNING, "%s%s%s(): Argument #%d%s%s%s must be passed by reference, value given",
2473 func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
2474 func->common.scope ? "::" : "",
2475 ZSTR_VAL(func->common.function_name),
2476 arg_num,
2477 arg_name ? " ($" : "",
2478 arg_name ? arg_name : "",
2479 arg_name ? ")" : ""
2480 );
2481}
2482
2483static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_scalar_as_array(void)
2484{
2485 zend_throw_error(NULL, "Cannot use a scalar value as an array");
2486}
2487
2489{
2490 zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
2491}
2492
2494{
2496 "Resource ID#" ZEND_LONG_FMT " used as offset, casting to integer (" ZEND_LONG_FMT ")",
2498}
2499
2500static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_string(void)
2501{
2502 zend_throw_error(NULL, "[] operator not supported for strings");
2503}
2504
2505#ifdef ZEND_CHECK_STACK_LIMIT
2507{
2508 size_t max_stack_size = 0;
2509 if ((uintptr_t) EG(stack_base) > (uintptr_t) EG(stack_limit)) {
2510 max_stack_size = (size_t) ((uintptr_t) EG(stack_base) - (uintptr_t) EG(stack_limit));
2511 }
2512
2513 zend_throw_error(NULL, "Maximum call stack size of %zu bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion?",
2514 max_stack_size);
2515}
2516#endif /* ZEND_CHECK_STACK_LIMIT */
2517
2518static ZEND_COLD void zend_binary_assign_op_dim_slow(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
2519{
2521 if (opline->op2_type == IS_UNUSED) {
2522 zend_use_new_element_for_string();
2523 } else {
2524 zend_check_string_offset(dim, BP_VAR_RW EXECUTE_DATA_CC);
2526 }
2527 } else {
2528 zend_use_scalar_as_array();
2529 }
2530}
2531
2532static zend_never_inline uint8_t slow_index_convert(HashTable *ht, const zval *dim, zend_value *value EXECUTE_DATA_DC)
2533{
2534 switch (Z_TYPE_P(dim)) {
2535 case IS_UNDEF: {
2536 /* The array may be destroyed while throwing the notice.
2537 * Temporarily increase the refcount to detect this situation. */
2538 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2539 GC_ADDREF(ht);
2540 }
2542 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2544 return IS_NULL;
2545 }
2546 if (EG(exception)) {
2547 return IS_NULL;
2548 }
2550 }
2551 case IS_NULL:
2552 value->str = ZSTR_EMPTY_ALLOC();
2553 return IS_STRING;
2554 case IS_DOUBLE:
2555 value->lval = zend_dval_to_lval(Z_DVAL_P(dim));
2556 if (!zend_is_long_compatible(Z_DVAL_P(dim), value->lval)) {
2557 /* The array may be destroyed while throwing the notice.
2558 * Temporarily increase the refcount to detect this situation. */
2559 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2560 GC_ADDREF(ht);
2561 }
2563 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2565 return IS_NULL;
2566 }
2567 if (EG(exception)) {
2568 return IS_NULL;
2569 }
2570 }
2571 return IS_LONG;
2572 case IS_RESOURCE:
2573 /* The array may be destroyed while throwing the notice.
2574 * Temporarily increase the refcount to detect this situation. */
2575 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2576 GC_ADDREF(ht);
2577 }
2579 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
2581 return IS_NULL;
2582 }
2583 if (EG(exception)) {
2584 return IS_NULL;
2585 }
2586 value->lval = Z_RES_HANDLE_P(dim);
2587 return IS_LONG;
2588 case IS_FALSE:
2589 value->lval = 0;
2590 return IS_LONG;
2591 case IS_TRUE:
2592 value->lval = 1;
2593 return IS_LONG;
2594 default:
2595 zend_illegal_array_offset_access(dim);
2596 return IS_NULL;
2597 }
2598}
2599
2600static zend_never_inline uint8_t slow_index_convert_w(HashTable *ht, const zval *dim, zend_value *value EXECUTE_DATA_DC)
2601{
2602 switch (Z_TYPE_P(dim)) {
2603 case IS_UNDEF: {
2604 /* The array may be destroyed while throwing the notice.
2605 * Temporarily increase the refcount to detect this situation. */
2606 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2607 GC_ADDREF(ht);
2608 }
2610 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2611 if (!GC_REFCOUNT(ht)) {
2613 }
2614 return IS_NULL;
2615 }
2616 if (EG(exception)) {
2617 return IS_NULL;
2618 }
2620 }
2621 case IS_NULL:
2622 value->str = ZSTR_EMPTY_ALLOC();
2623 return IS_STRING;
2624 case IS_DOUBLE:
2625 value->lval = zend_dval_to_lval(Z_DVAL_P(dim));
2626 if (!zend_is_long_compatible(Z_DVAL_P(dim), value->lval)) {
2627 /* The array may be destroyed while throwing the notice.
2628 * Temporarily increase the refcount to detect this situation. */
2629 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2630 GC_ADDREF(ht);
2631 }
2633 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2634 if (!GC_REFCOUNT(ht)) {
2636 }
2637 return IS_NULL;
2638 }
2639 if (EG(exception)) {
2640 return IS_NULL;
2641 }
2642 }
2643 return IS_LONG;
2644 case IS_RESOURCE:
2645 /* The array may be destroyed while throwing the notice.
2646 * Temporarily increase the refcount to detect this situation. */
2647 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
2648 GC_ADDREF(ht);
2649 }
2651 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
2652 if (!GC_REFCOUNT(ht)) {
2654 }
2655 return IS_NULL;
2656 }
2657 if (EG(exception)) {
2658 return IS_NULL;
2659 }
2660 value->lval = Z_RES_HANDLE_P(dim);
2661 return IS_LONG;
2662 case IS_FALSE:
2663 value->lval = 0;
2664 return IS_LONG;
2665 case IS_TRUE:
2666 value->lval = 1;
2667 return IS_LONG;
2668 default:
2669 zend_illegal_array_offset_access(dim);
2670 return IS_NULL;
2671 }
2672}
2673
2674static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type EXECUTE_DATA_DC)
2675{
2676 zval *retval = NULL;
2677 zend_string *offset_key;
2678 zend_ulong hval;
2679
2680try_again:
2681 if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
2682 hval = Z_LVAL_P(dim);
2683num_index:
2684 if (type != BP_VAR_W) {
2685 ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
2686 return retval;
2687num_undef:
2688 switch (type) {
2689 case BP_VAR_R:
2690 zend_undefined_offset(hval);
2692 case BP_VAR_UNSET:
2693 case BP_VAR_IS:
2694 retval = &EG(uninitialized_zval);
2695 break;
2696 case BP_VAR_RW:
2698 break;
2699 }
2700 } else {
2702 }
2703 } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
2704 offset_key = Z_STR_P(dim);
2705 if (ZEND_CONST_COND(dim_type != IS_CONST, 1)) {
2706 if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
2707 goto num_index;
2708 }
2709 }
2710str_index:
2711 if (type != BP_VAR_W) {
2712 retval = zend_hash_find_ex(ht, offset_key, ZEND_CONST_COND(dim_type == IS_CONST, 0));
2713 if (!retval) {
2714 switch (type) {
2715 case BP_VAR_R:
2716 zend_undefined_index(offset_key);
2718 case BP_VAR_UNSET:
2719 case BP_VAR_IS:
2720 retval = &EG(uninitialized_zval);
2721 break;
2722 case BP_VAR_RW:
2723 retval = zend_undefined_index_write(ht, offset_key);
2724 break;
2725 }
2726 }
2727 } else {
2728 retval = zend_hash_lookup(ht, offset_key);
2729 }
2730 } else if (EXPECTED(Z_TYPE_P(dim) == IS_REFERENCE)) {
2731 dim = Z_REFVAL_P(dim);
2732 goto try_again;
2733 } else {
2735 uint8_t t;
2736
2737 if (type != BP_VAR_W && type != BP_VAR_RW) {
2738 t = slow_index_convert(ht, dim, &val EXECUTE_DATA_CC);
2739 } else {
2740 t = slow_index_convert_w(ht, dim, &val EXECUTE_DATA_CC);
2741 }
2742 if (t == IS_STRING) {
2743 offset_key = val.str;
2744 goto str_index;
2745 } else if (t == IS_LONG) {
2746 hval = val.lval;
2747 goto num_index;
2748 } else {
2749 retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
2750 NULL : &EG(uninitialized_zval);
2751 }
2752 }
2753 return retval;
2754}
2755
2756static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2757{
2758 return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_W EXECUTE_DATA_CC);
2759}
2760
2761static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2762{
2763 return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_W EXECUTE_DATA_CC);
2764}
2765
2766static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2767{
2768 return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_RW EXECUTE_DATA_CC);
2769}
2770
2771static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
2772{
2773 return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_RW EXECUTE_DATA_CC);
2774}
2775
2776static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type EXECUTE_DATA_DC)
2777{
2778 zval *retval;
2779
2781try_array:
2783fetch_from_array:
2784 if (dim == NULL) {
2785 retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
2786 if (UNEXPECTED(retval == NULL)) {
2789 return;
2790 }
2791 } else {
2792 retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
2793 if (UNEXPECTED(!retval)) {
2794 /* This may fail without throwing if the array was modified while throwing an
2795 * undefined index error. */
2797 return;
2798 }
2799 }
2801 return;
2802 } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
2806 goto try_array;
2807 } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
2808 if (type != BP_VAR_UNSET) {
2809 if (ZEND_REF_HAS_TYPE_SOURCES(ref)) {
2812 return;
2813 }
2814 }
2816 goto fetch_from_array;
2817 } else {
2818 goto return_null;
2819 }
2820 }
2821 }
2823 if (dim == NULL) {
2824 zend_use_new_element_for_string();
2825 } else {
2826 zend_check_string_offset(dim, type EXECUTE_DATA_CC);
2828 }
2830 } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2832 GC_ADDREF(obj);
2833 if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
2835 } else if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
2836 dim++;
2837 }
2838 retval = obj->handlers->read_dimension(obj, dim, type, result);
2839
2840 if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
2841 zend_class_entry *ce = obj->ce;
2842
2844 zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
2845 } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
2846 if (!Z_ISREF_P(retval)) {
2847 if (result != retval) {
2849 retval = result;
2850 }
2851 if (Z_TYPE_P(retval) != IS_OBJECT) {
2852 zend_class_entry *ce = obj->ce;
2853 zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
2854 }
2855 } else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
2857 }
2858 if (result != retval) {
2860 }
2861 } else {
2862 ZEND_ASSERT(EG(exception) && "read_dimension() returned NULL without exception");
2864 }
2865 if (UNEXPECTED(GC_DELREF(obj) == 0)) {
2867 }
2868 } else {
2872 }
2873 if (type != BP_VAR_UNSET) {
2875 uint8_t old_type = Z_TYPE_P(container);
2876
2878 if (UNEXPECTED(old_type == IS_FALSE)) {
2879 GC_ADDREF(ht);
2881 if (UNEXPECTED(GC_DELREF(ht) == 0)) {
2883 goto return_null;
2884 }
2885 }
2886 goto fetch_from_array;
2887 } else {
2890 }
2891return_null:
2892 /* for read-mode only */
2893 if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
2895 }
2897 }
2898 } else {
2899 if (type == BP_VAR_UNSET) {
2900 zend_throw_error(NULL, "Cannot unset offset in a non-array variable");
2902 } else {
2903 zend_use_scalar_as_array();
2905 }
2906 }
2907 }
2908}
2909
2910static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_W(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
2911{
2912 zval *result = EX_VAR(opline->result.var);
2913 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W EXECUTE_DATA_CC);
2914}
2915
2916static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_RW(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
2917{
2918 zval *result = EX_VAR(opline->result.var);
2919 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW EXECUTE_DATA_CC);
2920}
2921
2922static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_UNSET(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
2923{
2924 zval *result = EX_VAR(opline->result.var);
2925 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET EXECUTE_DATA_CC);
2926}
2927
2928static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, bool is_list, int slow EXECUTE_DATA_DC)
2929{
2930 zval *retval;
2931
2932 if (!slow) {
2934try_array:
2935 retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
2937 return;
2938 } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
2941 goto try_array;
2942 }
2943 }
2944 }
2945 if (!is_list && EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
2948
2949try_string_offset:
2950 if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
2951 switch (Z_TYPE_P(dim)) {
2952 case IS_STRING:
2953 {
2954 bool trailing_data = false;
2955 /* For BC reasons we allow errors so that we can warn on leading numeric string */
2956 if (IS_LONG == is_numeric_string_ex(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset,
2957 NULL, /* allow errors */ true, NULL, &trailing_data)) {
2958 if (UNEXPECTED(trailing_data)) {
2959 zend_error(E_WARNING, "Illegal string offset \"%s\"", Z_STRVAL_P(dim));
2960 }
2961 goto out;
2962 }
2963 if (type == BP_VAR_IS) {
2965 return;
2966 }
2967 zend_illegal_string_offset(dim, BP_VAR_R);
2969 return;
2970 }
2971 case IS_UNDEF:
2972 /* The string may be destroyed while throwing the notice.
2973 * Temporarily increase the refcount to detect this situation. */
2974 if (!(GC_FLAGS(str) & IS_STR_INTERNED)) {
2975 GC_ADDREF(str);
2976 }
2978 if (!(GC_FLAGS(str) & IS_STR_INTERNED) && UNEXPECTED(GC_DELREF(str) == 0)) {
2979 zend_string_efree(str);
2981 return;
2982 }
2984 case IS_DOUBLE:
2985 case IS_NULL:
2986 case IS_FALSE:
2987 case IS_TRUE:
2988 if (type != BP_VAR_IS) {
2989 /* The string may be destroyed while throwing the notice.
2990 * Temporarily increase the refcount to detect this situation. */
2991 if (!(GC_FLAGS(str) & IS_STR_INTERNED)) {
2992 GC_ADDREF(str);
2993 }
2994 zend_error(E_WARNING, "String offset cast occurred");
2995 if (!(GC_FLAGS(str) & IS_STR_INTERNED) && UNEXPECTED(GC_DELREF(str) == 0)) {
2996 zend_string_efree(str);
2998 return;
2999 }
3000 }
3001 break;
3002 case IS_REFERENCE:
3003 dim = Z_REFVAL_P(dim);
3004 goto try_string_offset;
3005 default:
3006 zend_illegal_string_offset(dim, BP_VAR_R);
3008 return;
3009 }
3010
3011 offset = zval_get_long_func(dim, /* is_strict */ false);
3012 } else {
3013 offset = Z_LVAL_P(dim);
3014 }
3015 out:
3016
3017 if (UNEXPECTED(ZSTR_LEN(str) < ((offset < 0) ? -(size_t)offset : ((size_t)offset + 1)))) {
3018 if (type != BP_VAR_IS) {
3019 zend_error(E_WARNING, "Uninitialized string offset " ZEND_LONG_FMT, offset);
3021 } else {
3023 }
3024 } else {
3025 zend_uchar c;
3026 zend_long real_offset;
3027
3028 real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
3029 ? (zend_long)ZSTR_LEN(str) + offset : offset;
3030 c = (zend_uchar)ZSTR_VAL(str)[real_offset];
3031
3032 ZVAL_CHAR(result, c);
3033 }
3034 } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
3036
3037 GC_ADDREF(obj);
3038 if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
3040 }
3041 if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
3042 dim++;
3043 }
3044 retval = obj->handlers->read_dimension(obj, dim, type, result);
3045
3047 if (retval) {
3048 if (result != retval) {
3050 } else if (UNEXPECTED(Z_ISREF_P(retval))) {
3051 zend_unwrap_reference(result);
3052 }
3053 } else {
3055 }
3056 if (UNEXPECTED(GC_DELREF(obj) == 0)) {
3058 }
3059 } else {
3062 }
3063 if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
3065 }
3066 if (!is_list && type != BP_VAR_IS) {
3067 zend_error(E_WARNING, "Trying to access array offset on %s",
3069 }
3071 }
3072}
3073
3074static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_read_R(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3075{
3076 zval *result = EX_VAR(opline->result.var);
3077 zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 0, 0 EXECUTE_DATA_CC);
3078}
3079
3080static zend_never_inline void zend_fetch_dimension_address_read_R_slow(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
3081{
3082 zval *result = EX_VAR(opline->result.var);
3083 zend_fetch_dimension_address_read(result, container, dim, IS_CV, BP_VAR_R, 0, 1 EXECUTE_DATA_CC);
3084}
3085
3086static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_read_IS(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3087{
3088 zval *result = EX_VAR(opline->result.var);
3089 zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 0, 0 EXECUTE_DATA_CC);
3090}
3091
3092static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_LIST_r(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
3093{
3094 zval *result = EX_VAR(opline->result.var);
3095 zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1, 0 EXECUTE_DATA_CC);
3096}
3097
3099{
3100 zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, type, 0, 0 NO_EXECUTE_DATA_CC);
3101}
3102
3103static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable *ht, zval *offset EXECUTE_DATA_DC)
3104{
3105 zend_ulong hval;
3106
3107 if (Z_TYPE_P(offset) == IS_DOUBLE) {
3108 hval = zend_dval_to_lval_safe(Z_DVAL_P(offset));
3109num_idx:
3110 return zend_hash_index_find(ht, hval);
3111 } else if (Z_TYPE_P(offset) == IS_NULL) {
3112str_idx:
3114 } else if (Z_TYPE_P(offset) == IS_FALSE) {
3115 hval = 0;
3116 goto num_idx;
3117 } else if (Z_TYPE_P(offset) == IS_TRUE) {
3118 hval = 1;
3119 goto num_idx;
3120 } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
3122 hval = Z_RES_HANDLE_P(offset);
3123 goto num_idx;
3124 } else if (/*OP2_TYPE == IS_CV &&*/ Z_TYPE_P(offset) == IS_UNDEF) {
3126 goto str_idx;
3127 } else {
3128 zend_illegal_array_offset_isset(offset);
3129 return NULL;
3130 }
3131}
3132
3133static zend_never_inline bool ZEND_FASTCALL zend_isset_dim_slow(zval *container, zval *offset EXECUTE_DATA_DC)
3134{
3135 if (/*OP2_TYPE == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
3137 }
3138
3139 if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
3140 return Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 0);
3141 } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
3142 zend_long lval;
3143
3144 if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
3145 lval = Z_LVAL_P(offset);
3146str_offset:
3147 if (UNEXPECTED(lval < 0)) { /* Handle negative offset */
3148 lval += (zend_long)Z_STRLEN_P(container);
3149 }
3150 if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
3151 return 1;
3152 } else {
3153 return 0;
3154 }
3155 } else {
3156 /*if (OP2_TYPE & (IS_CV|IS_VAR)) {*/
3158 /*}*/
3159 if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
3160 || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
3161 && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
3162 lval = zval_get_long_ex(offset, /* is_strict */ true);
3163 goto str_offset;
3164 }
3165 return 0;
3166 }
3167 } else {
3168 return 0;
3169 }
3170}
3171
3172static zend_never_inline bool ZEND_FASTCALL zend_isempty_dim_slow(zval *container, zval *offset EXECUTE_DATA_DC)
3173{
3174 if (/*OP2_TYPE == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
3176 }
3177
3178 if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
3179 return !Z_OBJ_HT_P(container)->has_dimension(Z_OBJ_P(container), offset, 1);
3180 } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
3181 zend_long lval;
3182
3183 if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
3184 lval = Z_LVAL_P(offset);
3185str_offset:
3186 if (UNEXPECTED(lval < 0)) { /* Handle negative offset */
3187 lval += (zend_long)Z_STRLEN_P(container);
3188 }
3189 if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
3190 return (Z_STRVAL_P(container)[lval] == '0');
3191 } else {
3192 return 1;
3193 }
3194 } else {
3195 /*if (OP2_TYPE & (IS_CV|IS_VAR)) {*/
3197 /*}*/
3198 if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
3199 || (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
3200 && IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
3201 lval = zval_get_long_ex(offset, /* is_strict */ true);
3202 goto str_offset;
3203 }
3204 return 1;
3205 }
3206 } else {
3207 return 1;
3208 }
3209}
3210
3211static zend_never_inline bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC)
3212{
3213 zend_string *str;
3214 zend_ulong hval;
3215
3216try_again:
3217 if (EXPECTED(Z_TYPE_P(key) == IS_STRING)) {
3218 str = Z_STR_P(key);
3219 if (ZEND_HANDLE_NUMERIC(str, hval)) {
3220 goto num_key;
3221 }
3222str_key:
3223 return zend_hash_exists(ht, str);
3224 } else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) {
3225 hval = Z_LVAL_P(key);
3226num_key:
3227 return zend_hash_index_exists(ht, hval);
3228 } else if (EXPECTED(Z_ISREF_P(key))) {
3229 key = Z_REFVAL_P(key);
3230 goto try_again;
3231 } else if (Z_TYPE_P(key) == IS_DOUBLE) {
3232 hval = zend_dval_to_lval_safe(Z_DVAL_P(key));
3233 goto num_key;
3234 } else if (Z_TYPE_P(key) == IS_FALSE) {
3235 hval = 0;
3236 goto num_key;
3237 } else if (Z_TYPE_P(key) == IS_TRUE) {
3238 hval = 1;
3239 goto num_key;
3240 } else if (Z_TYPE_P(key) == IS_RESOURCE) {
3242 hval = Z_RES_HANDLE_P(key);
3243 goto num_key;
3244 } else if (Z_TYPE_P(key) <= IS_NULL) {
3245 if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) {
3247 }
3248 str = ZSTR_EMPTY_ALLOC();
3249 goto str_key;
3250 } else {
3251 zend_illegal_array_offset_access(key);
3252 return 0;
3253 }
3254}
3255
3256static ZEND_COLD void ZEND_FASTCALL zend_array_key_exists_error(
3258{
3259 if (Z_TYPE_P(key) == IS_UNDEF) {
3261 }
3262 if (Z_TYPE_P(subject) == IS_UNDEF) {
3264 }
3265 if (!EG(exception)) {
3266 zend_type_error("array_key_exists(): Argument #2 ($array) must be of type array, %s given",
3267 zend_zval_value_name(subject));
3268 }
3269}
3270
3271static zend_always_inline bool promotes_to_array(zval *val) {
3272 return Z_TYPE_P(val) <= IS_FALSE
3274}
3275
3276static zend_always_inline bool check_type_array_assignable(zend_type type) {
3277 if (!ZEND_TYPE_IS_SET(type)) {
3278 return 1;
3279 }
3280 return (ZEND_TYPE_FULL_MASK(type) & MAY_BE_ARRAY) != 0;
3281}
3282
3283/* Checks whether an array can be assigned to the reference. Throws error if not assignable. */
3285 zend_property_info *prop;
3288 if (!check_type_array_assignable(prop->type)) {
3289 zend_throw_auto_init_in_ref_error(prop);
3290 return 0;
3291 }
3293 return 1;
3294}
3295
3296static zend_never_inline bool zend_handle_fetch_obj_flags(
3298{
3299 switch (flags) {
3301 if (promotes_to_array(ptr)) {
3302 if (!prop_info) {
3303 break;
3304 }
3305 if (!check_type_array_assignable(prop_info->type)) {
3306 zend_throw_auto_init_in_prop_error(prop_info);
3307 if (result) ZVAL_ERROR(result);
3308 return 0;
3309 }
3310 }
3311 break;
3312 case ZEND_FETCH_REF:
3313 if (Z_TYPE_P(ptr) != IS_REFERENCE) {
3314 if (!prop_info) {
3315 break;
3316 }
3317 if (Z_TYPE_P(ptr) == IS_UNDEF) {
3318 if (!ZEND_TYPE_ALLOW_NULL(prop_info->type)) {
3319 zend_throw_access_uninit_prop_by_ref_error(prop_info);
3320 if (result) ZVAL_ERROR(result);
3321 return 0;
3322 }
3323 ZVAL_NULL(ptr);
3324 }
3325
3328 }
3329 break;
3331 }
3332 return 1;
3333}
3334
3335static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, zend_property_info **prop_info_p OPLINE_DC EXECUTE_DATA_DC)
3336{
3337 zval *ptr;
3340 void *_cache_slot[3] = {0};
3341 if (prop_op_type != IS_CONST) {
3342 cache_slot = _cache_slot;
3343 } else {
3344 ZEND_ASSERT(cache_slot);
3345 }
3346
3347 if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
3348 do {
3351 break;
3352 }
3353
3354 if (container_op_type == IS_CV
3355 && type != BP_VAR_W
3358 }
3359
3360 /* this should modify object only if it's empty */
3361 if (type == BP_VAR_UNSET) {
3363 return;
3364 }
3365
3366 zend_throw_non_object_error(container, prop_ptr OPLINE_CC EXECUTE_DATA_CC);
3368 return;
3369 } while (0);
3370 }
3371
3373 if (prop_op_type == IS_CONST &&
3374 EXPECTED(zobj->ce == CACHED_PTR_EX(cache_slot))) {
3375 uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
3376 if (prop_info_p) {
3377 *prop_info_p = CACHED_PTR_EX(cache_slot + 2);
3378 }
3379
3380 if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
3381 ptr = OBJ_PROP(zobj, prop_offset);
3382 if (EXPECTED(Z_TYPE_P(ptr) != IS_UNDEF)) {
3384 zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
3385 if (prop_info) {
3388 /* For objects, W/RW/UNSET fetch modes might not actually modify object.
3389 * Similar as with magic __get() allow them, but return the value as a copy
3390 * to make sure no actual modification is possible. */
3392 if (Z_TYPE_P(ptr) == IS_OBJECT) {
3394 } else {
3395 if (prop_info->flags & ZEND_ACC_READONLY) {
3397 } else {
3399 }
3401 }
3402 return;
3403 }
3405 if (flags) {
3406 zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags);
3407 }
3408 }
3409 return;
3410 }
3411 } else if (UNEXPECTED(IS_HOOKED_PROPERTY_OFFSET(prop_offset))) {
3412 /* Fall through to read_property for hooks. */
3413 } else if (EXPECTED(zobj->properties != NULL)) {
3415 if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
3416 if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
3417 GC_DELREF(zobj->properties);
3418 }
3419 zobj->properties = zend_array_dup(zobj->properties);
3420 }
3421 ptr = zend_hash_find_known_hash(zobj->properties, Z_STR_P(prop_ptr));
3422 if (EXPECTED(ptr)) {
3424 return;
3425 }
3426 }
3427 } else if (prop_op_type == IS_CONST) {
3428 /* CE mismatch, make cache slot consistent */
3429 cache_slot[0] = cache_slot[1] = cache_slot[2] = NULL;
3430 }
3431
3432 /* Pointer on property callback is required */
3433 ZEND_ASSERT(zobj->handlers->get_property_ptr_ptr != NULL);
3434
3435 if (prop_op_type == IS_CONST) {
3436 name = Z_STR_P(prop_ptr);
3437 } else {
3438 name = zval_get_tmp_string(prop_ptr, &tmp_name);
3439 }
3440 ptr = zobj->handlers->get_property_ptr_ptr(zobj, name, type, cache_slot);
3441 if (NULL == ptr) {
3442 ptr = zobj->handlers->read_property(zobj, name, type, cache_slot, result);
3443 if (ptr == result) {
3444 if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
3445 ZVAL_UNREF(ptr);
3446 }
3447 goto end;
3448 }
3449 if (UNEXPECTED(EG(exception))) {
3451 goto end;
3452 }
3453 } else if (UNEXPECTED(Z_ISERROR_P(ptr))) {
3455 goto end;
3456 }
3457
3460 if (flags) {
3461 zend_property_info *prop_info = CACHED_PTR_EX(cache_slot + 2);
3462 if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
3463 if (UNEXPECTED(!zend_handle_fetch_obj_flags(result, ptr, NULL, prop_info, flags))) {
3464 goto end;
3465 }
3466 }
3467 }
3468
3469end:
3470 if (prop_info_p) {
3471 *prop_info_p = CACHED_PTR_EX(cache_slot + 2);
3472 }
3473 if (prop_op_type != IS_CONST) {
3474 zend_tmp_string_release(tmp_name);
3475 }
3476}
3477
3478static zend_always_inline void zend_assign_to_property_reference(zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3479{
3480 zval variable, *variable_ptr = &variable;
3481 void **cache_addr = (prop_op_type == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_RETURNS_FUNCTION) : NULL;
3484
3485 zend_fetch_property_address(variable_ptr, container, container_op_type, prop_ptr, prop_op_type,
3486 cache_addr, BP_VAR_W, 0, &prop_info OPLINE_CC EXECUTE_DATA_CC);
3487
3490 if (/*OP_DATA_TYPE == IS_VAR &&*/
3491 (opline->extended_value & ZEND_RETURNS_FUNCTION) &&
3493
3494 variable_ptr = zend_wrong_assign_to_variable_reference(
3496 } else if (prop_info && ZEND_TYPE_IS_SET(prop_info->type)) {
3497 variable_ptr = zend_assign_to_typed_property_reference(prop_info, variable_ptr, value_ptr, &garbage EXECUTE_DATA_CC);
3498 } else {
3499 zend_assign_to_variable_reference(variable_ptr, value_ptr, &garbage);
3500 }
3501 } else if (Z_ISERROR_P(variable_ptr)) {
3502 variable_ptr = &EG(uninitialized_zval);
3503 } else {
3504 zend_throw_error(NULL, "Cannot assign by reference to overloaded object");
3505 zval_ptr_dtor(&variable);
3506 variable_ptr = &EG(uninitialized_zval);
3507 }
3508
3509 if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
3510 ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
3511 }
3512 if (garbage) {
3514 }
3515}
3516
3517static zend_never_inline void zend_assign_to_property_reference_this_const(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3518{
3519 zend_assign_to_property_reference(container, IS_UNUSED, prop_ptr, IS_CONST, value_ptr
3521}
3522
3523static zend_never_inline void zend_assign_to_property_reference_var_const(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3524{
3525 zend_assign_to_property_reference(container, IS_VAR, prop_ptr, IS_CONST, value_ptr
3527}
3528
3529static zend_never_inline void zend_assign_to_property_reference_this_var(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3530{
3531 zend_assign_to_property_reference(container, IS_UNUSED, prop_ptr, IS_VAR, value_ptr
3533}
3534
3535static zend_never_inline void zend_assign_to_property_reference_var_var(zval *container, zval *prop_ptr, zval *value_ptr OPLINE_DC EXECUTE_DATA_DC)
3536{
3537 zend_assign_to_property_reference(container, IS_VAR, prop_ptr, IS_VAR, value_ptr
3539}
3540
3541static zend_never_inline zend_result zend_fetch_static_property_address_ex(zval **retval, zend_property_info **prop_info, uint32_t cache_slot, int fetch_type OPLINE_DC EXECUTE_DATA_DC) {
3543 zend_class_entry *ce;
3544 zend_property_info *property_info;
3545
3546 uint8_t op1_type = opline->op1_type, op2_type = opline->op2_type;
3547
3548 if (EXPECTED(op2_type == IS_CONST)) {
3549 zval *class_name = RT_CONSTANT(opline, opline->op2);
3550
3551 ZEND_ASSERT(op1_type != IS_CONST || CACHED_PTR(cache_slot) == NULL);
3552
3553 if (EXPECTED((ce = CACHED_PTR(cache_slot)) == NULL)) {
3555 if (UNEXPECTED(ce == NULL)) {
3556 FREE_OP(op1_type, opline->op1.var);
3557 return FAILURE;
3558 }
3559 if (UNEXPECTED(op1_type != IS_CONST)) {
3560 CACHE_PTR(cache_slot, ce);
3561 }
3562 }
3563 } else {
3564 if (EXPECTED(op2_type == IS_UNUSED)) {
3565 ce = zend_fetch_class(NULL, opline->op2.num);
3566 if (UNEXPECTED(ce == NULL)) {
3567 FREE_OP(op1_type, opline->op1.var);
3568 return FAILURE;
3569 }
3570 } else {
3571 ce = Z_CE_P(EX_VAR(opline->op2.var));
3572 }
3573 if (EXPECTED(op1_type == IS_CONST) && EXPECTED(CACHED_PTR(cache_slot) == ce)) {
3574 *retval = CACHED_PTR(cache_slot + sizeof(void *));
3575 *prop_info = CACHED_PTR(cache_slot + sizeof(void *) * 2);
3576 return SUCCESS;
3577 }
3578 }
3579
3580 if (EXPECTED(op1_type == IS_CONST)) {
3581 name = Z_STR_P(RT_CONSTANT(opline, opline->op1));
3582 *retval = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info);
3583 } else {
3585 zval *varname = get_zval_ptr_undef(opline->op1_type, opline->op1, BP_VAR_R);
3586 if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
3587 name = Z_STR_P(varname);
3588 tmp_name = NULL;
3589 } else {
3590 if (op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
3591 zval_undefined_cv(opline->op1.var EXECUTE_DATA_CC);
3592 }
3593 name = zval_get_tmp_string(varname, &tmp_name);
3594 }
3595 *retval = zend_std_get_static_property_with_info(ce, name, fetch_type, &property_info);
3596
3597 zend_tmp_string_release(tmp_name);
3598
3599 FREE_OP(op1_type, opline->op1.var);
3600 }
3601
3602 if (UNEXPECTED(*retval == NULL)) {
3603 return FAILURE;
3604 }
3605
3606 *prop_info = property_info;
3607
3608 if (EXPECTED(op1_type == IS_CONST)
3609 && EXPECTED(!(property_info->ce->ce_flags & ZEND_ACC_TRAIT))) {
3610 CACHE_POLYMORPHIC_PTR(cache_slot, ce, *retval);
3611 CACHE_PTR(cache_slot + sizeof(void *) * 2, property_info);
3612 }
3613
3614 return SUCCESS;
3615}
3616
3617
3618static zend_always_inline zend_result zend_fetch_static_property_address(zval **retval, zend_property_info **prop_info, uint32_t cache_slot, int fetch_type, int flags OPLINE_DC EXECUTE_DATA_DC) {
3619 zend_property_info *property_info;
3620
3621 if (opline->op1_type == IS_CONST
3622 && (opline->op2_type == IS_CONST
3623 || (opline->op2_type == IS_UNUSED
3624 && ((opline->op2.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF
3625 || (opline->op2.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT)))
3626 && EXPECTED(CACHED_PTR(cache_slot) != NULL)) {
3627 *retval = CACHED_PTR(cache_slot + sizeof(void *));
3628 property_info = CACHED_PTR(cache_slot + sizeof(void *) * 2);
3629
3630 if ((fetch_type == BP_VAR_R || fetch_type == BP_VAR_RW)
3632 && ZEND_TYPE_IS_SET(property_info->type)) {
3633 zend_throw_error(NULL, "Typed static property %s::$%s must not be accessed before initialization",
3634 ZSTR_VAL(property_info->ce->name),
3635 zend_get_unmangled_property_name(property_info->name));
3636 return FAILURE;
3637 }
3638 } else {
3639 zend_result success;
3640 success = zend_fetch_static_property_address_ex(retval, &property_info, cache_slot, fetch_type OPLINE_CC EXECUTE_DATA_CC);
3641 if (UNEXPECTED(success != SUCCESS)) {
3642 return FAILURE;
3643 }
3644 }
3645
3647 if (flags && ZEND_TYPE_IS_SET(property_info->type)) {
3648 zend_handle_fetch_obj_flags(NULL, *retval, NULL, property_info, flags);
3649 }
3650
3651 if (prop_info) {
3652 *prop_info = property_info;
3653 }
3654
3655 return SUCCESS;
3656}
3657
3659 zend_string *type1_str = zend_type_to_string(prop1->type);
3660 zend_string *type2_str = zend_type_to_string(prop2->type);
3661 zend_type_error("Reference with value of type %s held by property %s::$%s of type %s is not compatible with property %s::$%s of type %s",
3663 ZSTR_VAL(prop1->ce->name),
3664 zend_get_unmangled_property_name(prop1->name),
3665 ZSTR_VAL(type1_str),
3666 ZSTR_VAL(prop2->ce->name),
3667 zend_get_unmangled_property_name(prop2->name),
3668 ZSTR_VAL(type2_str)
3669 );
3670 zend_string_release(type1_str);
3671 zend_string_release(type2_str);
3672}
3673
3675 zend_string *type_str = zend_type_to_string(prop->type);
3676 zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s",
3678 ZSTR_VAL(prop->ce->name),
3679 zend_get_unmangled_property_name(prop->name),
3680 ZSTR_VAL(type_str)
3681 );
3682 zend_string_release(type_str);
3683}
3684
3686 zend_string *type1_str = zend_type_to_string(prop1->type);
3687 zend_string *type2_str = zend_type_to_string(prop2->type);
3688 zend_type_error("Cannot assign %s to reference held by property %s::$%s of type %s and property %s::$%s of type %s, as this would result in an inconsistent type conversion",
3690 ZSTR_VAL(prop1->ce->name),
3691 zend_get_unmangled_property_name(prop1->name),
3692 ZSTR_VAL(type1_str),
3693 ZSTR_VAL(prop2->ce->name),
3694 zend_get_unmangled_property_name(prop2->name),
3695 ZSTR_VAL(type2_str)
3696 );
3697 zend_string_release(type1_str);
3698 zend_string_release(type2_str);
3699}
3700
3701/* 1: valid, 0: invalid, -1: may be valid after type coercion */
3702static zend_always_inline int i_zend_verify_type_assignable_zval(
3703 const zend_property_info *info, const zval *zv, bool strict) {
3704 zend_type type = info->type;
3705 uint32_t type_mask;
3706 uint8_t zv_type = Z_TYPE_P(zv);
3707
3708 if (EXPECTED(ZEND_TYPE_CONTAINS_CODE(type, zv_type))) {
3709 return 1;
3710 }
3711
3712 if (ZEND_TYPE_IS_COMPLEX(type) && zv_type == IS_OBJECT
3713 && zend_check_and_resolve_property_or_class_constant_class_type(info->ce, info->type, Z_OBJCE_P(zv))) {
3714 return 1;
3715 }
3716
3717 type_mask = ZEND_TYPE_FULL_MASK(type);
3718 ZEND_ASSERT(!(type_mask & (MAY_BE_CALLABLE|MAY_BE_STATIC)));
3719
3720 /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
3721 if (strict) {
3722 if ((type_mask & MAY_BE_DOUBLE) && zv_type == IS_LONG) {
3723 return -1;
3724 }
3725 return 0;
3726 }
3727
3728 /* NULL may be accepted only by nullable hints (this is already checked) */
3729 if (zv_type == IS_NULL) {
3730 return 0;
3731 }
3732
3733 /* Does not contain any type to which a coercion is possible */
3734 if (!(type_mask & (MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING))
3735 && (type_mask & MAY_BE_BOOL) != MAY_BE_BOOL) {
3736 return 0;
3737 }
3738
3739 /* Coercion may be necessary, check separately */
3740 return -1;
3741}
3742
3744{
3745 const zend_property_info *prop;
3746
3747 /* The value must satisfy each property type, and coerce to the same value for each property
3748 * type. Remember the first coerced type and value we've seen for this purpose. */
3749 const zend_property_info *first_prop = NULL;
3750 zval coerced_value;
3751 ZVAL_UNDEF(&coerced_value);
3752
3755 int result = i_zend_verify_type_assignable_zval(prop, zv, strict);
3756 if (result == 0) {
3757type_error:
3759 zval_ptr_dtor(&coerced_value);
3760 return 0;
3761 }
3762
3763 if (result < 0) {
3764 if (!first_prop) {
3765 first_prop = prop;
3766 ZVAL_COPY(&coerced_value, zv);
3767 if (!zend_verify_weak_scalar_type_hint(
3768 ZEND_TYPE_FULL_MASK(prop->type), &coerced_value)) {
3769 goto type_error;
3770 }
3771 } else if (Z_ISUNDEF(coerced_value)) {
3772 /* A previous property did not require coercion, but this one does,
3773 * so they are incompatible. */
3774 goto conflicting_coercion_error;
3775 } else {
3776 zval tmp;
3777 ZVAL_COPY(&tmp, zv);
3778 if (!zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop->type), &tmp)) {
3779 zval_ptr_dtor(&tmp);
3780 goto type_error;
3781 }
3782 if (!zend_is_identical(&coerced_value, &tmp)) {
3783 zval_ptr_dtor(&tmp);
3784 goto conflicting_coercion_error;
3785 }
3786 zval_ptr_dtor(&tmp);
3787 }
3788 } else {
3789 if (!first_prop) {
3790 first_prop = prop;
3791 } else if (!Z_ISUNDEF(coerced_value)) {
3792 /* A previous property required coercion, but this one doesn't,
3793 * so they are incompatible. */
3794conflicting_coercion_error:
3795 zend_throw_conflicting_coercion_error(first_prop, prop, zv);
3796 zval_ptr_dtor(&coerced_value);
3797 return 0;
3798 }
3799 }
3801
3802 if (!Z_ISUNDEF(coerced_value)) {
3804 ZVAL_COPY_VALUE(zv, &coerced_value);
3805 }
3806
3807 return 1;
3808}
3809
3810static zend_always_inline void i_zval_ptr_dtor_noref(zval *zval_ptr) {
3811 if (Z_REFCOUNTED_P(zval_ptr)) {
3812 zend_refcounted *ref = Z_COUNTED_P(zval_ptr);
3813 ZEND_ASSERT(Z_TYPE_P(zval_ptr) != IS_REFERENCE);
3814 GC_DTOR_NO_REF(ref);
3815 }
3816}
3817
3818ZEND_API zval* zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict, zend_refcounted **garbage_ptr)
3819{
3820 bool ret;
3821 zval value;
3822 zend_refcounted *ref = NULL;
3823
3824 if (Z_ISREF_P(orig_value)) {
3825 ref = Z_COUNTED_P(orig_value);
3826 orig_value = Z_REFVAL_P(orig_value);
3827 }
3828
3829 ZVAL_COPY(&value, orig_value);
3832 if (EXPECTED(ret)) {
3834 *garbage_ptr = Z_COUNTED_P(variable_ptr);
3835 }
3837 } else {
3838 zval_ptr_dtor_nogc(&value);
3839 }
3840 if (value_type & (IS_VAR|IS_TMP_VAR)) {
3841 if (UNEXPECTED(ref)) {
3842 if (UNEXPECTED(GC_DELREF(ref) == 0)) {
3843 zval_ptr_dtor(orig_value);
3844 efree_size(ref, sizeof(zend_reference));
3845 }
3846 } else {
3847 i_zval_ptr_dtor_noref(orig_value);
3848 }
3849 }
3850 return variable_ptr;
3851}
3852
3853ZEND_API zval* zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict)
3854{
3856 zval *result = zend_assign_to_typed_ref_ex(variable_ptr, orig_value, value_type, strict, &garbage);
3857 if (garbage) {
3859 }
3860 return result;
3861}
3862
3864 zval *val = orig_val;
3866 int result;
3867
3868 val = Z_REFVAL_P(val);
3869 result = i_zend_verify_type_assignable_zval(prop_info, val, strict);
3870 if (result > 0) {
3871 return 1;
3872 }
3873
3874 if (result < 0) {
3875 /* This is definitely an error, but we still need to determined why: Either because
3876 * the value is simply illegal for the type, or because or a conflicting coercion. */
3877 zval tmp;
3878 ZVAL_COPY(&tmp, val);
3879 if (zend_verify_weak_scalar_type_hint(ZEND_TYPE_FULL_MASK(prop_info->type), &tmp)) {
3880 const zend_property_info *ref_prop = ZEND_REF_FIRST_SOURCE(Z_REF_P(orig_val));
3882 zval_ptr_dtor(&tmp);
3883 return 0;
3884 }
3885 zval_ptr_dtor(&tmp);
3886 }
3887 } else {
3888 ZVAL_DEREF(val);
3889 if (i_zend_check_property_type(prop_info, val, strict)) {
3890 return 1;
3891 }
3892 }
3893
3896 } else {
3899 }
3900
3901 return 0;
3902}
3903
3907
3909{
3911 if (source_list->ptr == NULL) {
3912 source_list->ptr = prop;
3913 return;
3914 }
3915
3916 list = ZEND_PROPERTY_INFO_SOURCE_TO_LIST(source_list->list);
3917 if (!ZEND_PROPERTY_INFO_SOURCE_IS_LIST(source_list->list)) {
3918 list = emalloc(sizeof(zend_property_info_list) + (4 - 1) * sizeof(zend_property_info *));
3919 list->ptr[0] = source_list->ptr;
3920 list->num_allocated = 4;
3921 list->num = 1;
3922 } else if (list->num_allocated == list->num) {
3923 list->num_allocated = list->num * 2;
3924 list = erealloc(list, sizeof(zend_property_info_list) + (list->num_allocated - 1) * sizeof(zend_property_info *));
3925 }
3926
3927 list->ptr[list->num++] = prop;
3928 source_list->list = ZEND_PROPERTY_INFO_SOURCE_FROM_LIST(list);
3929}
3930
3932{
3935
3936 ZEND_ASSERT(prop);
3937 if (!ZEND_PROPERTY_INFO_SOURCE_IS_LIST(source_list->list)) {
3938 ZEND_ASSERT(source_list->ptr == prop);
3939 source_list->ptr = NULL;
3940 return;
3941 }
3942
3943 if (list->num == 1) {
3944 ZEND_ASSERT(*list->ptr == prop);
3945 efree(list);
3946 source_list->ptr = NULL;
3947 return;
3948 }
3949
3950 /* Checking against end here to get a more graceful failure mode if we missed adding a type
3951 * source at some point. */
3952 ptr = list->ptr;
3953 end = ptr + list->num;
3954 while (ptr < end && *ptr != prop) {
3955 ptr++;
3956 }
3957 ZEND_ASSERT(*ptr == prop);
3958
3959 /* Copy the last list element into the deleted slot. */
3960 *ptr = list->ptr[--list->num];
3961
3962 if (list->num >= 4 && list->num * 4 == list->num_allocated) {
3963 list->num_allocated = list->num * 2;
3964 source_list->list = ZEND_PROPERTY_INFO_SOURCE_FROM_LIST(erealloc(list, sizeof(zend_property_info_list) + (list->num_allocated - 1) * sizeof(zend_property_info *)));
3965 }
3966}
3967
3968static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DATA_DC)
3969{
3970 zval *result = EX_VAR(opline->result.var);
3971
3972 switch (type) {
3973 case BP_VAR_R:
3974 if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
3975 ZVAL_OBJ(result, Z_OBJ(EX(This)));
3977 } else {
3979 zend_error_unchecked(E_WARNING, "Undefined variable $this");
3980 }
3981 break;
3982 case BP_VAR_IS:
3983 if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
3984 ZVAL_OBJ(result, Z_OBJ(EX(This)));
3986 } else {
3988 }
3989 break;
3990 case BP_VAR_RW:
3991 case BP_VAR_W:
3993 zend_throw_error(NULL, "Cannot re-assign $this");
3994 break;
3995 case BP_VAR_UNSET:
3997 zend_throw_error(NULL, "Cannot unset $this");
3998 break;
4000 }
4001}
4002
4003static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_clone_call(zend_function *clone, zend_class_entry *scope)
4004{
4005 zend_throw_error(NULL, "Call to %s %s::__clone() from %s%s",
4007 scope ? "scope " : "global scope",
4008 scope ? ZSTR_VAL(scope->name) : ""
4009 );
4010}
4011
4012#if ZEND_INTENSIVE_DEBUGGING
4013
4014#define CHECK_SYMBOL_TABLES() \
4015 zend_hash_apply(&EG(symbol_table), zend_check_symbol); \
4016 if (&EG(symbol_table)!=EX(symbol_table)) { \
4017 zend_hash_apply(EX(symbol_table), zend_check_symbol); \
4018 }
4019
4020static void zend_check_symbol(zval *pz)
4021{
4022 if (Z_TYPE_P(pz) == IS_INDIRECT) {
4023 pz = Z_INDIRECT_P(pz);
4024 }
4025 if (Z_TYPE_P(pz) > 10) {
4026 fprintf(stderr, "Warning! %x has invalid type!\n", *pz);
4027/* See http://support.microsoft.com/kb/190351 */
4028#ifdef ZEND_WIN32
4029 fflush(stderr);
4030#endif
4031 } else if (Z_TYPE_P(pz) == IS_ARRAY) {
4032 zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol);
4033 } else if (Z_TYPE_P(pz) == IS_OBJECT) {
4034 /* OBJ-TBI - doesn't support new object model! */
4035 zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol);
4036 }
4037}
4038
4039
4040#else
4041#define CHECK_SYMBOL_TABLES()
4042#endif
4043
4048
4050{
4051 /* Clean before putting into the cache, since clean could call dtors,
4052 * which could use the cached hash. Also do this before the check for
4053 * available cache slots, as those may be used by a dtor as well. */
4054 zend_symtable_clean(symbol_table);
4055 if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
4056 zend_array_destroy(symbol_table);
4057 } else {
4058 *(EG(symtable_cache_ptr)++) = symbol_table;
4059 }
4060}
4061/* }}} */
4062
4063static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
4064{
4065 zval *cv = EX_VAR_NUM(0);
4066 int count = EX(func)->op_array.last_var;
4067 while (EXPECTED(count != 0)) {
4068 i_zval_ptr_dtor(cv);
4069 cv++;
4070 count--;
4071 }
4072}
4073/* }}} */
4074
4076{
4077 i_free_compiled_variables(execute_data);
4078}
4079/* }}} */
4080
4082{
4083 zend_atomic_bool_store_ex(&EG(vm_interrupt), false);
4084 if (zend_atomic_bool_load_ex(&EG(timed_out))) {
4085 zend_timeout();
4086 } else if (zend_interrupt_function) {
4088 }
4089}
4090
4091#define ZEND_VM_INTERRUPT_CHECK() do { \
4092 if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \
4093 ZEND_VM_INTERRUPT(); \
4094 } \
4095 } while (0)
4096
4097#define ZEND_VM_LOOP_INTERRUPT_CHECK() do { \
4098 if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \
4099 ZEND_VM_LOOP_INTERRUPT(); \
4100 } \
4101 } while (0)
4102
4103#define ZEND_VM_FCALL_INTERRUPT_CHECK(call) do { \
4104 if (UNEXPECTED(zend_atomic_bool_load_ex(&EG(vm_interrupt)))) { \
4105 zend_fcall_interrupt(call); \
4106 } \
4107 } while (0)
4108
4109/*
4110 * Stack Frame Layout (the whole stack frame is allocated at once)
4111 * ==================
4112 *
4113 * +========================================+
4114 * EG(current_execute_data) -> | zend_execute_data |
4115 * +----------------------------------------+
4116 * EX_VAR_NUM(0) --------> | VAR[0] = ARG[1] |
4117 * | ... |
4118 * | VAR[op_array->num_args-1] = ARG[N] |
4119 * | ... |
4120 * | VAR[op_array->last_var-1] |
4121 * | VAR[op_array->last_var] = TMP[0] |
4122 * | ... |
4123 * | VAR[op_array->last_var+op_array->T-1] |
4124 * | ARG[N+1] (extra_args) |
4125 * | ... |
4126 * +----------------------------------------+
4127 */
4128
4129/* zend_copy_extra_args is used when the actually passed number of arguments
4130 * (EX_NUM_ARGS) is greater than what the function defined (op_array->num_args).
4131 *
4132 * The extra arguments will be copied into the call frame after all the compiled variables.
4133 *
4134 * If there are extra arguments copied, a flag "ZEND_CALL_FREE_EXTRA_ARGS" will be set
4135 * on the zend_execute_data, and when the executor leaves the function, the
4136 * args will be freed in zend_leave_helper.
4137 */
4138static zend_never_inline void zend_copy_extra_args(EXECUTE_DATA_D)
4139{
4140 zend_op_array *op_array = &EX(func)->op_array;
4141 uint32_t first_extra_arg = op_array->num_args;
4142 uint32_t num_args = EX_NUM_ARGS();
4143 zval *src;
4144 size_t delta;
4145 uint32_t count;
4146 uint32_t type_flags = 0;
4147
4148 if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
4149 /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
4150#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4151 opline += first_extra_arg;
4152#else
4153 EX(opline) += first_extra_arg;
4154#endif
4155
4156 }
4157
4158 /* move extra args into separate array after all CV and TMP vars */
4159 src = EX_VAR_NUM(num_args - 1);
4160 delta = op_array->last_var + op_array->T - first_extra_arg;
4161 count = num_args - first_extra_arg;
4162 if (EXPECTED(delta != 0)) {
4163 delta *= sizeof(zval);
4164 do {
4165 type_flags |= Z_TYPE_INFO_P(src);
4166 ZVAL_COPY_VALUE((zval*)(((char*)src) + delta), src);
4167 ZVAL_UNDEF(src);
4168 src--;
4169 } while (--count);
4170 if (Z_TYPE_INFO_REFCOUNTED(type_flags)) {
4172 }
4173 } else {
4174 do {
4175 if (Z_REFCOUNTED_P(src)) {
4177 break;
4178 }
4179 src--;
4180 } while (--count);
4181 }
4182}
4183
4184static zend_always_inline void zend_init_cvs(uint32_t first, uint32_t last EXECUTE_DATA_DC)
4185{
4186 if (EXPECTED(first < last)) {
4187 uint32_t count = last - first;
4188 zval *var = EX_VAR_NUM(first);
4189
4190 do {
4191 ZVAL_UNDEF(var);
4192 var++;
4193 } while (--count);
4194 }
4195}
4196
4197static zend_always_inline void i_init_func_execute_data(zend_op_array *op_array, zval *return_value, bool may_be_trampoline EXECUTE_DATA_DC) /* {{{ */
4198{
4199 uint32_t first_extra_arg, num_args;
4200 ZEND_ASSERT(EX(func) == (zend_function*)op_array);
4201
4202#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4203 opline = op_array->opcodes;
4204#else
4205 EX(opline) = op_array->opcodes;
4206#endif
4207 EX(call) = NULL;
4209
4210 /* Handle arguments */
4211 first_extra_arg = op_array->num_args;
4213 if (UNEXPECTED(num_args > first_extra_arg)) {
4214 if (!may_be_trampoline || EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
4215 zend_copy_extra_args(EXECUTE_DATA_C);
4216 }
4217 } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
4218 /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
4219#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4220 opline += num_args;
4221#else
4222 EX(opline) += num_args;
4223#endif
4224 }
4225
4226 /* Initialize CV variables (skip arguments) */
4227 zend_init_cvs(num_args, op_array->last_var EXECUTE_DATA_CC);
4228
4229 EX(run_time_cache) = RUN_TIME_CACHE(op_array);
4230
4231 EG(current_execute_data) = execute_data;
4232}
4233/* }}} */
4234
4235static zend_always_inline void init_func_run_time_cache_i(zend_op_array *op_array) /* {{{ */
4236{
4237 void **run_time_cache;
4238
4239 ZEND_ASSERT(RUN_TIME_CACHE(op_array) == NULL);
4240 run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
4241 memset(run_time_cache, 0, op_array->cache_size);
4242 ZEND_MAP_PTR_SET(op_array->run_time_cache, run_time_cache);
4243}
4244/* }}} */
4245
4246static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
4247{
4248 init_func_run_time_cache_i(op_array);
4249}
4250/* }}} */
4251
4253{
4254 zval *zv = zend_hash_find(EG(function_table), name);
4255
4256 if (EXPECTED(zv != NULL)) {
4258
4259 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4260 init_func_run_time_cache_i(&fbc->op_array);
4261 }
4262 return fbc;
4263 }
4264 return NULL;
4265} /* }}} */
4266
4268{
4269 zval *zv = zend_hash_str_find(EG(function_table), name, len);
4270
4271 if (EXPECTED(zv != NULL)) {
4273
4274 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4275 init_func_run_time_cache_i(&fbc->op_array);
4276 }
4277 return fbc;
4278 }
4279 return NULL;
4280} /* }}} */
4281
4283{
4284 if (!RUN_TIME_CACHE(op_array)) {
4285 init_func_run_time_cache_i(op_array);
4286 }
4287} /* }}} */
4288
4289static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
4290{
4291 ZEND_ASSERT(EX(func) == (zend_function*)op_array);
4292
4293 EX(opline) = op_array->opcodes;
4294 EX(call) = NULL;
4296
4297 if (op_array->last_var) {
4299 }
4300
4301 if (!ZEND_MAP_PTR(op_array->run_time_cache)) {
4302 void *ptr;
4303
4305 ptr = emalloc(op_array->cache_size);
4306 ZEND_MAP_PTR_INIT(op_array->run_time_cache, ptr);
4307 memset(ptr, 0, op_array->cache_size);
4308 }
4309 EX(run_time_cache) = RUN_TIME_CACHE(op_array);
4310
4311 EG(current_execute_data) = execute_data;
4312}
4313/* }}} */
4314
4316{
4317#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4318 zend_execute_data *orig_execute_data = execute_data;
4319#endif
4320#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4321 const zend_op *orig_opline = opline;
4322#endif
4323#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4324 execute_data = ex;
4325#else
4327#endif
4328
4329 EX(prev_execute_data) = EG(current_execute_data);
4330 if (!RUN_TIME_CACHE(op_array)) {
4331 init_func_run_time_cache(op_array);
4332 }
4333 i_init_func_execute_data(op_array, return_value, 1 EXECUTE_DATA_CC);
4334
4335#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4336 EX(opline) = opline;
4337 opline = orig_opline;
4338#endif
4339#if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
4340 execute_data = orig_execute_data;
4341#endif
4342}
4343/* }}} */
4344
4346{
4347 EX(prev_execute_data) = EG(current_execute_data);
4348 i_init_code_execute_data(execute_data, op_array, return_value);
4349}
4350/* }}} */
4351
4360/* }}} */
4361
4362zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
4363{
4364 zend_execute_data *new_call;
4365 int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
4366
4367 /* copy call frame into new stack segment */
4368 new_call = zend_vm_stack_extend(used_stack * sizeof(zval));
4369 *new_call = *call;
4371
4372 if (passed_args) {
4373 zval *src = ZEND_CALL_ARG(call, 1);
4374 zval *dst = ZEND_CALL_ARG(new_call, 1);
4375 do {
4376 ZVAL_COPY_VALUE(dst, src);
4377 passed_args--;
4378 src++;
4379 dst++;
4380 } while (passed_args);
4381 }
4382
4383 /* delete old call_frame from previous stack segment */
4384 EG(vm_stack)->prev->top = (zval*)call;
4385
4386 /* delete previous stack segment if it became empty */
4387 if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMENTS(EG(vm_stack)->prev))) {
4388 zend_vm_stack r = EG(vm_stack)->prev;
4389
4390 EG(vm_stack)->prev = r->prev;
4391 efree(r);
4392 }
4393
4394 return new_call;
4395}
4396/* }}} */
4397
4398static zend_always_inline zend_generator *zend_get_running_generator(EXECUTE_DATA_D) /* {{{ */
4399{
4400 /* The generator object is stored in EX(return_value) */
4402 /* However control may currently be delegated to another generator.
4403 * That's the one we're interested in. */
4404 return generator;
4405}
4406/* }}} */
4407
4409{
4410 zend_op *opline = EX(func)->op_array.opcodes + op_num;
4411 int level;
4412 int do_exit;
4413 uint32_t num_args;
4414
4415 if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
4416 opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
4418 opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
4419 opline->opcode == ZEND_INIT_USER_CALL ||
4420 opline->opcode == ZEND_INIT_METHOD_CALL ||
4422 opline->opcode == ZEND_NEW)) {
4423 ZEND_ASSERT(op_num);
4424 opline--;
4425 }
4426
4427 do {
4428 /* find the number of actually passed arguments */
4429 level = 0;
4430 do_exit = 0;
4432 do {
4433 switch (opline->opcode) {
4434 case ZEND_DO_FCALL:
4435 case ZEND_DO_ICALL:
4436 case ZEND_DO_UCALL:
4439 level++;
4440 break;
4441 case ZEND_INIT_FCALL:
4448 case ZEND_NEW:
4449 if (level == 0) {
4450 num_args = 0;
4451 do_exit = 1;
4452 }
4453 level--;
4454 break;
4455 case ZEND_SEND_VAL:
4456 case ZEND_SEND_VAL_EX:
4457 case ZEND_SEND_VAR:
4458 case ZEND_SEND_VAR_EX:
4459 case ZEND_SEND_FUNC_ARG:
4460 case ZEND_SEND_REF:
4463 case ZEND_SEND_USER:
4464 if (level == 0) {
4465 /* For named args, the number of arguments is up to date. */
4466 if (opline->op2_type != IS_CONST) {
4467 num_args = opline->op2.num;
4468 }
4469 do_exit = 1;
4470 }
4471 break;
4472 case ZEND_SEND_ARRAY:
4473 case ZEND_SEND_UNPACK:
4475 if (level == 0) {
4476 do_exit = 1;
4477 }
4478 break;
4479 }
4480 if (!do_exit) {
4481 opline--;
4482 }
4483 } while (!do_exit);
4484 if (call->prev_execute_data) {
4485 /* skip current call region */
4486 level = 0;
4487 do_exit = 0;
4488 do {
4489 switch (opline->opcode) {
4490 case ZEND_DO_FCALL:
4491 case ZEND_DO_ICALL:
4492 case ZEND_DO_UCALL:
4495 level++;
4496 break;
4497 case ZEND_INIT_FCALL:
4504 case ZEND_NEW:
4505 if (level == 0) {
4506 do_exit = 1;
4507 }
4508 level--;
4509 break;
4510 }
4511 opline--;
4512 } while (!do_exit);
4513 }
4514
4515 if (EXPECTED(num_args > 0)) {
4516 zval *p = ZEND_CALL_ARG(call, 1);
4517 do {
4518 zend_get_gc_buffer_add_zval(buf, p);
4519 p++;
4520 } while (--num_args);
4521 }
4523 zend_get_gc_buffer_add_obj(buf, Z_OBJ(call->This));
4524 }
4526 zval *val;
4527 ZEND_HASH_FOREACH_VAL(call->extra_named_params, val) {
4528 zend_get_gc_buffer_add_zval(buf, val);
4530 }
4531 if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
4532 zend_get_gc_buffer_add_obj(buf, ZEND_CLOSURE_OBJECT(call->func));
4533 }
4534
4535 call = call->prev_execute_data;
4536 } while (call);
4537}
4538/* }}} */
4539
4540static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t op_num) /* {{{ */
4541{
4542 if (UNEXPECTED(EX(call))) {
4544 zend_op *opline = EX(func)->op_array.opcodes + op_num;
4545 int level;
4546 int do_exit;
4547
4548 if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
4549 opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
4551 opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
4552 opline->opcode == ZEND_INIT_USER_CALL ||
4553 opline->opcode == ZEND_INIT_METHOD_CALL ||
4556 opline->opcode == ZEND_NEW)) {
4557 ZEND_ASSERT(op_num);
4558 opline--;
4559 }
4560
4561 do {
4562 /* If the exception was thrown during a function call there might be
4563 * arguments pushed to the stack that have to be dtor'ed. */
4564
4565 /* find the number of actually passed arguments */
4566 level = 0;
4567 do_exit = 0;
4568 do {
4569 switch (opline->opcode) {
4570 case ZEND_DO_FCALL:
4571 case ZEND_DO_ICALL:
4572 case ZEND_DO_UCALL:
4575 level++;
4576 break;
4577 case ZEND_INIT_FCALL:
4585 case ZEND_NEW:
4586 if (level == 0) {
4588 do_exit = 1;
4589 }
4590 level--;
4591 break;
4592 case ZEND_SEND_VAL:
4593 case ZEND_SEND_VAL_EX:
4594 case ZEND_SEND_VAR:
4595 case ZEND_SEND_VAR_EX:
4596 case ZEND_SEND_FUNC_ARG:
4597 case ZEND_SEND_REF:
4600 case ZEND_SEND_USER:
4601 if (level == 0) {
4602 /* For named args, the number of arguments is up to date. */
4603 if (opline->op2_type != IS_CONST) {
4604 ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
4605 }
4606 do_exit = 1;
4607 }
4608 break;
4609 case ZEND_SEND_ARRAY:
4610 case ZEND_SEND_UNPACK:
4612 if (level == 0) {
4613 do_exit = 1;
4614 }
4615 break;
4616 }
4617 if (!do_exit) {
4618 opline--;
4619 }
4620 } while (!do_exit);
4621 if (call->prev_execute_data) {
4622 /* skip current call region */
4623 level = 0;
4624 do_exit = 0;
4625 do {
4626 switch (opline->opcode) {
4627 case ZEND_DO_FCALL:
4628 case ZEND_DO_ICALL:
4629 case ZEND_DO_UCALL:
4632 level++;
4633 break;
4634 case ZEND_INIT_FCALL:
4642 case ZEND_NEW:
4643 if (level == 0) {
4644 do_exit = 1;
4645 }
4646 level--;
4647 break;
4648 }
4649 opline--;
4650 } while (!do_exit);
4651 }
4652
4653 zend_vm_stack_free_args(EX(call));
4654
4656 OBJ_RELEASE(Z_OBJ(call->This));
4657 }
4659 zend_free_extra_named_params(call->extra_named_params);
4660 }
4661 if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
4662 zend_object_release(ZEND_CLOSURE_OBJECT(call->func));
4663 } else if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
4664 zend_string_release_ex(call->func->common.function_name, 0);
4666 }
4667
4668 EX(call) = call->prev_execute_data;
4669 zend_vm_stack_free_call_frame(call);
4670 call = EX(call);
4671 } while (call);
4672 }
4673}
4674/* }}} */
4675
4676static const zend_live_range *find_live_range(const zend_op_array *op_array, uint32_t op_num, uint32_t var_num) /* {{{ */
4677{
4678 int i;
4679 for (i = 0; i < op_array->last_live_range; i++) {
4680 const zend_live_range *range = &op_array->live_range[i];
4681 if (op_num >= range->start && op_num < range->end
4682 && var_num == (range->var & ~ZEND_LIVE_MASK)) {
4683 return range;
4684 }
4685 }
4686 return NULL;
4687}
4688/* }}} */
4689
4690static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
4691{
4692 int i;
4693
4694 for (i = 0; i < EX(func)->op_array.last_live_range; i++) {
4695 const zend_live_range *range = &EX(func)->op_array.live_range[i];
4696 if (range->start > op_num) {
4697 /* further blocks will not be relevant... */
4698 break;
4699 } else if (op_num < range->end) {
4700 if (!catch_op_num || catch_op_num >= range->end) {
4701 uint32_t kind = range->var & ZEND_LIVE_MASK;
4702 uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
4703 zval *var = EX_VAR(var_num);
4704
4705 if (kind == ZEND_LIVE_TMPVAR) {
4706 zval_ptr_dtor_nogc(var);
4707 } else if (kind == ZEND_LIVE_NEW) {
4708 zend_object *obj;
4710 obj = Z_OBJ_P(var);
4711 zend_object_store_ctor_failed(obj);
4712 OBJ_RELEASE(obj);
4713 } else if (kind == ZEND_LIVE_LOOP) {
4714 if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
4716 }
4717 zval_ptr_dtor_nogc(var);
4718 } else if (kind == ZEND_LIVE_ROPE) {
4719 zend_string **rope = (zend_string **)var;
4720 zend_op *last = EX(func)->op_array.opcodes + op_num;
4721 while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
4722 || last->result.var != var_num) {
4723 ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
4724 last--;
4725 }
4726 if (last->opcode == ZEND_ROPE_INIT) {
4727 zend_string_release_ex(*rope, 0);
4728 } else {
4729 int j = last->extended_value;
4730 do {
4731 zend_string_release_ex(rope[j], 0);
4732 } while (j--);
4733 }
4734 } else if (kind == ZEND_LIVE_SILENCE) {
4735 /* restore previous error_reporting value */
4738 EG(error_reporting) = Z_LVAL_P(var);
4739 }
4740 }
4741 }
4742 }
4743 }
4744}
4745/* }}} */
4746
4747ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) {
4748 cleanup_unfinished_calls(execute_data, op_num);
4749 cleanup_live_vars(execute_data, op_num, catch_op_num);
4750}
4751
4756
4758{
4759 if (!EX(func)) {
4760 return NULL;
4761 }
4762
4764 zend_get_gc_buffer_add_obj(gc_buffer, Z_OBJ(execute_data->This));
4765 }
4766
4768 zend_get_gc_buffer_add_obj(gc_buffer, ZEND_CLOSURE_OBJECT(EX(func)));
4769 }
4770
4771 if (!ZEND_USER_CODE(EX(func)->common.type)) {
4773 return NULL;
4774 }
4775
4776 zend_op_array *op_array = &EX(func)->op_array;
4777
4779 uint32_t i, num_cvs = EX(func)->op_array.last_var;
4780 for (i = 0; i < num_cvs; i++) {
4781 zend_get_gc_buffer_add_zval(gc_buffer, EX_VAR_NUM(i));
4782 }
4783 }
4784
4786 zval *zv = EX_VAR_NUM(op_array->last_var + op_array->T);
4787 zval *end = zv + (EX_NUM_ARGS() - op_array->num_args);
4788 while (zv != end) {
4789 zend_get_gc_buffer_add_zval(gc_buffer, zv++);
4790 }
4791 }
4792
4794 zval extra_named_params;
4795 ZVAL_ARR(&extra_named_params, EX(extra_named_params));
4796 zend_get_gc_buffer_add_zval(gc_buffer, &extra_named_params);
4797 }
4798
4799 uint32_t op_num;
4800 if (UNEXPECTED(execute_data->opline->opcode == ZEND_HANDLE_EXCEPTION)) {
4801 op_num = EG(opline_before_exception) - op_array->opcodes;
4802 } else {
4803 op_num = execute_data->opline - op_array->opcodes;
4804 }
4805 ZEND_ASSERT(op_num < op_array->last);
4806
4807 if (call) {
4808 zend_unfinished_calls_gc(execute_data, call, op_num, gc_buffer);
4809 }
4810
4811 if (execute_data->opline != op_array->opcodes) {
4812 uint32_t i;
4813 for (i = 0; i < op_array->last_live_range; i++) {
4814 const zend_live_range *range = &op_array->live_range[i];
4815 if (range->start > op_num) {
4816 break;
4817 } else if (op_num < range->end) {
4818 uint32_t kind = range->var & ZEND_LIVE_MASK;
4819 uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
4820 zval *var = EX_VAR(var_num);
4822 zend_get_gc_buffer_add_zval(gc_buffer, var);
4823 }
4824 }
4825 }
4826 }
4827
4829 return execute_data->symbol_table;
4830 } else {
4831 return NULL;
4832 }
4833}
4834
4835#if ZEND_VM_SPEC
4836static void zend_swap_operands(zend_op *op) /* {{{ */
4837{
4838 znode_op tmp;
4839 uint8_t tmp_type;
4840
4841 tmp = op->op1;
4842 tmp_type = op->op1_type;
4843 op->op1 = op->op2;
4844 op->op1_type = op->op2_type;
4845 op->op2 = tmp;
4846 op->op2_type = tmp_type;
4847
4848#ifdef ZEND_VERIFY_TYPE_INFERENCE
4849 uint32_t tmp_info;
4850 tmp_info = op->op1_use_type;
4851 op->op1_use_type = op->op2_use_type;
4852 op->op2_use_type = tmp_info;
4853 tmp_info = op->op1_def_type;
4854 op->op1_def_type = op->op2_def_type;
4855 op->op2_def_type = tmp_info;
4856#endif
4857}
4858/* }}} */
4859#endif
4860
4861static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
4862{
4864 zval *func;
4865 zend_class_entry *called_scope;
4867 const char *colon;
4868
4869 if ((colon = zend_memrchr(ZSTR_VAL(function), ':', ZSTR_LEN(function))) != NULL &&
4870 colon > ZSTR_VAL(function) &&
4871 *(colon-1) == ':'
4872 ) {
4873 zend_string *mname;
4874 size_t cname_length = colon - ZSTR_VAL(function) - 1;
4875 size_t mname_length = ZSTR_LEN(function) - cname_length - (sizeof("::") - 1);
4876
4877 lcname = zend_string_init(ZSTR_VAL(function), cname_length, 0);
4878
4880 if (UNEXPECTED(called_scope == NULL)) {
4882 return NULL;
4883 }
4884
4885 mname = zend_string_init(ZSTR_VAL(function) + (cname_length + sizeof("::") - 1), mname_length, 0);
4886
4887 if (called_scope->get_static_method) {
4888 fbc = called_scope->get_static_method(called_scope, mname);
4889 } else {
4890 fbc = zend_std_get_static_method(called_scope, mname, NULL);
4891 }
4892 if (UNEXPECTED(fbc == NULL)) {
4893 if (EXPECTED(!EG(exception))) {
4894 zend_undefined_method(called_scope, mname);
4895 }
4897 zend_string_release_ex(mname, 0);
4898 return NULL;
4899 }
4900
4902 zend_string_release_ex(mname, 0);
4903
4904 if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
4905 zend_non_static_method_call(fbc);
4906 if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
4907 zend_string_release_ex(fbc->common.function_name, 0);
4909 }
4910 return NULL;
4911 }
4912 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4913 init_func_run_time_cache(&fbc->op_array);
4914 }
4915 } else {
4916 if (ZSTR_VAL(function)[0] == '\\') {
4917 lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
4919 } else {
4920 lcname = zend_string_tolower(function);
4921 }
4922 if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
4923 zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
4925 return NULL;
4926 }
4928
4929 fbc = Z_FUNC_P(func);
4930 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4931 init_func_run_time_cache(&fbc->op_array);
4932 }
4933 called_scope = NULL;
4934 }
4935
4936 return zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC,
4937 fbc, num_args, called_scope);
4938}
4939/* }}} */
4940
4941static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zend_object *function, uint32_t num_args) /* {{{ */
4942{
4944 void *object_or_called_scope;
4945 zend_class_entry *called_scope;
4947 uint32_t call_info;
4948
4949 if (EXPECTED(function->handlers->get_closure) &&
4950 EXPECTED(function->handlers->get_closure(function, &called_scope, &fbc, &object, 0) == SUCCESS)) {
4951
4952 object_or_called_scope = called_scope;
4953 if (EXPECTED(fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
4954 /* Delay closure destruction until its invocation */
4958 (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE);
4959 if (object) {
4961 object_or_called_scope = object;
4962 }
4963 } else {
4965 if (object) {
4967 GC_ADDREF(object); /* For $this pointer */
4968 object_or_called_scope = object;
4969 }
4970 }
4971 } else {
4972 zend_throw_error(NULL, "Object of type %s is not callable", ZSTR_VAL(function->ce->name));
4973 return NULL;
4974 }
4975
4976 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
4977 init_func_run_time_cache(&fbc->op_array);
4978 }
4979
4980 return zend_vm_stack_push_call_frame(call_info,
4981 fbc, num_args, object_or_called_scope);
4982}
4983/* }}} */
4984
4985static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_array *function, uint32_t num_args) /* {{{ */
4986{
4988 void *object_or_called_scope;
4990
4991 if (zend_hash_num_elements(function) == 2) {
4992 zval *obj;
4993 zval *method;
4995 method = zend_hash_index_find(function, 1);
4996
4997 if (UNEXPECTED(!obj) || UNEXPECTED(!method)) {
4998 zend_throw_error(NULL, "Array callback has to contain indices 0 and 1");
4999 return NULL;
5000 }
5001
5002 ZVAL_DEREF(obj);
5003 if (UNEXPECTED(Z_TYPE_P(obj) != IS_STRING) && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
5004 zend_throw_error(NULL, "First array member is not a valid class name or object");
5005 return NULL;
5006 }
5007
5008 ZVAL_DEREF(method);
5009 if (UNEXPECTED(Z_TYPE_P(method) != IS_STRING)) {
5010 zend_throw_error(NULL, "Second array member is not a valid method");
5011 return NULL;
5012 }
5013
5014 if (Z_TYPE_P(obj) == IS_STRING) {
5016
5017 if (UNEXPECTED(called_scope == NULL)) {
5018 return NULL;
5019 }
5020
5021 if (called_scope->get_static_method) {
5022 fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
5023 } else {
5024 fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
5025 }
5026 if (UNEXPECTED(fbc == NULL)) {
5027 if (EXPECTED(!EG(exception))) {
5028 zend_undefined_method(called_scope, Z_STR_P(method));
5029 }
5030 return NULL;
5031 }
5032 if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
5033 zend_non_static_method_call(fbc);
5034 if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
5035 zend_string_release_ex(fbc->common.function_name, 0);
5037 }
5038 return NULL;
5039 }
5040 object_or_called_scope = called_scope;
5041 } else {
5042 zend_object *object = Z_OBJ_P(obj);
5043
5044 fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
5045 if (UNEXPECTED(fbc == NULL)) {
5046 if (EXPECTED(!EG(exception))) {
5047 zend_undefined_method(object->ce, Z_STR_P(method));
5048 }
5049 return NULL;
5050 }
5051
5052 if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
5053 object_or_called_scope = object->ce;
5054 } else {
5056 GC_ADDREF(object); /* For $this pointer */
5057 object_or_called_scope = object;
5058 }
5059 }
5060 } else {
5061 zend_throw_error(NULL, "Array callback must have exactly two elements");
5062 return NULL;
5063 }
5064
5065 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
5066 init_func_run_time_cache(&fbc->op_array);
5067 }
5068
5069 return zend_vm_stack_push_call_frame(call_info,
5070 fbc, num_args, object_or_called_scope);
5071}
5072/* }}} */
5073
5074#define ZEND_FAKE_OP_ARRAY ((zend_op_array*)(intptr_t)-1)
5075
5076static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval *inc_filename_zv, int type) /* {{{ */
5077{
5079 zend_string *tmp_inc_filename;
5080 zend_string *inc_filename = zval_try_get_tmp_string(inc_filename_zv, &tmp_inc_filename);
5081 if (UNEXPECTED(!inc_filename)) {
5082 return NULL;
5083 }
5084
5085 switch (type) {
5086 case ZEND_INCLUDE_ONCE:
5087 case ZEND_REQUIRE_ONCE: {
5088 zend_file_handle file_handle;
5089 zend_string *resolved_path;
5090
5091 resolved_path = zend_resolve_path(inc_filename);
5092 if (EXPECTED(resolved_path)) {
5093 if (zend_hash_exists(&EG(included_files), resolved_path)) {
5095 zend_string_release_ex(resolved_path, 0);
5096 break;
5097 }
5098 } else if (UNEXPECTED(EG(exception))) {
5099 break;
5102 (type == ZEND_INCLUDE_ONCE) ?
5105 break;
5106 } else {
5107 resolved_path = zend_string_copy(inc_filename);
5108 }
5109
5110 zend_stream_init_filename_ex(&file_handle, resolved_path);
5111 if (SUCCESS == zend_stream_open(&file_handle)) {
5112
5113 if (!file_handle.opened_path) {
5114 file_handle.opened_path = zend_string_copy(resolved_path);
5115 }
5116
5117 if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path)) {
5119 } else {
5121 }
5122 } else if (!EG(exception)) {
5124 (type == ZEND_INCLUDE_ONCE) ?
5127 }
5128 zend_destroy_file_handle(&file_handle);
5129 zend_string_release_ex(resolved_path, 0);
5130 }
5131 break;
5132 case ZEND_INCLUDE:
5133 case ZEND_REQUIRE:
5136 (type == ZEND_INCLUDE) ?
5139 break;
5140 }
5142 break;
5143 case ZEND_EVAL: {
5144 char *eval_desc = zend_make_compiled_string_description("eval()'d code");
5146 efree(eval_desc);
5147 }
5148 break;
5150 }
5151
5152 zend_tmp_string_release(tmp_inc_filename);
5153 return new_op_array;
5154}
5155/* }}} */
5156
5157static zend_never_inline bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5158{
5159 zend_class_entry *ce = Z_OBJCE_P(array_ptr);
5160 zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, by_ref);
5161 bool is_empty;
5162
5163 if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) {
5164 if (iter) {
5165 OBJ_RELEASE(&iter->std);
5166 }
5167 if (!EG(exception)) {
5168 zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name));
5169 }
5170 ZVAL_UNDEF(EX_VAR(opline->result.var));
5171 return 1;
5172 }
5173
5174 iter->index = 0;
5175 if (iter->funcs->rewind) {
5176 iter->funcs->rewind(iter);
5177 if (UNEXPECTED(EG(exception) != NULL)) {
5178 OBJ_RELEASE(&iter->std);
5179 ZVAL_UNDEF(EX_VAR(opline->result.var));
5180 return 1;
5181 }
5182 }
5183
5184 is_empty = iter->funcs->valid(iter) != SUCCESS;
5185
5186 if (UNEXPECTED(EG(exception) != NULL)) {
5187 OBJ_RELEASE(&iter->std);
5188 ZVAL_UNDEF(EX_VAR(opline->result.var));
5189 return 1;
5190 }
5191 iter->index = -1; /* will be set to 0 before using next handler */
5192
5193 ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std);
5194 Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
5195
5196 return is_empty;
5197}
5198/* }}} */
5199
5200static zend_always_inline zend_result _zend_quick_get_constant(
5201 const zval *key, uint32_t flags, bool check_defined_only OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5202{
5203 zval *zv;
5204 zend_constant *c = NULL;
5205
5206 /* null/true/false are resolved during compilation, so don't check for them here. */
5207 zv = zend_hash_find_known_hash(EG(zend_constants), Z_STR_P(key));
5208 if (zv) {
5209 c = (zend_constant*)Z_PTR_P(zv);
5211 key++;
5212 zv = zend_hash_find_known_hash(EG(zend_constants), Z_STR_P(key));
5213 if (zv) {
5214 c = (zend_constant*)Z_PTR_P(zv);
5215 }
5216 }
5217
5218 if (!c) {
5219 if (!check_defined_only) {
5220 zend_throw_error(NULL, "Undefined constant \"%s\"", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)));
5221 ZVAL_UNDEF(EX_VAR(opline->result.var));
5222 }
5223 return FAILURE;
5224 }
5225
5226 if (!check_defined_only) {
5227 ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
5229 zend_error(E_DEPRECATED, "Constant %s is deprecated", ZSTR_VAL(c->name));
5230 return SUCCESS;
5231 }
5232 }
5233
5234 CACHE_PTR(opline->extended_value, c);
5235 return SUCCESS;
5236}
5237/* }}} */
5238
5239static zend_never_inline void ZEND_FASTCALL zend_quick_get_constant(
5240 const zval *key, uint32_t flags OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5241{
5242 _zend_quick_get_constant(key, flags, 0 OPLINE_CC EXECUTE_DATA_CC);
5243} /* }}} */
5244
5245static zend_never_inline zend_result ZEND_FASTCALL zend_quick_check_constant(
5246 const zval *key OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
5247{
5248 return _zend_quick_get_constant(key, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
5249} /* }}} */
5250
5251static zend_always_inline uint32_t zend_get_arg_offset_by_name(
5252 zend_function *fbc, zend_string *arg_name, void **cache_slot) {
5253 if (EXPECTED(*cache_slot == fbc)) {
5254 return *(uintptr_t *)(cache_slot + 1);
5255 }
5256
5257 // TODO: Use a hash table?
5258 uint32_t num_args = fbc->common.num_args;
5259 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)
5260 || EXPECTED(fbc->common.fn_flags & ZEND_ACC_USER_ARG_INFO)) {
5261 for (uint32_t i = 0; i < num_args; i++) {
5262 zend_arg_info *arg_info = &fbc->op_array.arg_info[i];
5263 if (zend_string_equals(arg_name, arg_info->name)) {
5264 *cache_slot = fbc;
5265 *(uintptr_t *)(cache_slot + 1) = i;
5266 return i;
5267 }
5268 }
5269 } else {
5270 for (uint32_t i = 0; i < num_args; i++) {
5271 zend_internal_arg_info *arg_info = &fbc->internal_function.arg_info[i];
5272 size_t len = strlen(arg_info->name);
5273 if (zend_string_equals_cstr(arg_name, arg_info->name, len)) {
5274 *cache_slot = fbc;
5275 *(uintptr_t *)(cache_slot + 1) = i;
5276 return i;
5277 }
5278 }
5279 }
5280
5281 if (fbc->common.fn_flags & ZEND_ACC_VARIADIC) {
5282 *cache_slot = fbc;
5283 *(uintptr_t *)(cache_slot + 1) = fbc->common.num_args;
5284 return fbc->common.num_args;
5285 }
5286
5287 return (uint32_t) -1;
5288}
5289
5291 zend_execute_data **call_ptr, zend_string *arg_name,
5292 uint32_t *arg_num_ptr, void **cache_slot) {
5293 zend_execute_data *call = *call_ptr;
5294 zend_function *fbc = call->func;
5295 uint32_t arg_offset = zend_get_arg_offset_by_name(fbc, arg_name, cache_slot);
5296 if (UNEXPECTED(arg_offset == (uint32_t) -1)) {
5297 zend_throw_error(NULL, "Unknown named parameter $%s", ZSTR_VAL(arg_name));
5298 return NULL;
5299 }
5300
5301 zval *arg;
5302 if (UNEXPECTED(arg_offset == fbc->common.num_args)) {
5303 /* Unknown named parameter that will be collected into a variadic. */
5306 call->extra_named_params = zend_new_array(0);
5307 }
5308
5309 arg = zend_hash_add_empty_element(call->extra_named_params, arg_name);
5310 if (!arg) {
5311 zend_throw_error(NULL, "Named parameter $%s overwrites previous argument",
5312 ZSTR_VAL(arg_name));
5313 return NULL;
5314 }
5315 *arg_num_ptr = arg_offset + 1;
5316 return arg;
5317 }
5318
5319 uint32_t current_num_args = ZEND_CALL_NUM_ARGS(call);
5320 // TODO: We may wish to optimize the arg_offset == current_num_args case,
5321 // which is probably common (if the named parameters are in order of declaration).
5322 if (arg_offset >= current_num_args) {
5323 uint32_t new_num_args = arg_offset + 1;
5324 ZEND_CALL_NUM_ARGS(call) = new_num_args;
5325
5326 uint32_t num_extra_args = new_num_args - current_num_args;
5327 zend_vm_stack_extend_call_frame(call_ptr, current_num_args, num_extra_args);
5328 call = *call_ptr;
5329
5330 arg = ZEND_CALL_VAR_NUM(call, arg_offset);
5331 if (num_extra_args > 1) {
5332 zval *zv = ZEND_CALL_VAR_NUM(call, current_num_args);
5333 do {
5334 ZVAL_UNDEF(zv);
5335 zv++;
5336 } while (zv != arg);
5338 }
5339 } else {
5340 arg = ZEND_CALL_VAR_NUM(call, arg_offset);
5341 if (UNEXPECTED(!Z_ISUNDEF_P(arg))) {
5342 zend_throw_error(NULL, "Named parameter $%s overwrites previous argument",
5343 ZSTR_VAL(arg_name));
5344 return NULL;
5345 }
5346 }
5347
5348 *arg_num_ptr = arg_offset + 1;
5349 return arg;
5350}
5351
5352static zend_execute_data *start_fake_frame(zend_execute_data *call, const zend_op *opline) {
5353 zend_execute_data *old_prev_execute_data = call->prev_execute_data;
5354 call->prev_execute_data = EG(current_execute_data);
5355 call->opline = opline;
5356 EG(current_execute_data) = call;
5357 return old_prev_execute_data;
5358}
5359
5360static void end_fake_frame(zend_execute_data *call, zend_execute_data *old_prev_execute_data) {
5361 zend_execute_data *prev_execute_data = call->prev_execute_data;
5362 EG(current_execute_data) = prev_execute_data;
5363 call->prev_execute_data = old_prev_execute_data;
5364 if (UNEXPECTED(EG(exception)) && ZEND_USER_CODE(prev_execute_data->func->common.type)) {
5365 zend_rethrow_exception(prev_execute_data);
5366 }
5367}
5368
5370 zend_function *fbc = call->func;
5371 if (fbc->type == ZEND_USER_FUNCTION) {
5372 zend_op_array *op_array = &fbc->op_array;
5373 uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
5374 for (uint32_t i = 0; i < num_args; i++) {
5376 if (!Z_ISUNDEF_P(arg)) {
5377 continue;
5378 }
5379
5380 zend_op *opline = &op_array->opcodes[i];
5381 if (EXPECTED(opline->opcode == ZEND_RECV_INIT)) {
5382 zval *default_value = RT_CONSTANT(opline, opline->op2);
5383 if (Z_OPT_TYPE_P(default_value) == IS_CONSTANT_AST) {
5384 if (UNEXPECTED(!RUN_TIME_CACHE(op_array))) {
5385 init_func_run_time_cache(op_array);
5386 }
5387
5388 void *run_time_cache = RUN_TIME_CACHE(op_array);
5389 zval *cache_val =
5390 (zval *) ((char *) run_time_cache + Z_CACHE_SLOT_P(default_value));
5391
5392 if (Z_TYPE_P(cache_val) != IS_UNDEF) {
5393 /* We keep in cache only not refcounted values */
5394 ZVAL_COPY_VALUE(arg, cache_val);
5395 } else {
5396 /* Update constant inside a temporary zval, to make sure the CONSTANT_AST
5397 * value is not accessible through back traces. */
5398 zval tmp;
5399 ZVAL_COPY(&tmp, default_value);
5400 zend_execute_data *old = start_fake_frame(call, opline);
5401 zend_result ret = zval_update_constant_ex(&tmp, fbc->op_array.scope);
5402 end_fake_frame(call, old);
5403 if (UNEXPECTED(ret == FAILURE)) {
5404 zval_ptr_dtor_nogc(&tmp);
5405 return FAILURE;
5406 }
5407 ZVAL_COPY_VALUE(arg, &tmp);
5408 if (!Z_REFCOUNTED(tmp)) {
5409 ZVAL_COPY_VALUE(cache_val, &tmp);
5410 }
5411 }
5412 } else {
5413 ZVAL_COPY(arg, default_value);
5414 }
5415 } else {
5416 ZEND_ASSERT(opline->opcode == ZEND_RECV);
5417 zend_execute_data *old = start_fake_frame(call, opline);
5419 end_fake_frame(call, old);
5420 return FAILURE;
5421 }
5422 }
5423
5424 return SUCCESS;
5425 } else {
5426 if (fbc->common.fn_flags & ZEND_ACC_USER_ARG_INFO) {
5427 /* Magic function, let it deal with it. */
5428 return SUCCESS;
5429 }
5430
5431 uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
5432 for (uint32_t i = 0; i < num_args; i++) {
5434 if (!Z_ISUNDEF_P(arg)) {
5435 continue;
5436 }
5437
5438 zend_internal_arg_info *arg_info = &fbc->internal_function.arg_info[i];
5439 if (i < fbc->common.required_num_args) {
5440 zend_execute_data *old = start_fake_frame(call, NULL);
5442 end_fake_frame(call, old);
5443 return FAILURE;
5444 }
5445
5446 zval default_value;
5447 if (zend_get_default_from_internal_arg_info(&default_value, arg_info) == FAILURE) {
5448 zend_execute_data *old = start_fake_frame(call, NULL);
5450 "must be passed explicitly, because the default value is not known");
5451 end_fake_frame(call, old);
5452 return FAILURE;
5453 }
5454
5455 if (Z_TYPE(default_value) == IS_CONSTANT_AST) {
5456 zend_execute_data *old = start_fake_frame(call, NULL);
5457 zend_result ret = zval_update_constant_ex(&default_value, fbc->common.scope);
5458 end_fake_frame(call, old);
5459 if (ret == FAILURE) {
5460 return FAILURE;
5461 }
5462 }
5463
5464 ZVAL_COPY_VALUE(arg, &default_value);
5465 if (ZEND_ARG_SEND_MODE(arg_info) & ZEND_SEND_BY_REF) {
5467 }
5468 }
5469 }
5470
5471 return SUCCESS;
5472}
5473
5475{
5476 /* Extra named params may be shared. */
5477 zend_array_release(extra_named_params);
5478}
5479
5480#if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
5481/* Special versions of functions that sets EX(opline) before calling zend_vm_stack_extend() */
5482static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame_ex(uint32_t used_stack, uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) /* {{{ */
5483{
5484 zend_execute_data *call = (zend_execute_data*)EG(vm_stack_top);
5485
5487
5488 if (UNEXPECTED(used_stack > (size_t)(((char*)EG(vm_stack_end)) - (char*)call))) {
5489 EX(opline) = opline; /* this is the only difference */
5492 zend_vm_init_call_frame(call, call_info | ZEND_CALL_ALLOCATED, func, num_args, object_or_called_scope);
5493 return call;
5494 } else {
5495 EG(vm_stack_top) = (zval*)((char*)call + used_stack);
5496 zend_vm_init_call_frame(call, call_info, func, num_args, object_or_called_scope);
5497 return call;
5498 }
5499} /* }}} */
5500
5501static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint32_t call_info, zend_function *func, uint32_t num_args, void *object_or_called_scope) /* {{{ */
5502{
5503 uint32_t used_stack = zend_vm_calc_used_stack(num_args, func);
5504
5506 func, num_args, object_or_called_scope);
5507} /* }}} */
5508#else
5509# define _zend_vm_stack_push_call_frame_ex zend_vm_stack_push_call_frame_ex
5510# define _zend_vm_stack_push_call_frame zend_vm_stack_push_call_frame
5511#endif
5512
5513#ifdef ZEND_VM_TRACE_HANDLERS
5514# include "zend_vm_trace_handlers.h"
5515#elif defined(ZEND_VM_TRACE_LINES)
5516# include "zend_vm_trace_lines.h"
5517#elif defined(ZEND_VM_TRACE_MAP)
5518# include "zend_vm_trace_map.h"
5519#elif defined(ZEND_VERIFY_TYPE_INFERENCE)
5521#endif
5522
5523#define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
5524 CHECK_SYMBOL_TABLES() \
5525 if (check_exception) { \
5526 OPLINE = EX(opline) + (skip); \
5527 } else { \
5528 ZEND_ASSERT(!EG(exception)); \
5529 OPLINE = opline + (skip); \
5530 } \
5531 ZEND_VM_CONTINUE()
5532
5533#define ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() \
5534 ZEND_VM_NEXT_OPCODE_EX(1, 1)
5535
5536#define ZEND_VM_NEXT_OPCODE() \
5537 ZEND_VM_NEXT_OPCODE_EX(0, 1)
5538
5539#define ZEND_VM_SET_NEXT_OPCODE(new_op) \
5540 CHECK_SYMBOL_TABLES() \
5541 OPLINE = new_op
5542
5543#define ZEND_VM_SET_OPCODE_NO_INTERRUPT(new_op) \
5544 CHECK_SYMBOL_TABLES() \
5545 OPLINE = new_op
5546
5547#define ZEND_VM_SET_OPCODE(new_op) \
5548 ZEND_VM_SET_OPCODE_NO_INTERRUPT(new_op); \
5549 ZEND_VM_INTERRUPT_CHECK()
5550
5551#define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
5552 ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset))
5553
5554#define ZEND_VM_JMP_EX(new_op, check_exception) do { \
5555 if (check_exception && UNEXPECTED(EG(exception))) { \
5556 HANDLE_EXCEPTION(); \
5557 } \
5558 ZEND_VM_SET_OPCODE(new_op); \
5559 ZEND_VM_CONTINUE(); \
5560 } while (0)
5561
5562#define ZEND_VM_JMP(new_op) \
5563 ZEND_VM_JMP_EX(new_op, 1)
5564
5565#define ZEND_VM_INC_OPCODE() \
5566 OPLINE++
5567
5568
5569#define ZEND_VM_REPEATABLE_OPCODE \
5570 do {
5571#define ZEND_VM_REPEAT_OPCODE(_opcode) \
5572 } while (UNEXPECTED((++opline)->opcode == _opcode)); \
5573 OPLINE = opline; \
5574 ZEND_VM_CONTINUE()
5575#define ZEND_VM_SMART_BRANCH(_result, _check) do { \
5576 if ((_check) && UNEXPECTED(EG(exception))) { \
5577 OPLINE = EX(opline); \
5578 } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \
5579 if (_result) { \
5580 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5581 } else { \
5582 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5583 } \
5584 } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \
5585 if (!(_result)) { \
5586 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5587 } else { \
5588 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5589 } \
5590 } else { \
5591 ZVAL_BOOL(EX_VAR(opline->result.var), _result); \
5592 ZEND_VM_SET_NEXT_OPCODE(opline + 1); \
5593 } \
5594 ZEND_VM_CONTINUE(); \
5595 } while (0)
5596#define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) do { \
5597 if ((_check) && UNEXPECTED(EG(exception))) { \
5598 OPLINE = EX(opline); \
5599 } else if (_result) { \
5600 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5601 } else { \
5602 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5603 } \
5604 ZEND_VM_CONTINUE(); \
5605 } while (0)
5606#define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) do { \
5607 if ((_check) && UNEXPECTED(EG(exception))) { \
5608 OPLINE = EX(opline); \
5609 } else if (!(_result)) { \
5610 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5611 } else { \
5612 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5613 } \
5614 ZEND_VM_CONTINUE(); \
5615 } while (0)
5616#define ZEND_VM_SMART_BRANCH_NONE(_result, _check) do { \
5617 ZVAL_BOOL(EX_VAR(opline->result.var), _result); \
5618 ZEND_VM_NEXT_OPCODE_EX(_check, 1); \
5619 ZEND_VM_CONTINUE(); \
5620 } while (0)
5621#define ZEND_VM_SMART_BRANCH_TRUE() do { \
5622 if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \
5623 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5624 } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \
5625 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5626 } else { \
5627 ZVAL_TRUE(EX_VAR(opline->result.var)); \
5628 ZEND_VM_SET_NEXT_OPCODE(opline + 1); \
5629 } \
5630 ZEND_VM_CONTINUE(); \
5631 } while (0)
5632#define ZEND_VM_SMART_BRANCH_TRUE_JMPZ() do { \
5633 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5634 ZEND_VM_CONTINUE(); \
5635 } while (0)
5636#define ZEND_VM_SMART_BRANCH_TRUE_JMPNZ() do { \
5637 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5638 ZEND_VM_CONTINUE(); \
5639 } while (0)
5640#define ZEND_VM_SMART_BRANCH_TRUE_NONE() do { \
5641 ZVAL_TRUE(EX_VAR(opline->result.var)); \
5642 ZEND_VM_NEXT_OPCODE(); \
5643 } while (0)
5644#define ZEND_VM_SMART_BRANCH_FALSE() do { \
5645 if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPNZ|IS_TMP_VAR))) { \
5646 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5647 } else if (EXPECTED(opline->result_type == (IS_SMART_BRANCH_JMPZ|IS_TMP_VAR))) { \
5648 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5649 } else { \
5650 ZVAL_FALSE(EX_VAR(opline->result.var)); \
5651 ZEND_VM_SET_NEXT_OPCODE(opline + 1); \
5652 } \
5653 ZEND_VM_CONTINUE(); \
5654 } while (0)
5655#define ZEND_VM_SMART_BRANCH_FALSE_JMPZ() do { \
5656 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
5657 ZEND_VM_CONTINUE(); \
5658 } while (0)
5659#define ZEND_VM_SMART_BRANCH_FALSE_JMPNZ() do { \
5660 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
5661 ZEND_VM_CONTINUE(); \
5662 } while (0)
5663#define ZEND_VM_SMART_BRANCH_FALSE_NONE() do { \
5664 ZVAL_FALSE(EX_VAR(opline->result.var)); \
5665 ZEND_VM_NEXT_OPCODE(); \
5666 } while (0)
5667
5668#ifdef __GNUC__
5669# define ZEND_VM_GUARD(name) __asm__("#" #name)
5670#else
5671# define ZEND_VM_GUARD(name)
5672#endif
5673
5674#define UNDEF_RESULT() do { \
5675 if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { \
5676 ZVAL_UNDEF(EX_VAR(opline->result.var)); \
5677 } \
5678 } while (0)
5679
5680/* This callback disables optimization of "vm_stack_data" variable in VM */
5681ZEND_API void (ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data) = NULL;
5682
5683#include "zend_vm_execute.h"
5684
5686{
5687 if (opcode != ZEND_USER_OPCODE) {
5688 if (handler == NULL) {
5689 /* restore the original handler */
5690 zend_user_opcodes[opcode] = opcode;
5691 } else {
5692 zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
5693 }
5694 zend_user_opcode_handlers[opcode] = handler;
5695 return SUCCESS;
5696 }
5697 return FAILURE;
5698}
5699
5701{
5702 return zend_user_opcode_handlers[opcode];
5703}
5704
5705ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data)
5706{
5707 zval *ret;
5708
5709 switch (op_type) {
5710 case IS_CONST:
5711 ret = RT_CONSTANT(opline, *node);
5712 break;
5713 case IS_TMP_VAR:
5714 case IS_VAR:
5715 case IS_CV:
5716 ret = EX_VAR(node->var);
5717 break;
5718 default:
5719 ret = NULL;
5720 break;
5721 }
5722 return ret;
5723}
size_t len
Definition apprentice.c:174
bool exception
Definition assert.c:30
fprintf($stream, string $format, mixed ... $values)
prev(array|object &$array)
copy(string $from, string $to, $context=null)
constant(string $name)
count(Countable|array $value, int $mode=COUNT_NORMAL)
fflush($stream)
char s[4]
Definition cdf.c:77
DNS_STATUS status
Definition dns_win32.c:49
zend_ffi_type * type
Definition ffi.c:3812
zval * zv
Definition ffi.c:3975
new_type size
Definition ffi.c:4365
new_type kind
Definition ffi.c:4363
zend_string * res
Definition ffi.c:4692
void * ptr
Definition ffi.c:3814
zval * arg
Definition ffi.c:3975
memset(ptr, 0, type->size)
zval * val
Definition ffi.c:4262
HashTable * ht
Definition ffi.c:4838
zend_ffi_ctype_name_buf buf
Definition ffi.c:4685
zend_ffi_type * old_type
Definition ffi.c:3971
zend_long offset
#define NULL
Definition gdcache.h:45
#define SUCCESS
Definition hash_sha3.c:261
#define pass(a, b, c, mul)
Definition hash_tiger.c:50
again j
char * arena
Definition php_bcmath.h:37
unsigned const char * end
Definition php_ffi.h:51
unsigned char key[REFLECTION_KEY_LEN]
char * msg
Definition phpdbg.h:289
phpdbg_frame_t frame
Definition phpdbg.h:236
const char * func_name
zend_string * lcname
zend_object * ex
zval rv
Definition session.c:1024
p
Definition session.c:1105
zend_string * name
zend_class_entry * ce
zend_object_iterator *(* get_iterator)(zend_class_entry *ce, zval *object, int by_ref)
Definition zend.h:198
zend_string * name
Definition zend.h:149
uint32_t ce_flags
Definition zend.h:156
char type
Definition zend.h:148
zend_function *(* get_static_method)(zend_class_entry *ce, zend_string *method)
Definition zend.h:199
zend_class_entry * parent
Definition zend.h:152
zend_string * name
fcall_end_handler_func_t fcall_end_handler
fcall_begin_handler_func_t fcall_begin_handler
statement_handler_func_t statement_handler
zend_string * opened_path
Definition zend_stream.h:59
zend_internal_arg_info * arg_info
zend_object_read_dimension_t read_dimension
zend_object_write_dimension_t write_dimension
void(* rewind)(zend_object_iterator *iter)
zend_result(* valid)(zend_object_iterator *iter)
const zend_object_iterator_funcs * funcs
zend_class_entry * ce
Definition zend_types.h:560
const zend_object_handlers * handlers
Definition zend_types.h:561
uint32_t num_args
zend_op * opcodes
zend_live_range * live_range
uint32_t fn_flags
znode_op op1
znode_op op2
znode_op result
uint8_t opcode
uint8_t op1_type
uint32_t extended_value
uint8_t op2_type
zend_string * name
zend_class_entry * ce
zend_vm_stack prev
Definition dce.c:49
struct _zend_property_info * ptr[1]
Definition zend_types.h:576
zend_arg_info * arg_info
zend_class_entry * scope
zend_string * function_name
struct _zend_function::@236135173067030250234125302313220025134003177336 common
uint32_t fn_flags
zend_internal_function internal_function
uint32_t var
uint32_t num
struct _zend_property_info * ptr
Definition zend_types.h:580
ZEND_API ZEND_COLD void zend_error_unchecked(int type, const char *format,...)
Definition zend.c:1670
ZEND_API char * zend_make_compiled_string_description(const char *name)
Definition zend.c:1980
ZEND_API ZEND_COLD ZEND_NORETURN void zend_error_noreturn(int type, const char *format,...)
Definition zend.c:1703
ZEND_API zend_string * zend_strpprintf_unchecked(size_t max_len, const char *format,...)
Definition zend.c:365
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format,...)
Definition zend.c:1772
ZEND_API ZEND_COLD void zend_type_error(const char *format,...)
Definition zend.c:1824
ZEND_API ZEND_COLD void zend_error(int type, const char *format,...)
Definition zend.c:1666
ZEND_API zend_string *(* zend_resolve_path)(zend_string *filename)
Definition zend.c:94
ZEND_API ZEND_COLD void zend_illegal_container_offset(const zend_string *container, const zval *offset, int type)
Definition zend.c:1802
ZEND_API void(* zend_interrupt_function)(zend_execute_data *execute_data)
Definition zend.c:89
ZEND_API void zend_message_dispatcher(zend_long message, const void *data)
Definition zend.c:1393
#define ZMSG_FAILED_REQUIRE_FOPEN
Definition zend.h:424
#define ZMSG_FAILED_INCLUDE_FOPEN
Definition zend.h:423
ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(const zval *arg, zend_long *dest, uint32_t arg_num)
Definition zend_API.c:557
ZEND_API zval * zend_read_property_ex(zend_class_entry *scope, zend_object *object, zend_string *name, bool silent, zval *rv)
Definition zend_API.c:5187
ZEND_API const char * zend_zval_value_name(const zval *arg)
Definition zend_API.c:148
ZEND_API const char * zend_get_type_by_const(int type)
Definition zend_API.c:112
ZEND_API zend_result zend_get_default_from_internal_arg_info(zval *default_value_zval, zend_internal_arg_info *arg_info)
Definition zend_API.c:5352
ZEND_API const char * zend_zval_type_name(const zval *arg)
Definition zend_API.c:167
ZEND_API ZEND_COLD void zend_argument_error(zend_class_entry *error_ce, uint32_t arg_num, const char *format,...)
Definition zend_API.c:413
ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, bool *dest, uint32_t arg_num)
Definition zend_API.c:526
ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *dest, uint32_t arg_num)
Definition zend_API.c:644
ZEND_API ZEND_COLD void zend_argument_type_error(uint32_t arg_num, const char *format,...)
Definition zend_API.c:423
ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num)
Definition zend_API.c:751
ZEND_API bool zend_is_callable(zval *callable, uint32_t check_flags, zend_string **callable_name)
Definition zend_API.c:4286
#define IS_CALLABLE_SUPPRESS_DEPRECATIONS
Definition zend_API.h:412
#define ZEND_FN(name)
Definition zend_API.h:71
#define ZVAL_CHAR(z, c)
Definition zend_API.h:978
#define ZEND_END_ARG_INFO()
Definition zend_API.h:219
ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data)
#define ZEND_BEGIN_ARG_INFO_EX(name, _unused, return_reference, required_num_args)
Definition zend_API.h:214
ZEND_API zend_array * zend_rebuild_symbol_table(void)
#define ZEND_FUNCTION(name)
Definition zend_API.h:75
#define array_init(arg)
Definition zend_API.h:537
#define ZVAL_EMPTY_STRING(z)
Definition zend_API.h:961
#define efree_size(ptr, size)
Definition zend_alloc.h:138
#define efree(ptr)
Definition zend_alloc.h:155
#define erealloc(ptr, size)
Definition zend_alloc.h:159
#define emalloc(size)
Definition zend_alloc.h:151
ZEND_API zend_result zend_get_attribute_object(zval *obj, zend_class_entry *attribute_ce, zend_attribute *attribute_data, zend_class_entry *scope, zend_string *filename)
ZEND_API zend_attribute * zend_get_attribute_str(HashTable *attributes, const char *str, size_t len)
ZEND_API zend_class_entry * zend_ce_deprecated
struct _zend_attribute zend_attribute
struct _zval_struct zval
error_reporting(?int $error_level=null)
strlen(string $string)
uint32_t num_args
zend_string_release_ex(func->internal_function.function_name, 0)
execute_data func
#define ZEND_CLOSURE_OBJECT(op_array)
ZEND_API zend_op_array *(* zend_compile_file)(zend_file_handle *file_handle, int type)
ZEND_API zend_op_array *(* zend_compile_string)(zend_string *source_string, const char *filename, zend_compile_position position)
ZEND_API zend_string * zend_type_to_string(zend_type type)
zend_string * zend_type_to_string_resolved(zend_type type, zend_class_entry *scope)
#define BP_VAR_R
zend_result(ZEND_FASTCALL * binary_op_type)(zval *, zval *, zval *)
#define ZEND_RET_USES_STRICT_TYPES()
ZEND_API zend_op_array * compile_filename(int type, zend_string *filename)
#define ZEND_FETCH_CLASS_SELF
#define ZEND_CALL_CLOSURE
#define ZEND_FETCH_DIM_REF
#define ZEND_LIVE_MASK
#define ZEND_LIVE_TMPVAR
struct _zend_op zend_op
#define ZEND_FETCH_CLASS_AUTO
#define ZEND_LIVE_LOOP
#define ZEND_USER_CODE(type)
#define EX_VAR_NUM(n)
#define ZEND_LIVE_NEW
#define IS_UNUSED
#define ZEND_ACC_FAKE_CLOSURE
#define ZEND_FETCH_CLASS_MASK
#define ZEND_CALL_ALLOCATED
#define ZEND_FETCH_GLOBAL_LOCK
#define IS_CONST
#define ZEND_ACC_HAS_TYPE_HINTS
#define BP_VAR_W
#define ZEND_SEND_BY_REF
#define ZEND_INTERNAL_FUNCTION
#define ZEND_EVAL
#define EX_VAR_TO_NUM(n)
#define IS_VAR
#define ZEND_CLASS_CONST_FLAGS(c)
#define EX_NUM_ARGS()
#define ZEND_ACC_READONLY
#define ZEND_ACC_PROTECTED_SET
#define RUN_TIME_CACHE(op_array)
#define ZEND_FETCH_DIM_DIM
#define ZEND_ARG_SEND_MODE(arg_info)
#define ZEND_ACC_PPP_SET_MASK
#define ZEND_FETCH_CLASS_NO_AUTOLOAD
#define ZEND_ACC_USER_ARG_INFO
#define ZEND_CALL_NESTED_FUNCTION
#define EX(element)
#define ZEND_USER_FUNCTION
#define EX_CALL_INFO()
int(* user_opcode_handler_t)(zend_execute_data *execute_data)
#define ZEND_CALL_HAS_SYMBOL_TABLE
#define ZEND_ACC_PRIVATE_SET
#define ZEND_ACC_CALL_VIA_TRAMPOLINE
#define ZEND_REQUIRE
struct _zend_op_array zend_op_array
#define ZEND_CALL_HAS_THIS
union _znode_op znode_op
#define EX_USES_STRICT_TYPES()
#define OBJ_PROP(obj, offset)
struct _zend_class_constant zend_class_constant
struct _zend_property_info zend_property_info
#define ZEND_CALL_HAS_EXTRA_NAMED_PARAMS
#define ZEND_ACC_TRAIT
#define ZEND_FETCH_DIM_INCDEC
#define ZEND_FETCH_REF
#define ZEND_FETCH_DIM_WRITE
#define ZEND_FETCH_CLASS_DEFAULT
struct _zend_internal_arg_info zend_internal_arg_info
#define ZEND_EXTRA_VALUE
#define ZEND_INCLUDE_ONCE
#define ZEND_CALL_NUM_ARGS(call)
#define RT_CONSTANT(opline, node)
#define ZEND_ACC_STATIC
#define ZEND_FETCH_CLASS_EXCEPTION
ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
#define ZEND_CALL_INFO(call)
#define ZEND_FETCH_CLASS_PARENT
struct _zend_arg_info zend_arg_info
@ ZEND_COMPILE_POSITION_AFTER_OPEN_TAG
#define EX_VAR(n)
#define ZEND_CALL_DYNAMIC
#define ZEND_ACC_HEAP_RT_CACHE
#define ZEND_FETCH_OBJ_FLAGS
#define ZEND_LIVE_ROPE
#define ZEND_FETCH_GLOBAL
#define ZEND_REQUIRE_ONCE
#define ZEND_ACC_VARIADIC
#define ZEND_INCLUDE
#define ZEND_ADD_CALL_FLAG(call, flag)
#define ZEND_CALL_FREE_EXTRA_ARGS
#define ZEND_LIVE_SILENCE
#define ZEND_CALL_MAY_HAVE_UNDEF
#define IS_CV
#define IS_TMP_VAR
#define ZEND_CLASS_CONST_IS_CASE
#define ZEND_IS_INCREMENT(opcode)
#define BP_VAR_RW
struct _zend_live_range zend_live_range
#define ZEND_INTERNAL_CLASS
#define ZEND_FETCH_LOCAL
struct _zend_internal_function zend_internal_function
#define ZEND_CALL_RELEASE_THIS
#define ZEND_FETCH_CLASS_SILENT
#define IS_CONSTANT_UNQUALIFIED_IN_NAMESPACE
#define ZEND_RETURNS_FUNCTION
char * zend_visibility_string(uint32_t fn_flags)
#define BP_VAR_IS
#define ZEND_ACC_CLOSURE
#define BP_VAR_UNSET
#define ZEND_ARG_USES_STRICT_TYPES()
#define ZEND_FETCH_DIM_OBJ
#define ZEND_CALL_VAR_NUM(call, n)
#define ZEND_CALL_ARG(call, n)
#define ZEND_CALL_FAKE_CLOSURE
#define ZEND_API
#define ZEND_CONSTANT_FLAGS(c)
struct _zend_constant zend_constant
#define CONST_DEPRECATED
#define E_NOTICE
Definition zend_errors.h:26
#define E_ERROR
Definition zend_errors.h:23
#define E_WARNING
Definition zend_errors.h:24
#define E_CORE_ERROR
Definition zend_errors.h:27
#define E_HAS_ONLY_FATAL_ERRORS(mask)
Definition zend_errors.h:49
#define E_USER_DEPRECATED
Definition zend_errors.h:38
#define E_DEPRECATED
Definition zend_errors.h:37
ZEND_API zend_class_entry * zend_ce_unhandled_match_error
ZEND_API zend_class_entry * zend_ce_argument_count_error
ZEND_API ZEND_COLD zend_object * zend_throw_exception_ex(zend_class_entry *exception_ce, zend_long code, const char *format,...)
ZEND_API zend_class_entry * zend_ce_error
ZEND_API void ZEND_FASTCALL zend_free_extra_named_params(zend_array *extra_named_params)
ZEND_API HashTable * zend_unfinished_execution_gc_ex(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer, bool suspended_by_yield)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_indirect_modification_error(const zend_property_info *info)
ZEND_API bool zend_verify_ref_array_assignable(zend_reference *ref)
ZEND_API void zend_vm_stack_init_ex(size_t page_size)
ZEND_API void zend_unfinished_calls_gc(zend_execute_data *execute_data, zend_execute_data *call, uint32_t op_num, zend_get_gc_buffer *buf)
ZEND_API bool zend_check_user_type_slow(zend_type *type, zval *arg, zend_reference *ref, void **cache_slot, bool is_return_type)
ZEND_API void ZEND_FASTCALL zend_init_func_run_time_cache(zend_op_array *op_array)
ZEND_API void zend_frameless_observed_call(zend_execute_data *execute_data)
ZEND_API void zend_init_func_execute_data(zend_execute_data *ex, zend_op_array *op_array, zval *return_value)
#define OPLINE_DC
#define EXECUTE_DATA_CC
ZEND_API ZEND_COLD zval *ZEND_FASTCALL zend_undefined_offset_write(HashTable *ht, zend_long lval)
#define ZEND_FAKE_OP_ARRAY
ZEND_API const zend_internal_function zend_pass_function
ZEND_API zval * zend_assign_to_typed_ref(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict)
#define EXECUTE_DATA_D
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error_ex(const char *class_name, const char *prop_name)
#define _zend_vm_stack_push_call_frame
#define PROGRESS_CACHE_SLOT()
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_fcall_interrupt(zend_execute_data *call)
ZEND_API ZEND_ATTRIBUTE_DEPRECATED HashTable * zend_unfinished_execution_gc(zend_execute_data *execute_data, zend_execute_data *call, zend_get_gc_buffer *gc_buffer)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_invalid_class_constant_type_error(uint8_t type)
#define get_zval_ptr_undef(op_type, node, type)
#define EXECUTE_DATA_DC
ZEND_COLD void zend_match_unhandled_error(const zval *value)
ZEND_API zend_function *ZEND_FASTCALL zend_fetch_function(zend_string *name)
#define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size, page_size)
#define get_op_data_zval_ptr_r(op_type, node)
ZEND_API ZEND_COLD void zend_verify_arg_error(const zend_function *zf, const zend_arg_info *arg_info, uint32_t arg_num, zval *value)
ZEND_API bool zend_never_inline zend_verify_property_type(const zend_property_info *info, zval *property, bool strict)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_class_constant(const zend_class_constant *c, const zend_string *constant_name)
#define get_zval_ptr_ptr(op_type, node, type)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc)
ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num)
#define get_zval_ptr(op_type, node, type)
#define CV_DEF_OF(i)
ZEND_API ZEND_COLD void zend_verify_never_error(const zend_function *zf)
ZEND_API bool zend_never_inline zend_verify_class_constant_type(zend_class_constant *c, const zend_string *name, zval *constant)
ZEND_API void zend_vm_stack_destroy(void)
ZEND_API void zend_vm_stack_init(void)
#define OPLINE_CC
ZEND_API zend_result zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
#define HAVE_CACHE_SLOT
ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value)
ZEND_API void ZEND_FASTCALL zend_free_compiled_variables(zend_execute_data *execute_data)
ZEND_API zend_result ZEND_FASTCALL zend_handle_undef_args(zend_execute_data *call)
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref(const zend_property_info *prop_info, zval *orig_val, bool strict)
ZEND_API ZEND_COLD void zend_throw_conflicting_coercion_error(const zend_property_info *prop1, const zend_property_info *prop2, const zval *zv)
ZEND_API zend_function *ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_object_released_while_assigning_to_property_error(const zend_property_info *info)
ZEND_API bool zend_gcc_global_regs(void)
ZEND_API zval * zend_assign_to_typed_ref_ex(zval *variable_ptr, zval *orig_value, uint8_t value_type, bool strict, zend_refcounted **garbage_ptr)
#define ZEND_VM_STACK_PAGE_SIZE
#define EXECUTE_DATA_C
ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value)
ZEND_API ZEND_COLD void zend_throw_ref_type_error_type(const zend_property_info *prop1, const zend_property_info *prop2, const zval *zv)
#define RETURN_VALUE_USED(opline)
ZEND_API void zend_fetch_dimension_const(zval *result, zval *container, zval *dim, int type)
#define ZVAL_UNDEFINED_OP1()
#define NO_EXECUTE_DATA_CC
ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict)
ZEND_API void ZEND_FASTCALL zend_ref_add_type_source(zend_property_info_source_list *source_list, zend_property_info *prop)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim)
ZEND_COLD zend_never_inline void zend_verify_class_constant_type_error(const zend_class_constant *c, const zend_string *name, const zval *constant)
ZEND_API bool zend_verify_scalar_type_hint(uint32_t type_mask, zval *arg, bool strict, bool is_internal_arg)
ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num)
ZEND_COLD zend_never_inline void zend_verify_property_type_error(const zend_property_info *info, const zval *property)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_asymmetric_visibility_property_modification_error(const zend_property_info *prop_info, const char *operation)
ZEND_API ZEND_COLD zval *ZEND_FASTCALL zend_undefined_index_write(HashTable *ht, zend_string *offset)
#define FREE_OP(type, var)
ZEND_API ZEND_COLD void zend_wrong_string_offset_error(void)
ZEND_API bool ZEND_FASTCALL zend_verify_prop_assignable_by_ref_ex(const zend_property_info *prop_info, zval *orig_val, bool strict, zend_verify_prop_assignable_by_ref_context context)
ZEND_API zval * zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
#define _zend_vm_stack_push_call_frame_ex
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data)
#define ZVAL_UNDEFINED_OP2()
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_list *source_list, const zend_property_info *prop)
int(ZEND_FASTCALL * incdec_t)(zval *)
zend_execute_data * zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args)
ZEND_API zval * zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data)
ZEND_COLD zend_never_inline void zend_magic_get_property_type_inconsistency_error(const zend_property_info *info, const zval *property)
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void)
ZEND_API void * zend_vm_stack_extend(size_t size)
ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value)
ZEND_API ZEND_COLD void zend_throw_ref_type_error_zval(const zend_property_info *prop, const zval *zv)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_cannot_pass_by_reference(uint32_t arg_num)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_readonly_property_modification_error(const zend_property_info *info)
zval *ZEND_FASTCALL zend_handle_named_arg(zend_execute_data **call_ptr, zend_string *arg_name, uint32_t *arg_num_ptr, void **cache_slot)
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void)
ZEND_API ZEND_COLD void zend_verify_return_error(const zend_function *zf, zval *value)
#define CACHED_PTR_EX(slot)
ZEND_API zend_class_entry * zend_get_called_scope(zend_execute_data *ex)
#define ZEND_REF_FOREACH_TYPE_SOURCES(ref, prop)
#define ZEND_REF_HAS_TYPE_SOURCES(ref)
#define ZEND_REF_DEL_TYPE_SOURCE(ref, source)
ZEND_API const char * get_function_arg_name(const zend_function *func, uint32_t arg_num)
#define ZEND_VM_STACK_ELEMENTS(stack)
ZEND_API zend_string * get_function_or_method_name(const zend_function *func)
#define ZEND_ASSERT_VM_STACK_GLOBAL
#define ZEND_VM_STACK_HEADER_SLOTS
ZEND_API zend_class_entry * zend_fetch_class(zend_string *class_name, uint32_t fetch_type)
ZEND_API zend_class_entry * zend_fetch_class_by_name(zend_string *class_name, zend_string *lcname, uint32_t fetch_type)
ZEND_API zend_result ZEND_FASTCALL zval_update_constant_ex(zval *pp, zend_class_entry *scope)
#define CACHED_PTR(num)
ZEND_API zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_call_stack_size_error(void)
#define ZEND_REF_FOREACH_TYPE_SOURCES_END()
ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void)
#define CACHE_PTR(num, ptr)
#define ZEND_REF_FIRST_SOURCE(ref)
#define ZEND_REF_ADD_TYPE_SOURCE(ref, source)
#define CACHE_ADDR(num)
ZEND_API bool ZEND_FASTCALL zend_asymmetric_property_has_set_access(const zend_property_info *prop_info)
zend_verify_prop_assignable_by_ref_context
@ ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_MAGIC_GET
@ ZEND_VERIFY_PROP_ASSIGNABLE_BY_REF_CONTEXT_ASSIGNMENT
ZEND_API zend_class_entry * zend_lookup_class_ex(zend_string *name, zend_string *lcname, uint32_t flags)
#define CACHE_POLYMORPHIC_PTR(num, ce, ptr)
struct _zend_extension zend_extension
union _zend_function zend_function
#define ZEND_FLF_NUM_ARGS(opcode)
#define ZEND_FLF_FUNC(opline)
uint32_t zend_get_internal_func_info(const zend_function *callee_func, const zend_call_info *call_info, const zend_ssa *ssa)
struct _zend_generator zend_generator
struct _zend_vm_stack * zend_vm_stack
#define CG(v)
#define EG(v)
ZEND_API void ZEND_FASTCALL zend_hash_apply(HashTable *ht, apply_func_t apply_func)
Definition zend_hash.c:2059
ZEND_API zval *ZEND_FASTCALL zend_hash_str_find(const HashTable *ht, const char *str, size_t len)
Definition zend_hash.c:2689
ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht)
Definition zend_hash.c:1946
ZEND_API zval *ZEND_FASTCALL zend_hash_next_index_insert(HashTable *ht, zval *pData)
Definition zend_hash.c:1224
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add_new(HashTable *ht, zend_ulong h, zval *pData)
Definition zend_hash.c:1214
ZEND_API zval *ZEND_FASTCALL zend_hash_lookup(HashTable *ht, zend_string *key)
Definition zend_hash.c:1012
ZEND_API zval *ZEND_FASTCALL zend_hash_add_new(HashTable *ht, zend_string *key, zval *pData)
Definition zend_hash.c:1007
ZEND_API zval *ZEND_FASTCALL zend_hash_find_known_hash(const HashTable *ht, const zend_string *key)
Definition zend_hash.c:2679
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
Definition zend_hash.c:1808
ZEND_API HashTable *ZEND_FASTCALL zend_array_dup(HashTable *source)
Definition zend_hash.c:2438
ZEND_API zval *ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key)
Definition zend_hash.c:1067
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
Definition zend_hash.c:2668
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
Definition zend_hash.c:2701
ZEND_API void ZEND_FASTCALL zend_hash_iterator_del(uint32_t idx)
Definition zend_hash.c:649
#define ZEND_HASH_INDEX_LOOKUP(_ht, _h, _ret)
Definition zend_hash.h:219
#define zend_new_array(size)
Definition zend_hash.h:338
#define ZEND_HASH_INDEX_FIND(_ht, _h, _ret, _not_found)
Definition zend_hash.h:196
#define ZEND_HANDLE_NUMERIC(key, idx)
Definition zend_hash.h:420
#define ZEND_HASH_FOREACH_STR_KEY_VAL(ht, _key, _val)
Definition zend_hash.h:1166
#define ZEND_HASH_FOREACH_END()
Definition zend_hash.h:1086
#define ZEND_HASH_FOREACH_VAL(ht, _val)
Definition zend_hash.h:1102
struct _zend_file_handle zend_file_handle
struct _zend_object_iterator zend_object_iterator
int32_t zend_long
Definition zend_long.h:42
#define ZEND_LONG_MIN
Definition zend_long.h:46
uint32_t zend_ulong
Definition zend_long.h:43
#define ZEND_LONG_FMT
Definition zend_long.h:87
#define ZEND_LONG_MAX
Definition zend_long.h:45
struct _zend_string zend_string
#define ZEND_MAP_PTR_INIT(ptr, val)
#define ZEND_MAP_PTR(ptr)
#define ZEND_MAP_PTR_SET(ptr, val)
ZEND_API zval * zend_std_get_static_property_with_info(zend_class_entry *ce, zend_string *property_name, int type, zend_property_info **property_info_ptr)
ZEND_API zend_result zend_std_cast_object_tostring(zend_object *readobj, zval *writeobj, int type)
ZEND_API zend_function * zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key)
#define IS_HOOKED_PROPERTY_OFFSET(offset)
#define IS_VALID_PROPERTY_OFFSET(offset)
#define zend_free_trampoline(func)
#define IS_DYNAMIC_PROPERTY_OFFSET(offset)
ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object)
#define OBJ_RELEASE(obj)
ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin_prechecked(zend_execute_data *execute_data, zend_observer_fcall_begin_handler *handler)
#define ZEND_OBSERVER_DATA(function)
ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1)
ZEND_API bool ZEND_FASTCALL zend_is_identical(const zval *op1, const zval *op2)
ZEND_API zend_result ZEND_FASTCALL shift_right_function(zval *result, zval *op1, zval *op2)
ZEND_API void ZEND_COLD zend_incompatible_double_to_long_error(double d)
ZEND_API zend_result ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL shift_left_function(zval *result, zval *op1, zval *op2)
ZEND_API char *ZEND_FASTCALL zend_str_tolower_copy(char *dest, const char *source, size_t length)
ZEND_API zend_string *ZEND_FASTCALL zval_try_get_string_func(zval *op)
ZEND_API zend_result ZEND_FASTCALL concat_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(const zval *op, bool is_strict)
ZEND_API zend_result ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1)
ZEND_API zend_result ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op2)
ZEND_API uint8_t ZEND_FASTCALL is_numeric_str_function(const zend_string *str, zend_long *lval, double *dval)
ZEND_API zend_result ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2)
ZEND_API zend_result ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2)
int last
#define ZEND_ATTRIBUTE_DEPRECATED
#define zend_never_inline
#define ZEND_ATTRIBUTE_UNUSED
#define ZEND_FALLTHROUGH
#define EXPECTED(condition)
#define zend_always_inline
#define ZEND_CONST_COND(_condition, _default)
#define ZEND_FASTCALL
#define ZEND_ASSERT(c)
#define ZEND_COLD
#define EMPTY_SWITCH_DEFAULT_CASE()
#define UNEXPECTED(condition)
struct _zend_array zend_array
struct _zend_class_entry zend_class_entry
struct _zend_object zend_object
ZEND_API zend_result ZEND_FASTCALL smart_str_append_zval(smart_str *dest, const zval *value, size_t truncate)
ZEND_API void zend_stream_init_filename_ex(zend_file_handle *handle, zend_string *filename)
Definition zend_stream.c:76
ZEND_API zend_result zend_stream_open(zend_file_handle *handle)
Definition zend_stream.c:82
#define ZSTR_H(zstr)
Definition zend_string.h:70
#define ZSTR_VAL(zstr)
Definition zend_string.h:68
#define ZSTR_KNOWN(idx)
#define ZSTR_EMPTY_ALLOC()
#define ZSTR_LEN(zstr)
Definition zend_string.h:69
#define zend_string_equals_literal_ci(str, c)
#define dval(x)
#define MAY_BE_STRING
#define MAY_BE_RC1
#define MAY_BE_FALSE
#define MAY_BE_ARRAY_SHIFT
#define MAY_BE_BOOL
#define MAY_BE_ARRAY_KEY_STRING
#define MAY_BE_STATIC
#define MAY_BE_DOUBLE
#define MAY_BE_VOID
#define MAY_BE_NEVER
#define MAY_BE_LONG
#define MAY_BE_TRUE
#define MAY_BE_ARRAY_KEY_LONG
#define MAY_BE_CALLABLE
#define MAY_BE_RCN
#define MAY_BE_ARRAY
#define Z_TYPE_P(zval_p)
Definition zend_types.h:660
#define IS_TRUE
Definition zend_types.h:603
#define GC_DTOR(p)
Definition zend_types.h:716
#define ZEND_TYPE_PURE_MASK(t)
Definition zend_types.h:257
#define Z_ISREF_P(zval_p)
Definition zend_types.h:954
#define Z_TRY_ADDREF_P(pz)
#define ZEND_TYPE_NAME(t)
Definition zend_types.h:198
#define ZVAL_UNDEF(z)
#define Z_REFVAL_P(zval_p)
#define IS_FALSE
Definition zend_types.h:602
#define Z_STRVAL_P(zval_p)
Definition zend_types.h:975
#define IS_UNDEF
Definition zend_types.h:600
#define Z_ISUNDEF_P(zval_p)
Definition zend_types.h:957
#define Z_ARRVAL_P(zval_p)
Definition zend_types.h:987
#define IS_STR_INTERNED
Definition zend_types.h:817
#define ZVAL_NULL(z)
#define ZVAL_DEREF(z)
#define ZVAL_LONG(z, l)
#define IS_STRING
Definition zend_types.h:606
#define GC_DTOR_NO_REF(p)
Definition zend_types.h:726
#define ZEND_PROPERTY_INFO_SOURCE_TO_LIST(list)
Definition zend_types.h:585
#define ZEND_TYPE_IS_INTERSECTION(t)
Definition zend_types.h:186
#define Z_REFCOUNTED_P(zval_p)
Definition zend_types.h:921
#define Z_FE_ITER_P(zval_p)
Definition zend_types.h:687
#define ZVAL_INDIRECT(z, v)
struct _zend_array HashTable
Definition zend_types.h:386
#define IS_RESOURCE
Definition zend_types.h:609
union _zend_value zend_value
#define Z_OBJ_P(zval_p)
Definition zend_types.h:990
#define IS_ARRAY
Definition zend_types.h:607
#define ZVAL_COPY_OR_DUP(z, v)
#define IS_PROP_REINITABLE
#define Z_OBJ_HT_P(zval_p)
Definition zend_types.h:993
#define ZEND_TYPE_HAS_NAME(t)
Definition zend_types.h:174
#define ZVAL_COPY_DEREF(z, v)
#define IS_DOUBLE
Definition zend_types.h:605
#define Z_TYPE_INFO_P(zval_p)
Definition zend_types.h:669
#define Z_ISUNDEF(zval)
Definition zend_types.h:956
#define Z_COUNTED_P(zval_p)
Definition zend_types.h:699
#define Z_STR_P(zval_p)
Definition zend_types.h:972
#define Z_PTR_P(zval_p)
#define ZVAL_NEW_REF(z, r)
#define GC_DELREF(p)
Definition zend_types.h:710
#define GC_FLAGS(p)
Definition zend_types.h:756
#define ZSTR_HAS_CE_CACHE(s)
Definition zend_types.h:841
#define GC_ADDREF(p)
Definition zend_types.h:709
#define Z_FUNC_P(zval_p)
#define ZEND_TYPE_FULL_MASK(t)
Definition zend_types.h:254
#define Z_ADDREF_P(pz)
#define ZEND_TYPE_HAS_LIST(t)
Definition zend_types.h:180
#define Z_REFCOUNTED(zval)
Definition zend_types.h:917
#define Z_STRLEN_P(zval_p)
Definition zend_types.h:978
#define ZVAL_UNREF(z)
#define ZEND_TYPE_LIST_FOREACH_END()
Definition zend_types.h:217
#define IS_NULL
Definition zend_types.h:601
#define Z_OBJCE_P(zval_p)
#define ZVAL_OBJ(z, o)
@ FAILURE
Definition zend_types.h:61
#define IS_OBJECT
Definition zend_types.h:608
#define IS_LONG
Definition zend_types.h:604
#define ZVAL_ARR(z, a)
#define ZEND_TYPE_IS_SET(t)
Definition zend_types.h:166
#define ZSTR_GET_CE_CACHE(s)
Definition zend_types.h:842
#define IS_REFERENCE
Definition zend_types.h:610
#define Z_RES_HANDLE_P(zval_p)
#define ZVAL_NEW_STR(z, s)
#define ZVAL_COPY(z, v)
#define ZEND_PROPERTY_INFO_SOURCE_IS_LIST(list)
Definition zend_types.h:586
struct _zend_refcounted zend_refcounted
Definition zend_types.h:95
#define Z_TYPE_INFO_REFCOUNTED(t)
Definition zend_types.h:799
#define Z_INDIRECT_P(zval_p)
#define Z_REF_P(zval_p)
#define Z_OBJPROP_P(zval_p)
#define ZVAL_DOUBLE(z, d)
#define Z_REFCOUNT_P(pz)
ZEND_RESULT_CODE zend_result
Definition zend_types.h:64
#define IS_ARRAY_IMMUTABLE
Definition zend_types.h:823
#define Z_ISERROR_P(zval_p)
Definition zend_types.h:963
unsigned char zend_uchar
Definition zend_types.h:57
#define IS_CONSTANT_AST
Definition zend_types.h:611
#define Z_CE_P(zval_p)
#define ZVAL_REF(z, r)
#define ZEND_TYPE_ALLOW_NULL(t)
Definition zend_types.h:269
#define SEPARATE_ARRAY(zv)
#define Z_CACHE_SLOT_P(zval_p)
Definition zend_types.h:675
#define ZEND_TYPE_LIST_FOREACH(list, type_ptr)
Definition zend_types.h:211
#define ZEND_PROPERTY_INFO_SOURCE_FROM_LIST(list)
Definition zend_types.h:584
#define Z_PROP_FLAG_P(z)
#define GC_REFCOUNT(p)
Definition zend_types.h:707
#define Z_TYPE(zval)
Definition zend_types.h:659
#define ZEND_TYPE_CONTAINS_CODE(t, code)
Definition zend_types.h:266
#define Z_DVAL_P(zval_p)
Definition zend_types.h:969
#define IS_INDIRECT
Definition zend_types.h:623
#define ZEND_TYPE_LIST(t)
Definition zend_types.h:204
struct _zend_execute_data zend_execute_data
Definition zend_types.h:91
#define ZVAL_ERROR(z)
#define Z_LVAL_P(zval_p)
Definition zend_types.h:966
#define ZVAL_COPY_VALUE(z, v)
#define Z_EXTRA_P(zval_p)
Definition zend_types.h:696
struct _zend_reference zend_reference
Definition zend_types.h:100
#define ZVAL_BOOL(z, b)
#define ZEND_TYPE_IS_COMPLEX(t)
Definition zend_types.h:171
#define Z_OPT_TYPE_P(zval_p)
Definition zend_types.h:938
#define Z_OBJ(zval)
Definition zend_types.h:989
ZEND_API void zval_ptr_dtor(zval *zval_ptr)
container
zval retval
uint32_t call_info
zend_string * tmp_name
new_op_array
zval * return_value
call prev_execute_data
zend_property_info * prop_info
uint32_t arg_num
zval * dim
zend_generator * generator
zend_string * name
zval * inc_filename
fbc internal_function handler(call, ret)
zend_function * fbc
value_ptr
bool result
op2
function(EX_VAR(opline->result.var))
op1
zval * variable_ptr
execute_data
object
zend_refcounted * garbage
zval * ret
value
var_ptr
zend_execute_data * call
property
new_op_array scope
zend_object * zobj
out($f, $s)
#define ZEND_SEND_VAR_EX
#define ZEND_ASSIGN_DIM_OP
#define ZEND_PRE_DEC_OBJ
#define ZEND_RECV_INIT
#define ZEND_FETCH_OBJ_W
#define ZEND_NEW
#define ZEND_SEND_VAL_EX
#define ZEND_USER_OPCODE
#define ZEND_INIT_USER_CALL
#define ZEND_ROPE_INIT
#define ZEND_FETCH_LIST_W
#define ZEND_INIT_FCALL
#define ZEND_CALLABLE_CONVERT
#define ZEND_SEND_VAL
#define ZEND_FETCH_OBJ_FUNC_ARG
#define ZEND_PRE_INC_OBJ
#define ZEND_FETCH_DIM_FUNC_ARG
#define ZEND_HANDLE_EXCEPTION
#define ZEND_SEND_ARRAY
#define ZEND_SEND_UNPACK
#define ZEND_DO_UCALL
#define ZEND_ROPE_ADD
#define ZEND_SEND_VAR
#define ZEND_POST_DEC_OBJ
#define ZEND_CONCAT
#define ZEND_RECV
#define ZEND_INIT_NS_FCALL_BY_NAME
#define ZEND_DO_FCALL
#define ZEND_INIT_FCALL_BY_NAME
#define ZEND_SEND_VAR_NO_REF_EX
#define ZEND_SEND_USER
#define ZEND_DO_ICALL
#define ZEND_SEND_FUNC_ARG
#define ZEND_CHECK_UNDEF_ARGS
#define ZEND_FETCH_DIM_W
#define ZEND_INIT_DYNAMIC_CALL
#define ZEND_INIT_PARENT_PROPERTY_HOOK_CALL
#define ZEND_ASSIGN_OBJ_REF
#define ZEND_FETCH_OBJ_RW
#define ZEND_FETCH_DIM_UNSET
#define ZEND_SEND_VAR_NO_REF
#define ZEND_SEND_REF
#define ZEND_POST_INC_OBJ
#define ZEND_DO_FCALL_BY_NAME
#define ZEND_INIT_METHOD_CALL
#define ZEND_INIT_STATIC_METHOD_CALL
#define ZEND_ADD
#define ZEND_FETCH_DIM_RW