xref: /PHP-7.3/Zend/zend_execute.c (revision a07c1f56)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2018 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 
43 /* Virtual current working directory support */
44 #include "zend_virtual_cwd.h"
45 
46 #ifdef HAVE_GCC_GLOBAL_REGS
47 # if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
48 #  define ZEND_VM_FP_GLOBAL_REG "%esi"
49 #  define ZEND_VM_IP_GLOBAL_REG "%edi"
50 # elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
51 #  define ZEND_VM_FP_GLOBAL_REG "%r14"
52 #  define ZEND_VM_IP_GLOBAL_REG "%r15"
53 # elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
54 #  define ZEND_VM_FP_GLOBAL_REG "r28"
55 #  define ZEND_VM_IP_GLOBAL_REG "r29"
56 # elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
57 #  define ZEND_VM_FP_GLOBAL_REG "r28"
58 #  define ZEND_VM_IP_GLOBAL_REG "r29"
59 # endif
60 #endif
61 
62 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
63 # pragma GCC diagnostic ignored "-Wvolatile-register-var"
64   register zend_execute_data* volatile execute_data __asm__(ZEND_VM_FP_GLOBAL_REG);
65 # pragma GCC diagnostic warning "-Wvolatile-register-var"
66 # define EXECUTE_DATA_D     void
67 # define EXECUTE_DATA_C
68 # define EXECUTE_DATA_DC
69 # define EXECUTE_DATA_CC
70 # define NO_EXECUTE_DATA_CC
71 # define OPLINE_D           void
72 # define OPLINE_C
73 # define OPLINE_DC
74 # define OPLINE_CC
75 #else
76 # define EXECUTE_DATA_D     zend_execute_data* execute_data
77 # define EXECUTE_DATA_C     execute_data
78 # define EXECUTE_DATA_DC    , EXECUTE_DATA_D
79 # define EXECUTE_DATA_CC    , EXECUTE_DATA_C
80 # define NO_EXECUTE_DATA_CC , NULL
81 # define OPLINE_D           const zend_op* opline
82 # define OPLINE_C           opline
83 # define OPLINE_DC          , OPLINE_D
84 # define OPLINE_CC          , OPLINE_C
85 #endif
86 
87 #if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
88 # pragma GCC diagnostic ignored "-Wvolatile-register-var"
89   register const zend_op* volatile opline __asm__(ZEND_VM_IP_GLOBAL_REG);
90 # pragma GCC diagnostic warning "-Wvolatile-register-var"
91 #else
92 #endif
93 
94 #define _CONST_CODE  0
95 #define _TMP_CODE    1
96 #define _VAR_CODE    2
97 #define _UNUSED_CODE 3
98 #define _CV_CODE     4
99 
100 typedef int (ZEND_FASTCALL *incdec_t)(zval *);
101 
102 #define get_zval_ptr(op_type, node, should_free, type) _get_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC)
103 #define get_zval_ptr_deref(op_type, node, should_free, type) _get_zval_ptr_deref(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC)
104 #define get_zval_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC)
105 #define get_op_data_zval_ptr_r(op_type, node, should_free) _get_op_data_zval_ptr_r(op_type, node, should_free EXECUTE_DATA_CC OPLINE_CC)
106 #define get_op_data_zval_ptr_deref_r(op_type, node, should_free) _get_op_data_zval_ptr_deref_r(op_type, node, should_free EXECUTE_DATA_CC OPLINE_CC)
107 #define get_zval_ptr_ptr(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
108 #define get_zval_ptr_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
109 #define get_obj_zval_ptr(op_type, node, should_free, type) _get_obj_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC)
110 #define get_obj_zval_ptr_undef(op_type, node, should_free, type) _get_obj_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC OPLINE_CC)
111 #define get_obj_zval_ptr_ptr(op_type, node, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
112 
113 #define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED)
114 
ZEND_FUNCTION(pass)115 static ZEND_FUNCTION(pass)
116 {
117 }
118 
119 ZEND_API const zend_internal_function zend_pass_function = {
120 	ZEND_INTERNAL_FUNCTION, /* type              */
121 	{0, 0, 0},              /* arg_flags         */
122 	0,                      /* fn_flags          */
123 	NULL,                   /* name              */
124 	NULL,                   /* scope             */
125 	NULL,                   /* prototype         */
126 	0,                      /* num_args          */
127 	0,                      /* required_num_args */
128 	NULL,                   /* arg_info          */
129 	ZEND_FN(pass),          /* handler           */
130 	NULL,                   /* module            */
131 	{NULL,NULL,NULL,NULL}   /* reserved          */
132 };
133 
134 #undef zval_ptr_dtor
135 #define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC)
136 
137 #define FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(free_op, result) do {	\
138 	zval *__container_to_free = (free_op);									\
139 	if (UNEXPECTED(__container_to_free)										\
140 	 && EXPECTED(Z_REFCOUNTED_P(__container_to_free))) {					\
141 		zend_refcounted *__ref = Z_COUNTED_P(__container_to_free);			\
142 		if (UNEXPECTED(!GC_DELREF(__ref))) {								\
143 			zval *__zv = (result);											\
144 			if (EXPECTED(Z_TYPE_P(__zv) == IS_INDIRECT)) {					\
145 				ZVAL_COPY(__zv, Z_INDIRECT_P(__zv));						\
146 			}																\
147 			rc_dtor_func(__ref);											\
148 		}																	\
149 	}																		\
150 } while (0)
151 
152 #define FREE_OP(should_free) \
153 	if (should_free) { \
154 		zval_ptr_dtor_nogc(should_free); \
155 	}
156 
157 #define FREE_UNFETCHED_OP(type, var) \
158 	if ((type) & (IS_TMP_VAR|IS_VAR)) { \
159 		zval_ptr_dtor_nogc(EX_VAR(var)); \
160 	}
161 
162 #define FREE_OP_VAR_PTR(should_free) \
163 	if (should_free) { \
164 		zval_ptr_dtor_nogc(should_free); \
165 	}
166 
167 #define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
168 
169 #define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
170 
171 #define ZEND_VM_STACK_PAGE_SIZE  (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
172 
173 #define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size, page_size) \
174 	(((size) + ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval) \
175 	  + ((page_size) - 1)) & ~((page_size) - 1))
176 
zend_vm_stack_new_page(size_t size,zend_vm_stack prev)177 static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
178 	zend_vm_stack page = (zend_vm_stack)emalloc(size);
179 
180 	page->top = ZEND_VM_STACK_ELEMENTS(page);
181 	page->end = (zval*)((char*)page + size);
182 	page->prev = prev;
183 	return page;
184 }
185 
zend_vm_stack_init(void)186 ZEND_API void zend_vm_stack_init(void)
187 {
188 	EG(vm_stack_page_size) = ZEND_VM_STACK_PAGE_SIZE;
189 	EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
190 	EG(vm_stack)->top++;
191 	EG(vm_stack_top) = EG(vm_stack)->top;
192 	EG(vm_stack_end) = EG(vm_stack)->end;
193 }
194 
zend_vm_stack_init_ex(size_t page_size)195 ZEND_API void zend_vm_stack_init_ex(size_t page_size)
196 {
197 	/* page_size must be a power of 2 */
198 	ZEND_ASSERT(page_size > 0 && (page_size & (page_size - 1)) == 0);
199 	EG(vm_stack_page_size) = page_size;
200 	EG(vm_stack) = zend_vm_stack_new_page(page_size, NULL);
201 	EG(vm_stack_top) = EG(vm_stack)->top;
202 	EG(vm_stack_end) = EG(vm_stack)->end;
203 }
204 
zend_vm_stack_destroy(void)205 ZEND_API void zend_vm_stack_destroy(void)
206 {
207 	zend_vm_stack stack = EG(vm_stack);
208 
209 	while (stack != NULL) {
210 		zend_vm_stack p = stack->prev;
211 		efree(stack);
212 		stack = p;
213 	}
214 }
215 
zend_vm_stack_extend(size_t size)216 ZEND_API void* zend_vm_stack_extend(size_t size)
217 {
218 	zend_vm_stack stack;
219 	void *ptr;
220 
221 	stack = EG(vm_stack);
222 	stack->top = EG(vm_stack_top);
223 	EG(vm_stack) = stack = zend_vm_stack_new_page(
224 		EXPECTED(size < EG(vm_stack_page_size) - (ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval))) ?
225 			EG(vm_stack_page_size) : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size, EG(vm_stack_page_size)),
226 		stack);
227 	ptr = stack->top;
228 	EG(vm_stack_top) = (void*)(((char*)ptr) + size);
229 	EG(vm_stack_end) = stack->end;
230 	return ptr;
231 }
232 
zend_get_compiled_variable_value(const zend_execute_data * execute_data,uint32_t var)233 ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
234 {
235 	return EX_VAR(var);
236 }
237 
_get_zval_ptr_tmp(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)238 static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
239 {
240 	zval *ret = EX_VAR(var);
241 	*should_free = ret;
242 
243 	ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE);
244 
245 	return ret;
246 }
247 
_get_zval_ptr_var(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)248 static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
249 {
250 	zval *ret = EX_VAR(var);
251 
252 	*should_free = ret;
253 	return ret;
254 }
255 
_get_zval_ptr_var_deref(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)256 static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
257 {
258 	zval *ret = EX_VAR(var);
259 
260 	*should_free = ret;
261 	ZVAL_DEREF(ret);
262 	return ret;
263 }
264 
zval_undefined_cv(uint32_t var EXECUTE_DATA_DC)265 static zend_never_inline ZEND_COLD void zval_undefined_cv(uint32_t var EXECUTE_DATA_DC)
266 {
267 	if (EXPECTED(EG(exception) == NULL)) {
268 		zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
269 		zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
270 	}
271 }
272 
_get_zval_cv_lookup(zval * ptr,uint32_t var,int type EXECUTE_DATA_DC)273 static zend_never_inline ZEND_COLD zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type EXECUTE_DATA_DC)
274 {
275 	switch (type) {
276 		case BP_VAR_R:
277 		case BP_VAR_UNSET:
278 			zval_undefined_cv(var EXECUTE_DATA_CC);
279 			/* break missing intentionally */
280 		case BP_VAR_IS:
281 			ptr = &EG(uninitialized_zval);
282 			break;
283 		case BP_VAR_RW:
284 			zval_undefined_cv(var EXECUTE_DATA_CC);
285 			/* break missing intentionally */
286 		case BP_VAR_W:
287 			ZVAL_NULL(ptr);
288 			break;
289 	}
290 	return ptr;
291 }
292 
_get_zval_cv_lookup_BP_VAR_R(zval * ptr,uint32_t var EXECUTE_DATA_DC)293 static zend_never_inline ZEND_COLD zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var EXECUTE_DATA_DC)
294 {
295 	zval_undefined_cv(var EXECUTE_DATA_CC);
296 	return &EG(uninitialized_zval);
297 }
298 
_get_zval_cv_lookup_BP_VAR_UNSET(zval * ptr,uint32_t var EXECUTE_DATA_DC)299 static zend_never_inline ZEND_COLD zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var EXECUTE_DATA_DC)
300 {
301 	zval_undefined_cv(var EXECUTE_DATA_CC);
302 	return &EG(uninitialized_zval);
303 }
304 
_get_zval_cv_lookup_BP_VAR_RW(zval * ptr,uint32_t var EXECUTE_DATA_DC)305 static zend_never_inline ZEND_COLD zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var EXECUTE_DATA_DC)
306 {
307 	ZVAL_NULL(ptr);
308 	zval_undefined_cv(var EXECUTE_DATA_CC);
309 	return ptr;
310 }
311 
_get_zval_ptr_cv(uint32_t var,int type EXECUTE_DATA_DC)312 static zend_always_inline zval *_get_zval_ptr_cv(uint32_t var, int type EXECUTE_DATA_DC)
313 {
314 	zval *ret = EX_VAR(var);
315 
316 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
317 		if (type == BP_VAR_W) {
318 			ZVAL_NULL(ret);
319 		} else {
320 			return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
321 		}
322 	}
323 	return ret;
324 }
325 
_get_zval_ptr_cv_deref(uint32_t var,int type EXECUTE_DATA_DC)326 static zend_always_inline zval *_get_zval_ptr_cv_deref(uint32_t var, int type EXECUTE_DATA_DC)
327 {
328 	zval *ret = EX_VAR(var);
329 
330 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
331 		if (type == BP_VAR_W) {
332 			ZVAL_NULL(ret);
333 			return ret;
334 		} else {
335 			return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
336 		}
337 	}
338 	ZVAL_DEREF(ret);
339 	return ret;
340 }
341 
_get_zval_ptr_cv_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)342 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
343 {
344 	zval *ret = EX_VAR(var);
345 
346 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
347 		return _get_zval_cv_lookup_BP_VAR_R(ret, var EXECUTE_DATA_CC);
348 	}
349 	return ret;
350 }
351 
_get_zval_ptr_cv_deref_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)352 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
353 {
354 	zval *ret = EX_VAR(var);
355 
356 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
357 		return _get_zval_cv_lookup_BP_VAR_R(ret, var EXECUTE_DATA_CC);
358 	}
359 	ZVAL_DEREF(ret);
360 	return ret;
361 }
362 
_get_zval_ptr_cv_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)363 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
364 {
365 	zval *ret = EX_VAR(var);
366 
367 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
368 		return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var EXECUTE_DATA_CC);
369 	}
370 	return ret;
371 }
372 
_get_zval_ptr_cv_deref_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)373 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
374 {
375 	zval *ret = EX_VAR(var);
376 
377 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
378 		return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var EXECUTE_DATA_CC);
379 	}
380 	ZVAL_DEREF(ret);
381 	return ret;
382 }
383 
_get_zval_ptr_cv_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)384 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
385 {
386 	zval *ret = EX_VAR(var);
387 
388 	return ret;
389 }
390 
_get_zval_ptr_cv_deref_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)391 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
392 {
393 	zval *ret = EX_VAR(var);
394 
395 	ZVAL_DEREF(ret);
396 	return ret;
397 }
398 
_get_zval_ptr_cv_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)399 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
400 {
401 	zval *ret = EX_VAR(var);
402 
403 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
404 		return _get_zval_cv_lookup_BP_VAR_RW(ret, var EXECUTE_DATA_CC);
405 	}
406 	return ret;
407 }
408 
_get_zval_ptr_cv_deref_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)409 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
410 {
411 	zval *ret = EX_VAR(var);
412 
413 	if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
414 		return _get_zval_cv_lookup_BP_VAR_RW(ret, var EXECUTE_DATA_CC);
415 	}
416 	ZVAL_DEREF(ret);
417 	return ret;
418 }
419 
_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)420 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
421 {
422 	zval *ret = EX_VAR(var);
423 
424 	if (Z_TYPE_P(ret) == IS_UNDEF) {
425 		ZVAL_NULL(ret);
426 	}
427 	return ret;
428 }
429 
_get_zval_ptr_cv_deref_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)430 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
431 {
432 	zval *ret = EX_VAR(var);
433 
434 	if (Z_TYPE_P(ret) == IS_UNDEF) {
435 		ZVAL_NULL(ret);
436 		return ret;
437 	}
438 	ZVAL_DEREF(ret);
439 	return ret;
440 }
441 
_get_zval_ptr(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC OPLINE_DC)442 static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC)
443 {
444 	if (op_type & (IS_TMP_VAR|IS_VAR)) {
445 		if (op_type == IS_TMP_VAR) {
446 			return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
447 		} else {
448 			ZEND_ASSERT(op_type == IS_VAR);
449 			return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
450 		}
451 	} else {
452 		*should_free = NULL;
453 		if (op_type == IS_CONST) {
454 			return RT_CONSTANT(opline, node);
455 		} else if (op_type == IS_CV) {
456 			return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
457 		} else {
458 			return NULL;
459 		}
460 	}
461 }
462 
_get_op_data_zval_ptr_r(int op_type,znode_op node,zend_free_op * should_free EXECUTE_DATA_DC OPLINE_DC)463 static zend_always_inline zval *_get_op_data_zval_ptr_r(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC OPLINE_DC)
464 {
465 	if (op_type & (IS_TMP_VAR|IS_VAR)) {
466 		if (op_type == IS_TMP_VAR) {
467 			return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
468 		} else {
469 			ZEND_ASSERT(op_type == IS_VAR);
470 			return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
471 		}
472 	} else {
473 		*should_free = NULL;
474 		if (op_type == IS_CONST) {
475 			return RT_CONSTANT(opline + 1, node);
476 		} else if (op_type == IS_CV) {
477 			return _get_zval_ptr_cv_BP_VAR_R(node.var EXECUTE_DATA_CC);
478 		} else {
479 			return NULL;
480 		}
481 	}
482 }
483 
_get_zval_ptr_deref(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC OPLINE_DC)484 static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC)
485 {
486 	if (op_type & (IS_TMP_VAR|IS_VAR)) {
487 		if (op_type == IS_TMP_VAR) {
488 			return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
489 		} else {
490 			ZEND_ASSERT(op_type == IS_VAR);
491 			return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC);
492 		}
493 	} else {
494 		*should_free = NULL;
495 		if (op_type == IS_CONST) {
496 			return RT_CONSTANT(opline, node);
497 		} else if (op_type == IS_CV) {
498 			return _get_zval_ptr_cv_deref(node.var, type EXECUTE_DATA_CC);
499 		} else {
500 			return NULL;
501 		}
502 	}
503 }
504 
_get_op_data_zval_ptr_deref_r(int op_type,znode_op node,zend_free_op * should_free EXECUTE_DATA_DC OPLINE_DC)505 static zend_always_inline zval *_get_op_data_zval_ptr_deref_r(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC OPLINE_DC)
506 {
507 	if (op_type & (IS_TMP_VAR|IS_VAR)) {
508 		if (op_type == IS_TMP_VAR) {
509 			return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
510 		} else {
511 			ZEND_ASSERT(op_type == IS_VAR);
512 			return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC);
513 		}
514 	} else {
515 		*should_free = NULL;
516 		if (op_type == IS_CONST) {
517 			return RT_CONSTANT(opline + 1, node);
518 		} else if (op_type == IS_CV) {
519 			return _get_zval_ptr_cv_deref_BP_VAR_R(node.var EXECUTE_DATA_CC);
520 		} else {
521 			return NULL;
522 		}
523 	}
524 }
525 
_get_zval_ptr_undef(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC OPLINE_DC)526 static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC)
527 {
528 	if (op_type & (IS_TMP_VAR|IS_VAR)) {
529 		if (op_type == IS_TMP_VAR) {
530 			return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
531 		} else {
532 			ZEND_ASSERT(op_type == IS_VAR);
533 			return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
534 		}
535 	} else {
536 		*should_free = NULL;
537 		if (op_type == IS_CONST) {
538 			return RT_CONSTANT(opline, node);
539 		} else if (op_type == IS_CV) {
540 			return EX_VAR(node.var);
541 		} else {
542 			return NULL;
543 		}
544 	}
545 }
546 
_get_zval_ptr_ptr_var(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)547 static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
548 {
549 	zval *ret = EX_VAR(var);
550 
551 	if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
552 		*should_free = NULL;
553 		ret = Z_INDIRECT_P(ret);
554 	} else {
555 		*should_free = ret;
556 	}
557 	return ret;
558 }
559 
_get_zval_ptr_ptr(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC)560 static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
561 {
562 	if (op_type == IS_CV) {
563 		*should_free = NULL;
564 		return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
565 	} else /* if (op_type == IS_VAR) */ {
566 		ZEND_ASSERT(op_type == IS_VAR);
567 		return _get_zval_ptr_ptr_var(node.var, should_free EXECUTE_DATA_CC);
568 	}
569 }
570 
_get_obj_zval_ptr(int op_type,znode_op op,zend_free_op * should_free,int type EXECUTE_DATA_DC OPLINE_DC)571 static inline zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC)
572 {
573 	if (op_type == IS_UNUSED) {
574 		*should_free = NULL;
575 		return &EX(This);
576 	}
577 	return get_zval_ptr(op_type, op, should_free, type);
578 }
579 
_get_obj_zval_ptr_undef(int op_type,znode_op op,zend_free_op * should_free,int type EXECUTE_DATA_DC OPLINE_DC)580 static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC OPLINE_DC)
581 {
582 	if (op_type == IS_UNUSED) {
583 		*should_free = NULL;
584 		return &EX(This);
585 	}
586 	return get_zval_ptr_undef(op_type, op, should_free, type);
587 }
588 
_get_obj_zval_ptr_ptr(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC)589 static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
590 {
591 	if (op_type == IS_UNUSED) {
592 		*should_free = NULL;
593 		return &EX(This);
594 	}
595 	return get_zval_ptr_ptr(op_type, node, should_free, type);
596 }
597 
zend_assign_to_variable_reference(zval * variable_ptr,zval * value_ptr)598 static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr)
599 {
600 	zend_reference *ref;
601 
602 	if (EXPECTED(!Z_ISREF_P(value_ptr))) {
603 		ZVAL_NEW_REF(value_ptr, value_ptr);
604 	} else if (UNEXPECTED(variable_ptr == value_ptr)) {
605 		return;
606 	}
607 
608 	ref = Z_REF_P(value_ptr);
609 	GC_ADDREF(ref);
610 	if (Z_REFCOUNTED_P(variable_ptr)) {
611 		zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
612 
613 		if (GC_DELREF(garbage) == 0) {
614 			ZVAL_REF(variable_ptr, ref);
615 			rc_dtor_func(garbage);
616 			return;
617 		} else {
618 			gc_check_possible_root(garbage);
619 		}
620 	}
621 	ZVAL_REF(variable_ptr, ref);
622 }
623 
zend_wrong_assign_to_variable_reference(zval * variable_ptr,zval * value_ptr,zend_uchar value_type OPLINE_DC EXECUTE_DATA_DC)624 static zend_never_inline ZEND_COLD int zend_wrong_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr, zend_uchar value_type OPLINE_DC EXECUTE_DATA_DC)
625 {
626 	zend_error(E_NOTICE, "Only variables should be assigned by reference");
627 	if (UNEXPECTED(EG(exception) != NULL)) {
628 		return 0;
629 	}
630 
631 	value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, value_type);
632 
633 	if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
634 		ZVAL_COPY(EX_VAR(opline->result.var), value_ptr);
635 	}
636 	return 1;
637 }
638 
zend_wrong_property_assignment(zval * property OPLINE_DC EXECUTE_DATA_DC)639 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_assignment(zval *property OPLINE_DC EXECUTE_DATA_DC)
640 {
641 	zend_string *tmp_property_name;
642 	zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
643 	zend_error(E_WARNING, "Attempt to assign property '%s' of non-object", ZSTR_VAL(property_name));
644 	zend_tmp_string_release(tmp_property_name);
645 	if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
646 		ZVAL_NULL(EX_VAR(opline->result.var));
647 	}
648 }
649 
650 /* this should modify object only if it's empty */
make_real_object(zval * object,zval * property OPLINE_DC EXECUTE_DATA_DC)651 static zend_never_inline ZEND_COLD int ZEND_FASTCALL make_real_object(zval *object, zval *property OPLINE_DC EXECUTE_DATA_DC)
652 {
653 	zend_object *obj;
654 
655 	if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE)) {
656 		/* nothing to destroy */
657 	} else if (EXPECTED((Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
658 		zval_ptr_dtor_nogc(object);
659 	} else {
660 		if (opline->op1_type != IS_VAR || EXPECTED(!Z_ISERROR_P(object))) {
661 			zend_string *tmp_property_name;
662 			zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
663 
664 			if (opline->opcode == ZEND_PRE_INC_OBJ
665 			 || opline->opcode == ZEND_PRE_DEC_OBJ
666 			 || opline->opcode == ZEND_POST_INC_OBJ
667 			 || opline->opcode == ZEND_POST_DEC_OBJ) {
668 				zend_error(E_WARNING, "Attempt to increment/decrement property '%s' of non-object", ZSTR_VAL(property_name));
669 			} else {
670 				zend_error(E_WARNING, "Attempt to assign property '%s' of non-object", ZSTR_VAL(property_name));
671 			}
672 			zend_tmp_string_release(tmp_property_name);
673 		}
674 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
675 			ZVAL_NULL(EX_VAR(opline->result.var));
676 		}
677 		return 0;
678 	}
679 	object_init(object);
680 	Z_ADDREF_P(object);
681 	obj = Z_OBJ_P(object);
682 	zend_error(E_WARNING, "Creating default object from empty value");
683 	if (GC_REFCOUNT(obj) == 1) {
684 		/* the enclosing container was deleted, obj is unreferenced */
685 		OBJ_RELEASE(obj);
686 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
687 			ZVAL_NULL(EX_VAR(opline->result.var));
688 		}
689 		return 0;
690 	}
691 	Z_DELREF_P(object);
692 	return 1;
693 }
694 
make_real_object_rw(zval * object,zval * property OPLINE_DC)695 static zend_never_inline ZEND_COLD int ZEND_FASTCALL make_real_object_rw(zval *object, zval *property OPLINE_DC)
696 {
697 	if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE)) {
698 		/* nothing to destroy */
699 	} else if (EXPECTED((Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
700 		zval_ptr_dtor_nogc(object);
701 	} else {
702 		if (opline->op1_type != IS_VAR || EXPECTED(!Z_ISERROR_P(object))) {
703 			zend_string *tmp_property_name;
704 			zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
705 			zend_error(E_WARNING, "Attempt to modify property '%s' of non-object", ZSTR_VAL(property_name));
706 			zend_tmp_string_release(tmp_property_name);
707 		}
708 		return 0;
709 	}
710 	object_init(object);
711 	return 1;
712 }
713 
zend_verify_type_error_common(const zend_function * zf,const zend_arg_info * arg_info,const zend_class_entry * ce,zval * value,const char ** fname,const char ** fsep,const char ** fclass,const char ** need_msg,const char ** need_kind,const char ** need_or_null,const char ** given_msg,const char ** given_kind)714 static ZEND_COLD void zend_verify_type_error_common(
715 		const zend_function *zf, const zend_arg_info *arg_info,
716 		const zend_class_entry *ce, zval *value,
717 		const char **fname, const char **fsep, const char **fclass,
718 		const char **need_msg, const char **need_kind, const char **need_or_null,
719 		const char **given_msg, const char **given_kind)
720 {
721 	zend_bool is_interface = 0;
722 	*fname = ZSTR_VAL(zf->common.function_name);
723 	if (zf->common.scope) {
724 		*fsep =  "::";
725 		*fclass = ZSTR_VAL(zf->common.scope->name);
726 	} else {
727 		*fsep =  "";
728 		*fclass = "";
729 	}
730 
731 	if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
732 		if (ce) {
733 			if (ce->ce_flags & ZEND_ACC_INTERFACE) {
734 				*need_msg = "implement interface ";
735 				is_interface = 1;
736 			} else {
737 				*need_msg = "be an instance of ";
738 			}
739 			*need_kind = ZSTR_VAL(ce->name);
740 		} else {
741 			/* We don't know whether it's a class or interface, assume it's a class */
742 
743 			*need_msg = "be an instance of ";
744 			*need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type));
745 		}
746 	} else {
747 		switch (ZEND_TYPE_CODE(arg_info->type)) {
748 			case IS_OBJECT:
749 				*need_msg = "be an ";
750 				*need_kind = "object";
751 				break;
752 			case IS_CALLABLE:
753 				*need_msg = "be callable";
754 				*need_kind = "";
755 				break;
756 			case IS_ITERABLE:
757 				*need_msg = "be iterable";
758 				*need_kind = "";
759 				break;
760 			default:
761 				*need_msg = "be of the type ";
762 				*need_kind = zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type));
763 				break;
764 		}
765 	}
766 
767 	if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
768 		*need_or_null = is_interface ? " or be null" : " or null";
769 	} else {
770 		*need_or_null = "";
771 	}
772 
773 	if (value) {
774 		if (ZEND_TYPE_IS_CLASS(arg_info->type) && Z_TYPE_P(value) == IS_OBJECT) {
775 			*given_msg = "instance of ";
776 			*given_kind = ZSTR_VAL(Z_OBJCE_P(value)->name);
777 		} else {
778 			*given_msg = zend_zval_type_name(value);
779 			*given_kind = "";
780 		}
781 	} else {
782 		*given_msg = "none";
783 		*given_kind = "";
784 	}
785 }
786 
zend_verify_arg_error(const zend_function * zf,const zend_arg_info * arg_info,int arg_num,const zend_class_entry * ce,zval * value)787 static ZEND_COLD void zend_verify_arg_error(
788 		const zend_function *zf, const zend_arg_info *arg_info,
789 		int arg_num, const zend_class_entry *ce, zval *value)
790 {
791 	zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
792 	const char *fname, *fsep, *fclass;
793 	const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
794 
795 	if (value) {
796 		zend_verify_type_error_common(
797 			zf, arg_info, ce, value,
798 			&fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
799 
800 		if (zf->common.type == ZEND_USER_FUNCTION) {
801 			if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
802 				zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given, called in %s on line %d",
803 						arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind,
804 						ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
805 			} else {
806 				zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
807 			}
808 		} else {
809 			zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
810 		}
811 	} else {
812 		zend_missing_arg_error(ptr);
813 	}
814 }
815 
is_null_constant(zend_class_entry * scope,zval * default_value)816 static int is_null_constant(zend_class_entry *scope, zval *default_value)
817 {
818 	if (Z_TYPE_P(default_value) == IS_CONSTANT_AST) {
819 		zval constant;
820 
821 		ZVAL_COPY(&constant, default_value);
822 		if (UNEXPECTED(zval_update_constant_ex(&constant, scope) != SUCCESS)) {
823 			return 0;
824 		}
825 		if (Z_TYPE(constant) == IS_NULL) {
826 			return 1;
827 		}
828 		zval_ptr_dtor_nogc(&constant);
829 	}
830 	return 0;
831 }
832 
zend_verify_weak_scalar_type_hint(zend_uchar type_hint,zval * arg)833 static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg)
834 {
835 	switch (type_hint) {
836 		case _IS_BOOL: {
837 			zend_bool dest;
838 
839 			if (!zend_parse_arg_bool_weak(arg, &dest)) {
840 				return 0;
841 			}
842 			zval_ptr_dtor(arg);
843 			ZVAL_BOOL(arg, dest);
844 			return 1;
845 		}
846 		case IS_LONG: {
847 			zend_long dest;
848 
849 			if (!zend_parse_arg_long_weak(arg, &dest)) {
850 				return 0;
851 			}
852 			zval_ptr_dtor(arg);
853 			ZVAL_LONG(arg, dest);
854 			return 1;
855 		}
856 		case IS_DOUBLE: {
857 			double dest;
858 
859 			if (!zend_parse_arg_double_weak(arg, &dest)) {
860 				return 0;
861 			}
862 			zval_ptr_dtor(arg);
863 			ZVAL_DOUBLE(arg, dest);
864 			return 1;
865 		}
866 		case IS_STRING: {
867 			zend_string *dest;
868 
869 			/* on success "arg" is converted to IS_STRING */
870 			if (!zend_parse_arg_str_weak(arg, &dest)) {
871 				return 0;
872 			}
873 			return 1;
874 		}
875 		default:
876 			return 0;
877 	}
878 }
879 
zend_verify_scalar_type_hint(zend_uchar type_hint,zval * arg,zend_bool strict)880 static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict)
881 {
882 	if (UNEXPECTED(strict)) {
883 		/* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
884 		if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) {
885 			return 0;
886 		}
887 	} else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
888 		/* NULL may be accepted only by nullable hints (this is already checked) */
889 		return 0;
890 	}
891 	return zend_verify_weak_scalar_type_hint(type_hint, arg);
892 }
893 
zend_check_type(zend_type type,zval * arg,zend_class_entry ** ce,void ** cache_slot,zval * default_value,zend_class_entry * scope,zend_bool is_return_type)894 static zend_always_inline zend_bool zend_check_type(
895 		zend_type type,
896 		zval *arg, zend_class_entry **ce, void **cache_slot,
897 		zval *default_value, zend_class_entry *scope,
898 		zend_bool is_return_type)
899 {
900 	if (!ZEND_TYPE_IS_SET(type)) {
901 		return 1;
902 	}
903 
904 	ZVAL_DEREF(arg);
905 	if (ZEND_TYPE_IS_CLASS(type)) {
906 		if (EXPECTED(*cache_slot)) {
907 			*ce = (zend_class_entry *) *cache_slot;
908 		} else {
909 			*ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
910 			if (UNEXPECTED(!*ce)) {
911 				return Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)));
912 			}
913 			*cache_slot = (void *) *ce;
914 		}
915 		if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
916 			return instanceof_function(Z_OBJCE_P(arg), *ce);
917 		}
918 		return Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)));
919 	} else if (EXPECTED(ZEND_TYPE_CODE(type) == Z_TYPE_P(arg))) {
920 		return 1;
921 	}
922 
923 	if (Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)))) {
924 		/* Null passed to nullable type */
925 		return 1;
926 	}
927 
928 	if (ZEND_TYPE_CODE(type) == IS_CALLABLE) {
929 		return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL);
930 	} else if (ZEND_TYPE_CODE(type) == IS_ITERABLE) {
931 		return zend_is_iterable(arg);
932 	} else if (ZEND_TYPE_CODE(type) == _IS_BOOL &&
933 			   EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
934 		return 1;
935 	} else {
936 		return zend_verify_scalar_type_hint(ZEND_TYPE_CODE(type), arg,
937 			is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES());
938 	}
939 
940 	/* Special handling for IS_VOID is not necessary (for return types),
941 	 * because this case is already checked at compile-time. */
942 }
943 
zend_verify_arg_type(zend_function * zf,uint32_t arg_num,zval * arg,zval * default_value,void ** cache_slot)944 static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
945 {
946 	zend_arg_info *cur_arg_info;
947 	zend_class_entry *ce;
948 
949 	if (EXPECTED(arg_num <= zf->common.num_args)) {
950 		cur_arg_info = &zf->common.arg_info[arg_num-1];
951 	} else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) {
952 		cur_arg_info = &zf->common.arg_info[zf->common.num_args];
953 	} else {
954 		return 1;
955 	}
956 
957 	ce = NULL;
958 	if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0))) {
959 		zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg);
960 		return 0;
961 	}
962 
963 	return 1;
964 }
965 
zend_verify_internal_arg_types(zend_function * fbc,zend_execute_data * call)966 static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
967 {
968 	uint32_t i;
969 	uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
970 	zval *p = ZEND_CALL_ARG(call, 1);
971 	void *dummy_cache_slot;
972 
973 	for (i = 0; i < num_args; ++i) {
974 		dummy_cache_slot = NULL;
975 		if (UNEXPECTED(!zend_verify_arg_type(fbc, i + 1, p, NULL, &dummy_cache_slot))) {
976 			EG(current_execute_data) = call->prev_execute_data;
977 			zend_vm_stack_free_args(call);
978 			return 0;
979 		}
980 		p++;
981 	}
982 	return 1;
983 }
984 
zend_missing_arg_error(zend_execute_data * execute_data)985 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data)
986 {
987 	zend_execute_data *ptr = EX(prev_execute_data);
988 
989 	if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
990 		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",
991 			EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
992 			EX(func)->common.scope ? "::" : "",
993 			ZSTR_VAL(EX(func)->common.function_name),
994 			EX_NUM_ARGS(),
995 			ZSTR_VAL(ptr->func->op_array.filename),
996 			ptr->opline->lineno,
997 			EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
998 			EX(func)->common.required_num_args);
999 	} else {
1000 		zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed and %s %d expected",
1001 			EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
1002 			EX(func)->common.scope ? "::" : "",
1003 			ZSTR_VAL(EX(func)->common.function_name),
1004 			EX_NUM_ARGS(),
1005 			EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
1006 			EX(func)->common.required_num_args);
1007 	}
1008 }
1009 
zend_verify_return_error(const zend_function * zf,const zend_class_entry * ce,zval * value)1010 static ZEND_COLD void zend_verify_return_error(
1011 		const zend_function *zf, const zend_class_entry *ce, zval *value)
1012 {
1013 	const zend_arg_info *arg_info = &zf->common.arg_info[-1];
1014 	const char *fname, *fsep, *fclass;
1015 	const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
1016 
1017 	zend_verify_type_error_common(
1018 		zf, arg_info, ce, value,
1019 		&fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
1020 
1021 	zend_type_error("Return value of %s%s%s() must %s%s%s, %s%s returned",
1022 		fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
1023 }
1024 
1025 #if ZEND_DEBUG
zend_verify_internal_return_error(const zend_function * zf,const zend_class_entry * ce,zval * value)1026 static ZEND_COLD void zend_verify_internal_return_error(
1027 		const zend_function *zf, const zend_class_entry *ce, zval *value)
1028 {
1029 	const zend_arg_info *arg_info = &zf->common.arg_info[-1];
1030 	const char *fname, *fsep, *fclass;
1031 	const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
1032 
1033 	zend_verify_type_error_common(
1034 		zf, arg_info, ce, value,
1035 		&fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
1036 
1037 	zend_error_noreturn(E_CORE_ERROR, "Return value of %s%s%s() must %s%s%s, %s%s returned",
1038 		fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
1039 }
1040 
zend_verify_void_return_error(const zend_function * zf,const char * returned_msg,const char * returned_kind)1041 static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, const char *returned_msg, const char *returned_kind)
1042 {
1043 	const char *fname = ZSTR_VAL(zf->common.function_name);
1044 	const char *fsep;
1045 	const char *fclass;
1046 
1047 	if (zf->common.scope) {
1048 		fsep =  "::";
1049 		fclass = ZSTR_VAL(zf->common.scope->name);
1050 	} else {
1051 		fsep =  "";
1052 		fclass = "";
1053 	}
1054 
1055 	zend_type_error("%s%s%s() must not return a value, %s%s returned",
1056 		fclass, fsep, fname, returned_msg, returned_kind);
1057 }
1058 
zend_verify_internal_return_type(zend_function * zf,zval * ret)1059 static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
1060 {
1061 	zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
1062 	zend_class_entry *ce = NULL;
1063 	void *dummy_cache_slot = NULL;
1064 
1065 	if (ZEND_TYPE_CODE(ret_info->type) == IS_VOID) {
1066 		if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
1067 			zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
1068 			return 0;
1069 		}
1070 		return 1;
1071 	}
1072 
1073 	if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, &dummy_cache_slot, NULL, NULL, 1))) {
1074 		zend_verify_internal_return_error(zf, ce, ret);
1075 		return 0;
1076 	}
1077 
1078 	return 1;
1079 }
1080 #endif
1081 
zend_verify_return_type(zend_function * zf,zval * ret,void ** cache_slot)1082 static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *ret, void **cache_slot)
1083 {
1084 	zend_arg_info *ret_info = zf->common.arg_info - 1;
1085 	zend_class_entry *ce = NULL;
1086 
1087 	if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, cache_slot, NULL, NULL, 1))) {
1088 		zend_verify_return_error(zf, ce, ret);
1089 	}
1090 }
1091 
zend_verify_missing_return_type(const zend_function * zf,void ** cache_slot)1092 static ZEND_COLD int zend_verify_missing_return_type(const zend_function *zf, void **cache_slot)
1093 {
1094 	zend_arg_info *ret_info = zf->common.arg_info - 1;
1095 
1096 	if (ZEND_TYPE_IS_SET(ret_info->type) && UNEXPECTED(ZEND_TYPE_CODE(ret_info->type) != IS_VOID)) {
1097 		zend_class_entry *ce = NULL;
1098 		if (ZEND_TYPE_IS_CLASS(ret_info->type)) {
1099 			if (EXPECTED(*cache_slot)) {
1100 				ce = (zend_class_entry*) *cache_slot;
1101 			} else {
1102 				ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
1103 				if (ce) {
1104 					*cache_slot = (void*)ce;
1105 				}
1106 			}
1107 		}
1108 		zend_verify_return_error(zf, ce, NULL);
1109 		return 0;
1110 	}
1111 	return 1;
1112 }
1113 
zend_use_object_as_array(void)1114 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_object_as_array(void)
1115 {
1116 	zend_throw_error(NULL, "Cannot use object as array");
1117 }
1118 
zend_illegal_offset(void)1119 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_illegal_offset(void)
1120 {
1121 	zend_error(E_WARNING, "Illegal offset type");
1122 }
1123 
zend_assign_to_object_dim(zval * object,zval * dim,zval * value OPLINE_DC EXECUTE_DATA_DC)1124 static zend_never_inline void zend_assign_to_object_dim(zval *object, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
1125 {
1126 	if (UNEXPECTED(!Z_OBJ_HT_P(object)->write_dimension)) {
1127 		zend_use_object_as_array();
1128 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1129 			ZVAL_UNDEF(EX_VAR(opline->result.var));
1130 		}
1131 		return;
1132 	}
1133 
1134 	Z_OBJ_HT_P(object)->write_dimension(object, dim, value);
1135 
1136 	if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1137 		ZVAL_COPY(EX_VAR(opline->result.var), value);
1138 	}
1139 }
1140 
zend_binary_assign_op_obj_dim(zval * object,zval * property,zval * value,zval * retval,binary_op_type binary_op EXECUTE_DATA_DC)1141 static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *value, zval *retval, binary_op_type binary_op EXECUTE_DATA_DC)
1142 {
1143 	zval *z;
1144 	zval rv, res;
1145 
1146 	if (Z_OBJ_HT_P(object)->read_dimension &&
1147 		(z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) {
1148 
1149 		if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1150 			zval rv2;
1151 			zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1152 
1153 			if (z == &rv) {
1154 				zval_ptr_dtor(&rv);
1155 			}
1156 			ZVAL_COPY_VALUE(z, value);
1157 		}
1158 		binary_op(&res, Z_ISREF_P(z) ? Z_REFVAL_P(z) : z, value);
1159 		Z_OBJ_HT_P(object)->write_dimension(object, property, &res);
1160 		if (z == &rv) {
1161 			zval_ptr_dtor(&rv);
1162 		}
1163 		if (retval) {
1164 			ZVAL_COPY(retval, &res);
1165 		}
1166 		zval_ptr_dtor(&res);
1167 	} else {
1168 		zend_use_object_as_array();
1169 		if (retval) {
1170 			ZVAL_NULL(retval);
1171 		}
1172 	}
1173 }
1174 
zend_check_string_offset(zval * dim,int type EXECUTE_DATA_DC)1175 static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type EXECUTE_DATA_DC)
1176 {
1177 	zend_long offset;
1178 
1179 try_again:
1180 	if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1181 		switch(Z_TYPE_P(dim)) {
1182 			case IS_STRING:
1183 				if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1184 					break;
1185 				}
1186 				if (type != BP_VAR_UNSET) {
1187 					zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1188 				}
1189 				break;
1190 			case IS_UNDEF:
1191 				zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1192 			case IS_DOUBLE:
1193 			case IS_NULL:
1194 			case IS_FALSE:
1195 			case IS_TRUE:
1196 				zend_error(E_NOTICE, "String offset cast occurred");
1197 				break;
1198 			case IS_REFERENCE:
1199 				dim = Z_REFVAL_P(dim);
1200 				goto try_again;
1201 			default:
1202 				zend_illegal_offset();
1203 				break;
1204 		}
1205 
1206 		offset = zval_get_long_func(dim);
1207 	} else {
1208 		offset = Z_LVAL_P(dim);
1209 	}
1210 
1211 	return offset;
1212 }
1213 
zend_wrong_string_offset(EXECUTE_DATA_D)1214 static zend_never_inline ZEND_COLD void zend_wrong_string_offset(EXECUTE_DATA_D)
1215 {
1216 	const char *msg = NULL;
1217 	const zend_op *opline = EX(opline);
1218 	const zend_op *end;
1219 	uint32_t var;
1220 
1221 	if (UNEXPECTED(EG(exception) != NULL)) {
1222 		return;
1223 	}
1224 
1225 	switch (opline->opcode) {
1226 		case ZEND_ASSIGN_ADD:
1227 		case ZEND_ASSIGN_SUB:
1228 		case ZEND_ASSIGN_MUL:
1229 		case ZEND_ASSIGN_DIV:
1230 		case ZEND_ASSIGN_MOD:
1231 		case ZEND_ASSIGN_SL:
1232 		case ZEND_ASSIGN_SR:
1233 		case ZEND_ASSIGN_CONCAT:
1234 		case ZEND_ASSIGN_BW_OR:
1235 		case ZEND_ASSIGN_BW_AND:
1236 		case ZEND_ASSIGN_BW_XOR:
1237 		case ZEND_ASSIGN_POW:
1238 			msg = "Cannot use assign-op operators with string offsets";
1239 			break;
1240 		case ZEND_FETCH_DIM_W:
1241 		case ZEND_FETCH_DIM_RW:
1242 		case ZEND_FETCH_DIM_FUNC_ARG:
1243 		case ZEND_FETCH_DIM_UNSET:
1244 		case ZEND_FETCH_LIST_W:
1245 			/* TODO: Encode the "reason" into opline->extended_value??? */
1246 			var = opline->result.var;
1247 			opline++;
1248 			end = EG(current_execute_data)->func->op_array.opcodes +
1249 				EG(current_execute_data)->func->op_array.last;
1250 			while (opline < end) {
1251 				if (opline->op1_type == IS_VAR && opline->op1.var == var) {
1252 					switch (opline->opcode) {
1253 						case ZEND_ASSIGN_ADD:
1254 						case ZEND_ASSIGN_SUB:
1255 						case ZEND_ASSIGN_MUL:
1256 						case ZEND_ASSIGN_DIV:
1257 						case ZEND_ASSIGN_MOD:
1258 						case ZEND_ASSIGN_SL:
1259 						case ZEND_ASSIGN_SR:
1260 						case ZEND_ASSIGN_CONCAT:
1261 						case ZEND_ASSIGN_BW_OR:
1262 						case ZEND_ASSIGN_BW_AND:
1263 						case ZEND_ASSIGN_BW_XOR:
1264 						case ZEND_ASSIGN_POW:
1265 							if (opline->extended_value == ZEND_ASSIGN_OBJ) {
1266 								msg = "Cannot use string offset as an object";
1267 							} else if (opline->extended_value == ZEND_ASSIGN_DIM) {
1268 								msg = "Cannot use string offset as an array";
1269 							} else {
1270 								msg = "Cannot use assign-op operators with string offsets";
1271 							}
1272 							break;
1273 						case ZEND_PRE_INC_OBJ:
1274 						case ZEND_PRE_DEC_OBJ:
1275 						case ZEND_POST_INC_OBJ:
1276 						case ZEND_POST_DEC_OBJ:
1277 						case ZEND_PRE_INC:
1278 						case ZEND_PRE_DEC:
1279 						case ZEND_POST_INC:
1280 						case ZEND_POST_DEC:
1281 							msg = "Cannot increment/decrement string offsets";
1282 							break;
1283 						case ZEND_FETCH_DIM_W:
1284 						case ZEND_FETCH_DIM_RW:
1285 						case ZEND_FETCH_DIM_FUNC_ARG:
1286 						case ZEND_FETCH_DIM_UNSET:
1287 						case ZEND_FETCH_LIST_W:
1288 						case ZEND_ASSIGN_DIM:
1289 							msg = "Cannot use string offset as an array";
1290 							break;
1291 						case ZEND_FETCH_OBJ_W:
1292 						case ZEND_FETCH_OBJ_RW:
1293 						case ZEND_FETCH_OBJ_FUNC_ARG:
1294 						case ZEND_FETCH_OBJ_UNSET:
1295 						case ZEND_ASSIGN_OBJ:
1296 							msg = "Cannot use string offset as an object";
1297 							break;
1298 						case ZEND_ASSIGN_REF:
1299 						case ZEND_ADD_ARRAY_ELEMENT:
1300 						case ZEND_INIT_ARRAY:
1301 						case ZEND_MAKE_REF:
1302 							msg = "Cannot create references to/from string offsets";
1303 							break;
1304 						case ZEND_RETURN_BY_REF:
1305 						case ZEND_VERIFY_RETURN_TYPE:
1306 							msg = "Cannot return string offsets by reference";
1307 							break;
1308 						case ZEND_UNSET_DIM:
1309 						case ZEND_UNSET_OBJ:
1310 							msg = "Cannot unset string offsets";
1311 							break;
1312 						case ZEND_YIELD:
1313 							msg = "Cannot yield string offsets by reference";
1314 							break;
1315 						case ZEND_SEND_REF:
1316 						case ZEND_SEND_VAR_EX:
1317 						case ZEND_SEND_FUNC_ARG:
1318 							msg = "Only variables can be passed by reference";
1319 							break;
1320 						case ZEND_FE_RESET_RW:
1321 							msg = "Cannot iterate on string offsets by reference";
1322 							break;
1323 						EMPTY_SWITCH_DEFAULT_CASE();
1324 					}
1325 					break;
1326 				}
1327 				if (opline->op2_type == IS_VAR && opline->op2.var == var) {
1328 					ZEND_ASSERT(opline->opcode == ZEND_ASSIGN_REF);
1329 					msg = "Cannot create references to/from string offsets";
1330 					break;
1331 				}
1332 				opline++;
1333 			}
1334 			break;
1335 		EMPTY_SWITCH_DEFAULT_CASE();
1336 	}
1337 	ZEND_ASSERT(msg != NULL);
1338 	zend_throw_error(NULL, "%s", msg);
1339 }
1340 
zend_wrong_property_read(zval * property)1341 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_read(zval *property)
1342 {
1343 	zend_string *tmp_property_name;
1344 	zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
1345 	zend_error(E_NOTICE, "Trying to get property '%s' of non-object", ZSTR_VAL(property_name));
1346 	zend_tmp_string_release(tmp_property_name);
1347 }
1348 
zend_wrong_property_unset(zval * property)1349 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_unset(zval *property)
1350 {
1351 	zend_string *tmp_property_name;
1352 	zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
1353 	zend_error(E_NOTICE, "Trying to unset property '%s' of non-object", ZSTR_VAL(property_name));
1354 	zend_tmp_string_release(tmp_property_name);
1355 }
1356 
zend_wrong_property_check(zval * property)1357 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_wrong_property_check(zval *property)
1358 {
1359 	zend_string *tmp_property_name;
1360 	zend_string *property_name = zval_get_tmp_string(property, &tmp_property_name);
1361 	zend_error(E_NOTICE, "Trying to check property '%s' of non-object", ZSTR_VAL(property_name));
1362 	zend_tmp_string_release(tmp_property_name);
1363 }
1364 
zend_deprecated_function(const zend_function * fbc)1365 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc)
1366 {
1367 	zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
1368 		fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "",
1369 		fbc->common.scope ? "::" : "",
1370 		ZSTR_VAL(fbc->common.function_name));
1371 }
1372 
zend_assign_to_string_offset(zval * str,zval * dim,zval * value OPLINE_DC EXECUTE_DATA_DC)1373 static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
1374 {
1375 	zend_uchar c;
1376 	size_t string_len;
1377 	zend_long offset;
1378 
1379 	offset = zend_check_string_offset(dim, BP_VAR_W EXECUTE_DATA_CC);
1380 	if (offset < -(zend_long)Z_STRLEN_P(str)) {
1381 		/* Error on negative offset */
1382 		zend_error(E_WARNING, "Illegal string offset:  " ZEND_LONG_FMT, offset);
1383 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1384 			ZVAL_NULL(EX_VAR(opline->result.var));
1385 		}
1386 		return;
1387 	}
1388 
1389 	if (Z_TYPE_P(value) != IS_STRING) {
1390 		/* Convert to string, just the time to pick the 1st byte */
1391 		zend_string *tmp = zval_get_string_func(value);
1392 
1393 		string_len = ZSTR_LEN(tmp);
1394 		c = (zend_uchar)ZSTR_VAL(tmp)[0];
1395 		zend_string_release_ex(tmp, 0);
1396 	} else {
1397 		string_len = Z_STRLEN_P(value);
1398 		c = (zend_uchar)Z_STRVAL_P(value)[0];
1399 	}
1400 
1401 	if (string_len == 0) {
1402 		/* Error on empty input string */
1403 		zend_error(E_WARNING, "Cannot assign an empty string to a string offset");
1404 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1405 			ZVAL_NULL(EX_VAR(opline->result.var));
1406 		}
1407 		return;
1408 	}
1409 
1410 	if (offset < 0) { /* Handle negative offset */
1411 		offset += (zend_long)Z_STRLEN_P(str);
1412 	}
1413 
1414 	if ((size_t)offset >= Z_STRLEN_P(str)) {
1415 		/* Extend string if needed */
1416 		zend_long old_len = Z_STRLEN_P(str);
1417 		ZVAL_NEW_STR(str, zend_string_extend(Z_STR_P(str), offset + 1, 0));
1418 		memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
1419 		Z_STRVAL_P(str)[offset+1] = 0;
1420 	} else if (!Z_REFCOUNTED_P(str)) {
1421 		ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
1422 	} else if (Z_REFCOUNT_P(str) > 1) {
1423 		Z_DELREF_P(str);
1424 		ZVAL_NEW_STR(str, zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0));
1425 	} else {
1426 		zend_string_forget_hash_val(Z_STR_P(str));
1427 	}
1428 
1429 	Z_STRVAL_P(str)[offset] = c;
1430 
1431 	if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1432 		/* Return the new character */
1433 		ZVAL_INTERNED_STR(EX_VAR(opline->result.var), ZSTR_CHAR(c));
1434 	}
1435 }
1436 
zend_post_incdec_overloaded_property(zval * object,zval * property,void ** cache_slot,int inc OPLINE_DC EXECUTE_DATA_DC)1437 static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC)
1438 {
1439 	if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1440 		zval rv, obj;
1441 		zval *z;
1442 		zval z_copy;
1443 
1444 		ZVAL_OBJ(&obj, Z_OBJ_P(object));
1445 		Z_ADDREF(obj);
1446 		z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1447 		if (UNEXPECTED(EG(exception))) {
1448 			OBJ_RELEASE(Z_OBJ(obj));
1449 			ZVAL_UNDEF(EX_VAR(opline->result.var));
1450 			return;
1451 		}
1452 
1453 		if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1454 			zval rv2;
1455 			zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1456 			if (z == &rv) {
1457 				zval_ptr_dtor(&rv);
1458 			}
1459 			ZVAL_COPY_VALUE(z, value);
1460 		}
1461 
1462 		ZVAL_COPY_DEREF(&z_copy, z);
1463 		ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
1464 		if (inc) {
1465 			increment_function(&z_copy);
1466 		} else {
1467 			decrement_function(&z_copy);
1468 		}
1469 		Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
1470 		OBJ_RELEASE(Z_OBJ(obj));
1471 		zval_ptr_dtor(&z_copy);
1472 		zval_ptr_dtor(z);
1473 	} else {
1474 		zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1475 		ZVAL_NULL(EX_VAR(opline->result.var));
1476 	}
1477 }
1478 
zend_pre_incdec_overloaded_property(zval * object,zval * property,void ** cache_slot,int inc OPLINE_DC EXECUTE_DATA_DC)1479 static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc OPLINE_DC EXECUTE_DATA_DC)
1480 {
1481 	zval rv;
1482 
1483 	if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1484 		zval *z, obj;
1485 		zval z_copy;
1486 
1487 		ZVAL_OBJ(&obj, Z_OBJ_P(object));
1488 		Z_ADDREF(obj);
1489 		z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1490 		if (UNEXPECTED(EG(exception))) {
1491 			OBJ_RELEASE(Z_OBJ(obj));
1492 			if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1493 				ZVAL_NULL(EX_VAR(opline->result.var));
1494 			}
1495 			return;
1496 		}
1497 
1498 		if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1499 			zval rv2;
1500 			zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1501 
1502 			if (z == &rv) {
1503 				zval_ptr_dtor(&rv);
1504 			}
1505 			ZVAL_COPY_VALUE(z, value);
1506 		}
1507 		ZVAL_COPY_DEREF(&z_copy, z);
1508 		if (inc) {
1509 			increment_function(&z_copy);
1510 		} else {
1511 			decrement_function(&z_copy);
1512 		}
1513 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1514 			ZVAL_COPY(EX_VAR(opline->result.var), &z_copy);
1515 		}
1516 		Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
1517 		OBJ_RELEASE(Z_OBJ(obj));
1518 		zval_ptr_dtor(&z_copy);
1519 		zval_ptr_dtor(z);
1520 	} else {
1521 		zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1522 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1523 			ZVAL_NULL(EX_VAR(opline->result.var));
1524 		}
1525 	}
1526 }
1527 
zend_assign_op_overloaded_property(zval * object,zval * property,void ** cache_slot,zval * value,binary_op_type binary_op OPLINE_DC EXECUTE_DATA_DC)1528 static zend_never_inline void zend_assign_op_overloaded_property(zval *object, zval *property, void **cache_slot, zval *value, binary_op_type binary_op OPLINE_DC EXECUTE_DATA_DC)
1529 {
1530 	zval *z;
1531 	zval rv, obj, res;
1532 
1533 	ZVAL_OBJ(&obj, Z_OBJ_P(object));
1534 	Z_ADDREF(obj);
1535 	if (EXPECTED(Z_OBJ_HT(obj)->read_property)) {
1536 		z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1537 		if (UNEXPECTED(EG(exception))) {
1538 			OBJ_RELEASE(Z_OBJ(obj));
1539 			if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1540 				ZVAL_UNDEF(EX_VAR(opline->result.var));
1541 			}
1542 			return;
1543 		}
1544 		if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1545 			zval rv2;
1546 			zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1547 
1548 			if (z == &rv) {
1549 				zval_ptr_dtor(&rv);
1550 			}
1551 			ZVAL_COPY_VALUE(z, value);
1552 		}
1553 		binary_op(&res, z, value);
1554 		Z_OBJ_HT(obj)->write_property(&obj, property, &res, cache_slot);
1555 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1556 			ZVAL_COPY(EX_VAR(opline->result.var), &res);
1557 		}
1558 		zval_ptr_dtor(z);
1559 		zval_ptr_dtor(&res);
1560 	} else {
1561 		zend_error(E_WARNING, "Attempt to assign property of non-object");
1562 		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
1563 			ZVAL_NULL(EX_VAR(opline->result.var));
1564 		}
1565 	}
1566 	OBJ_RELEASE(Z_OBJ(obj));
1567 }
1568 
1569 /* Utility Functions for Extensions */
zend_extension_statement_handler(const zend_extension * extension,zend_execute_data * frame)1570 static void zend_extension_statement_handler(const zend_extension *extension, zend_execute_data *frame)
1571 {
1572 	if (extension->statement_handler) {
1573 		extension->statement_handler(frame);
1574 	}
1575 }
1576 
1577 
zend_extension_fcall_begin_handler(const zend_extension * extension,zend_execute_data * frame)1578 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_execute_data *frame)
1579 {
1580 	if (extension->fcall_begin_handler) {
1581 		extension->fcall_begin_handler(frame);
1582 	}
1583 }
1584 
1585 
zend_extension_fcall_end_handler(const zend_extension * extension,zend_execute_data * frame)1586 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_execute_data *frame)
1587 {
1588 	if (extension->fcall_end_handler) {
1589 		extension->fcall_end_handler(frame);
1590 	}
1591 }
1592 
1593 
zend_get_target_symbol_table(int fetch_type EXECUTE_DATA_DC)1594 static zend_always_inline HashTable *zend_get_target_symbol_table(int fetch_type EXECUTE_DATA_DC)
1595 {
1596 	HashTable *ht;
1597 
1598 	if (EXPECTED(fetch_type & (ZEND_FETCH_GLOBAL_LOCK | ZEND_FETCH_GLOBAL))) {
1599 		ht = &EG(symbol_table);
1600 	} else {
1601 		ZEND_ASSERT(fetch_type & ZEND_FETCH_LOCAL);
1602 		if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1603 			zend_rebuild_symbol_table();
1604 		}
1605 		ht = EX(symbol_table);
1606 	}
1607 	return ht;
1608 }
1609 
zend_undefined_offset(zend_long lval)1610 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_offset(zend_long lval)
1611 {
1612 	zend_error(E_NOTICE, "Undefined offset: " ZEND_LONG_FMT, lval);
1613 }
1614 
zend_undefined_index(const zend_string * offset)1615 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_index(const zend_string *offset)
1616 {
1617 	zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset));
1618 }
1619 
zend_undefined_method(const zend_class_entry * ce,const zend_string * method)1620 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_undefined_method(const zend_class_entry *ce, const zend_string *method)
1621 {
1622 	zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(method));
1623 }
1624 
zend_invalid_method_call(zval * object,zval * function_name)1625 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_invalid_method_call(zval *object, zval *function_name)
1626 {
1627 	zend_throw_error(NULL, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
1628 }
1629 
zend_non_static_method_call(const zend_function * fbc)1630 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_non_static_method_call(const zend_function *fbc)
1631 {
1632 	if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
1633 		zend_error(E_DEPRECATED,
1634 			"Non-static method %s::%s() should not be called statically",
1635 			ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
1636 	} else {
1637 		zend_throw_error(
1638 			zend_ce_error,
1639 			"Non-static method %s::%s() cannot be called statically",
1640 			ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
1641 	}
1642 }
1643 
zend_param_must_be_ref(const zend_function * func,uint32_t arg_num)1644 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num)
1645 {
1646 	zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
1647 		arg_num,
1648 		func->common.scope ? ZSTR_VAL(func->common.scope->name) : "",
1649 		func->common.scope ? "::" : "",
1650 		ZSTR_VAL(func->common.function_name));
1651 }
1652 
zend_use_scalar_as_array(void)1653 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_scalar_as_array(void)
1654 {
1655 	zend_error(E_WARNING, "Cannot use a scalar value as an array");
1656 }
1657 
zend_cannot_add_element(void)1658 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void)
1659 {
1660 	zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1661 }
1662 
zend_use_resource_as_offset(const zval * dim)1663 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim)
1664 {
1665 	zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
1666 }
1667 
zend_use_new_element_for_string(void)1668 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_new_element_for_string(void)
1669 {
1670 	zend_throw_error(NULL, "[] operator not supported for strings");
1671 }
1672 
zend_access_undefined_propery_in_overloaded_object(void)1673 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_access_undefined_propery_in_overloaded_object(void)
1674 {
1675 	zend_throw_error(NULL, "Cannot access undefined property for object with overloaded property access");
1676 }
1677 
zend_unsupported_property_reference(void)1678 static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_unsupported_property_reference(void)
1679 {
1680 	zend_error(E_WARNING, "This object doesn't support property references");
1681 }
1682 
zend_fetch_dimension_address_inner(HashTable * ht,const zval * dim,int dim_type,int type EXECUTE_DATA_DC)1683 static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type EXECUTE_DATA_DC)
1684 {
1685 	zval *retval = NULL;
1686 	zend_string *offset_key;
1687 	zend_ulong hval;
1688 
1689 try_again:
1690 	if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
1691 		hval = Z_LVAL_P(dim);
1692 num_index:
1693 		ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
1694 		return retval;
1695 num_undef:
1696 		switch (type) {
1697 			case BP_VAR_R:
1698 				zend_undefined_offset(hval);
1699 				/* break missing intentionally */
1700 			case BP_VAR_UNSET:
1701 			case BP_VAR_IS:
1702 				retval = &EG(uninitialized_zval);
1703 				break;
1704 			case BP_VAR_RW:
1705 				zend_undefined_offset(hval);
1706 				retval = zend_hash_index_update(ht, hval, &EG(uninitialized_zval));
1707 				break;
1708 			case BP_VAR_W:
1709 				retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
1710 				break;
1711 		}
1712 	} else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
1713 		offset_key = Z_STR_P(dim);
1714 		if (dim_type != IS_CONST) {
1715 			if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
1716 				goto num_index;
1717 			}
1718 		}
1719 str_index:
1720 		retval = zend_hash_find_ex(ht, offset_key, dim_type == IS_CONST);
1721 		if (retval) {
1722 			/* support for $GLOBALS[...] */
1723 			if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
1724 				retval = Z_INDIRECT_P(retval);
1725 				if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
1726 					switch (type) {
1727 						case BP_VAR_R:
1728 							zend_undefined_index(offset_key);
1729 							/* break missing intentionally */
1730 						case BP_VAR_UNSET:
1731 						case BP_VAR_IS:
1732 							retval = &EG(uninitialized_zval);
1733 							break;
1734 						case BP_VAR_RW:
1735 							zend_undefined_index(offset_key);
1736 							/* break missing intentionally */
1737 						case BP_VAR_W:
1738 							ZVAL_NULL(retval);
1739 							break;
1740 					}
1741 				}
1742 			}
1743 		} else {
1744 			switch (type) {
1745 				case BP_VAR_R:
1746 					zend_undefined_index(offset_key);
1747 					/* break missing intentionally */
1748 				case BP_VAR_UNSET:
1749 				case BP_VAR_IS:
1750 					retval = &EG(uninitialized_zval);
1751 					break;
1752 				case BP_VAR_RW:
1753 					zend_undefined_index(offset_key);
1754 					retval = zend_hash_update(ht, offset_key, &EG(uninitialized_zval));
1755 					break;
1756 				case BP_VAR_W:
1757 					retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
1758 					break;
1759 			}
1760 		}
1761 	} else {
1762 		switch (Z_TYPE_P(dim)) {
1763 			case IS_UNDEF:
1764 				zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1765 				/* break missing intentionally */
1766 			case IS_NULL:
1767 				offset_key = ZSTR_EMPTY_ALLOC();
1768 				goto str_index;
1769 			case IS_DOUBLE:
1770 				hval = zend_dval_to_lval(Z_DVAL_P(dim));
1771 				goto num_index;
1772 			case IS_RESOURCE:
1773 				zend_use_resource_as_offset(dim);
1774 				hval = Z_RES_HANDLE_P(dim);
1775 				goto num_index;
1776 			case IS_FALSE:
1777 				hval = 0;
1778 				goto num_index;
1779 			case IS_TRUE:
1780 				hval = 1;
1781 				goto num_index;
1782 			case IS_REFERENCE:
1783 				dim = Z_REFVAL_P(dim);
1784 				goto try_again;
1785 			default:
1786 				zend_illegal_offset();
1787 				retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
1788 					NULL : &EG(uninitialized_zval);
1789 		}
1790 	}
1791 	return retval;
1792 }
1793 
zend_fetch_dimension_address_inner_W(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1794 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1795 {
1796 	return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_W EXECUTE_DATA_CC);
1797 }
1798 
zend_fetch_dimension_address_inner_W_CONST(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1799 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1800 {
1801 	return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_W EXECUTE_DATA_CC);
1802 }
1803 
zend_fetch_dimension_address_inner_RW(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1804 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1805 {
1806 	return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_RW EXECUTE_DATA_CC);
1807 }
1808 
zend_fetch_dimension_address_inner_RW_CONST(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1809 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1810 {
1811 	return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_RW EXECUTE_DATA_CC);
1812 }
1813 
zend_fetch_dimension_address(zval * result,zval * container,zval * dim,int dim_type,int type EXECUTE_DATA_DC)1814 static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type EXECUTE_DATA_DC)
1815 {
1816     zval *retval;
1817 
1818 	if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1819 try_array:
1820 		SEPARATE_ARRAY(container);
1821 fetch_from_array:
1822 		if (dim == NULL) {
1823 			retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
1824 			if (UNEXPECTED(retval == NULL)) {
1825 				zend_cannot_add_element();
1826 				ZVAL_ERROR(result);
1827 				return;
1828 			}
1829 		} else {
1830 			retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
1831 			if (UNEXPECTED(!retval)) {
1832 				ZVAL_ERROR(result);
1833 				return;
1834 			}
1835 		}
1836 		ZVAL_INDIRECT(result, retval);
1837 		return;
1838 	} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1839 		container = Z_REFVAL_P(container);
1840 		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1841 			goto try_array;
1842 		}
1843 	}
1844 	if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1845 		if (dim == NULL) {
1846 			zend_use_new_element_for_string();
1847 		} else {
1848 			zend_check_string_offset(dim, type EXECUTE_DATA_CC);
1849 			zend_wrong_string_offset(EXECUTE_DATA_C);
1850 		}
1851 		ZVAL_ERROR(result);
1852 	} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1853 		if (/*dim_type == IS_CV &&*/ dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
1854 			zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1855 			dim = &EG(uninitialized_zval);
1856 		}
1857 		if (!Z_OBJ_HT_P(container)->read_dimension) {
1858 			zend_use_object_as_array();
1859 			ZVAL_ERROR(result);
1860 		} else {
1861 			if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
1862 				dim++;
1863 			}
1864 			retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
1865 
1866 			if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1867 				zend_class_entry *ce = Z_OBJCE_P(container);
1868 
1869 				ZVAL_NULL(result);
1870 				zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1871 			} else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1872 				if (!Z_ISREF_P(retval)) {
1873 					if (result != retval) {
1874 						ZVAL_COPY(result, retval);
1875 						retval = result;
1876 					}
1877 					if (Z_TYPE_P(retval) != IS_OBJECT) {
1878 						zend_class_entry *ce = Z_OBJCE_P(container);
1879 						zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1880 					}
1881 				} else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
1882 					ZVAL_UNREF(retval);
1883 				}
1884 				if (result != retval) {
1885 					ZVAL_INDIRECT(result, retval);
1886 				}
1887 			} else {
1888 				ZVAL_ERROR(result);
1889 			}
1890 		}
1891 	} else {
1892 		if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
1893 			zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
1894 		}
1895 		if (/*dim_type == IS_CV &&*/ dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
1896 			zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1897 		}
1898 		if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
1899 			if (type != BP_VAR_UNSET) {
1900 				array_init(container);
1901 				goto fetch_from_array;
1902 			} else {
1903 				/* for read-mode only */
1904 				ZVAL_NULL(result);
1905 			}
1906 		} else if (EXPECTED(Z_ISERROR_P(container))) {
1907 			ZVAL_ERROR(result);
1908 		} else {
1909 			if (type == BP_VAR_UNSET) {
1910 				zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1911 				ZVAL_NULL(result);
1912 			} else {
1913 				zend_use_scalar_as_array();
1914 				ZVAL_ERROR(result);
1915 			}
1916 		}
1917 	}
1918 }
1919 
zend_fetch_dimension_address_W(zval * container_ptr,zval * dim,int dim_type OPLINE_DC EXECUTE_DATA_DC)1920 static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_W(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
1921 {
1922 	zval *result = EX_VAR(opline->result.var);
1923 	zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W EXECUTE_DATA_CC);
1924 }
1925 
zend_fetch_dimension_address_RW(zval * container_ptr,zval * dim,int dim_type OPLINE_DC EXECUTE_DATA_DC)1926 static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_RW(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
1927 {
1928 	zval *result = EX_VAR(opline->result.var);
1929 	zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW EXECUTE_DATA_CC);
1930 }
1931 
zend_fetch_dimension_address_UNSET(zval * container_ptr,zval * dim,int dim_type OPLINE_DC EXECUTE_DATA_DC)1932 static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_UNSET(zval *container_ptr, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
1933 {
1934 	zval *result = EX_VAR(opline->result.var);
1935 	zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET EXECUTE_DATA_CC);
1936 }
1937 
zend_fetch_dimension_address_read(zval * result,zval * container,zval * dim,int dim_type,int type,int support_strings,int slow EXECUTE_DATA_DC)1938 static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, int support_strings, int slow EXECUTE_DATA_DC)
1939 {
1940 	zval *retval;
1941 
1942 	if (!slow) {
1943 		if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1944 try_array:
1945 			retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
1946 			ZVAL_COPY_DEREF(result, retval);
1947 			return;
1948 		} else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1949 			container = Z_REFVAL_P(container);
1950 			if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1951 				goto try_array;
1952 			}
1953 		}
1954 	}
1955 	if (support_strings && EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1956 		zend_long offset;
1957 
1958 try_string_offset:
1959 		if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1960 			switch (Z_TYPE_P(dim)) {
1961 				/* case IS_LONG: */
1962 				case IS_STRING:
1963 					if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1964 						break;
1965 					}
1966 					if (type == BP_VAR_IS) {
1967 						ZVAL_NULL(result);
1968 						return;
1969 					}
1970 					zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1971 					break;
1972 				case IS_UNDEF:
1973 					zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1974 				case IS_DOUBLE:
1975 				case IS_NULL:
1976 				case IS_FALSE:
1977 				case IS_TRUE:
1978 					if (type != BP_VAR_IS) {
1979 						zend_error(E_NOTICE, "String offset cast occurred");
1980 					}
1981 					break;
1982 				case IS_REFERENCE:
1983 					dim = Z_REFVAL_P(dim);
1984 					goto try_string_offset;
1985 				default:
1986 					zend_illegal_offset();
1987 					break;
1988 			}
1989 
1990 			offset = zval_get_long_func(dim);
1991 		} else {
1992 			offset = Z_LVAL_P(dim);
1993 		}
1994 
1995 		if (UNEXPECTED(Z_STRLEN_P(container) < (size_t)((offset < 0) ? -offset : (offset + 1)))) {
1996 			if (type != BP_VAR_IS) {
1997 				zend_error(E_NOTICE, "Uninitialized string offset: " ZEND_LONG_FMT, offset);
1998 				ZVAL_EMPTY_STRING(result);
1999 			} else {
2000 				ZVAL_NULL(result);
2001 			}
2002 		} else {
2003 			zend_uchar c;
2004 			zend_long real_offset;
2005 
2006 			real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
2007 				? (zend_long)Z_STRLEN_P(container) + offset : offset;
2008 			c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
2009 
2010 			ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
2011 		}
2012 	} else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2013 		if (/*dim_type == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
2014 			zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
2015 			dim = &EG(uninitialized_zval);
2016 		}
2017 		if (!Z_OBJ_HT_P(container)->read_dimension) {
2018 			zend_use_object_as_array();
2019 			ZVAL_NULL(result);
2020 		} else {
2021 			if (dim_type == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
2022 				dim++;
2023 			}
2024 			retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
2025 
2026 			ZEND_ASSERT(result != NULL);
2027 			if (retval) {
2028 				if (result != retval) {
2029 					ZVAL_COPY_DEREF(result, retval);
2030 				} else if (UNEXPECTED(Z_ISREF_P(retval))) {
2031 					zend_unwrap_reference(result);
2032 				}
2033 			} else {
2034 				ZVAL_NULL(result);
2035 			}
2036 		}
2037 	} else {
2038 		if (type != BP_VAR_IS && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
2039 			zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
2040 		}
2041 		if (/*dim_type == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
2042 			zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
2043 		}
2044 		ZVAL_NULL(result);
2045 	}
2046 }
2047 
zend_fetch_dimension_address_read_R(zval * container,zval * dim,int dim_type OPLINE_DC EXECUTE_DATA_DC)2048 static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_read_R(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
2049 {
2050 	zval *result = EX_VAR(opline->result.var);
2051 	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1, 0 EXECUTE_DATA_CC);
2052 }
2053 
zend_fetch_dimension_address_read_R_slow(zval * container,zval * dim OPLINE_DC EXECUTE_DATA_DC)2054 static zend_never_inline void zend_fetch_dimension_address_read_R_slow(zval *container, zval *dim OPLINE_DC EXECUTE_DATA_DC)
2055 {
2056 	zval *result = EX_VAR(opline->result.var);
2057 	zend_fetch_dimension_address_read(result, container, dim, IS_CV, BP_VAR_R, 1, 1 EXECUTE_DATA_CC);
2058 }
2059 
zend_fetch_dimension_address_read_IS(zval * container,zval * dim,int dim_type OPLINE_DC EXECUTE_DATA_DC)2060 static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_read_IS(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
2061 {
2062 	zval *result = EX_VAR(opline->result.var);
2063 	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0 EXECUTE_DATA_CC);
2064 }
2065 
zend_fetch_dimension_address_LIST_r(zval * container,zval * dim,int dim_type OPLINE_DC EXECUTE_DATA_DC)2066 static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_LIST_r(zval *container, zval *dim, int dim_type OPLINE_DC EXECUTE_DATA_DC)
2067 {
2068 	zval *result = EX_VAR(opline->result.var);
2069 	zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 0, 0 EXECUTE_DATA_CC);
2070 }
2071 
zend_fetch_dimension_const(zval * result,zval * container,zval * dim,int type)2072 ZEND_API void zend_fetch_dimension_const(zval *result, zval *container, zval *dim, int type)
2073 {
2074 	zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, type, 1, 0 NO_EXECUTE_DATA_CC);
2075 }
2076 
zend_find_array_dim_slow(HashTable * ht,zval * offset EXECUTE_DATA_DC)2077 static zend_never_inline zval* ZEND_FASTCALL zend_find_array_dim_slow(HashTable *ht, zval *offset EXECUTE_DATA_DC)
2078 {
2079 	zend_ulong hval;
2080 
2081 	if (Z_TYPE_P(offset) == IS_DOUBLE) {
2082 		hval = zend_dval_to_lval(Z_DVAL_P(offset));
2083 num_idx:
2084 		return zend_hash_index_find(ht, hval);
2085 	} else if (Z_TYPE_P(offset) == IS_NULL) {
2086 str_idx:
2087 		return zend_hash_find_ex_ind(ht, ZSTR_EMPTY_ALLOC(), 1);
2088 	} else if (Z_TYPE_P(offset) == IS_FALSE) {
2089 		hval = 0;
2090 		goto num_idx;
2091 	} else if (Z_TYPE_P(offset) == IS_TRUE) {
2092 		hval = 1;
2093 		goto num_idx;
2094 	} else if (Z_TYPE_P(offset) == IS_RESOURCE) {
2095 		hval = Z_RES_HANDLE_P(offset);
2096 		goto num_idx;
2097 	} else if (/*OP2_TYPE == IS_CV &&*/ Z_TYPE_P(offset) == IS_UNDEF) {
2098 		zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
2099 		goto str_idx;
2100 	} else {
2101 		zend_error(E_WARNING, "Illegal offset type in isset or empty");
2102 		return NULL;
2103 	}
2104 }
2105 
zend_isset_dim_slow(zval * container,zval * offset EXECUTE_DATA_DC)2106 static zend_never_inline int ZEND_FASTCALL zend_isset_dim_slow(zval *container, zval *offset EXECUTE_DATA_DC)
2107 {
2108 	if (/*OP2_TYPE == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
2109 		zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
2110 		offset = &EG(uninitialized_zval);
2111 	}
2112 
2113 	if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2114 		if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
2115 			return Z_OBJ_HT_P(container)->has_dimension(container, offset, 0);
2116 		} else {
2117 			zend_use_object_as_array();
2118 			return 0;
2119 		}
2120 	} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
2121 		zend_long lval;
2122 
2123 		if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
2124 			lval = Z_LVAL_P(offset);
2125 str_offset:
2126 			if (UNEXPECTED(lval < 0)) { /* Handle negative offset */
2127 				lval += (zend_long)Z_STRLEN_P(container);
2128 			}
2129 			if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
2130 				return 1;
2131 			} else {
2132 				return 0;
2133 			}
2134 		} else {
2135 			/*if (OP2_TYPE & (IS_CV|IS_VAR)) {*/
2136 				ZVAL_DEREF(offset);
2137 			/*}*/
2138 			if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
2139 					|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
2140 						&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
2141 				lval = zval_get_long(offset);
2142 				goto str_offset;
2143 			}
2144 			return 0;
2145 		}
2146 	} else {
2147 		return 0;
2148 	}
2149 }
2150 
zend_isempty_dim_slow(zval * container,zval * offset EXECUTE_DATA_DC)2151 static zend_never_inline int ZEND_FASTCALL zend_isempty_dim_slow(zval *container, zval *offset EXECUTE_DATA_DC)
2152 {
2153 	if (/*OP2_TYPE == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
2154 		zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
2155 		offset = &EG(uninitialized_zval);
2156 	}
2157 
2158 	if (/*OP1_TYPE != IS_CONST &&*/ EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2159 		if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
2160 			return !Z_OBJ_HT_P(container)->has_dimension(container, offset, 1);
2161 		} else {
2162 			zend_use_object_as_array();
2163 			return 1;
2164 		}
2165 	} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
2166 		zend_long lval;
2167 
2168 		if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
2169 			lval = Z_LVAL_P(offset);
2170 str_offset:
2171 			if (UNEXPECTED(lval < 0)) { /* Handle negative offset */
2172 				lval += (zend_long)Z_STRLEN_P(container);
2173 			}
2174 			if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
2175 				return (Z_STRVAL_P(container)[lval] == '0');
2176 			} else {
2177 				return 1;
2178 			}
2179 		} else {
2180 			/*if (OP2_TYPE & (IS_CV|IS_VAR)) {*/
2181 				ZVAL_DEREF(offset);
2182 			/*}*/
2183 			if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
2184 					|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
2185 						&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
2186 				lval = zval_get_long(offset);
2187 				goto str_offset;
2188 			}
2189 			return 1;
2190 		}
2191 	} else {
2192 		return 1;
2193 	}
2194 }
2195 
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 OPLINE_DC)2196 static 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 OPLINE_DC)
2197 {
2198     if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
2199 		do {
2200 			if (Z_ISREF_P(container)) {
2201 				container = Z_REFVAL_P(container);
2202 				if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
2203 					break;
2204 				}
2205 			}
2206 
2207 			/* this should modify object only if it's empty */
2208 			if (type == BP_VAR_UNSET ||
2209 				UNEXPECTED(!make_real_object_rw(container, prop_ptr OPLINE_CC))) {
2210 				ZVAL_ERROR(result);
2211 				return;
2212 			}
2213 		} while (0);
2214 	}
2215 	if (prop_op_type == IS_CONST &&
2216 	    EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) {
2217 		uintptr_t prop_offset = (uintptr_t)CACHED_PTR_EX(cache_slot + 1);
2218 		zend_object *zobj = Z_OBJ_P(container);
2219 		zval *retval;
2220 
2221 		if (EXPECTED(IS_VALID_PROPERTY_OFFSET(prop_offset))) {
2222 			retval = OBJ_PROP(zobj, prop_offset);
2223 			if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
2224 				ZVAL_INDIRECT(result, retval);
2225 				return;
2226 			}
2227 		} else if (EXPECTED(zobj->properties != NULL)) {
2228 			if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
2229 				if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
2230 					GC_DELREF(zobj->properties);
2231 				}
2232 				zobj->properties = zend_array_dup(zobj->properties);
2233 			}
2234 			retval = zend_hash_find_ex(zobj->properties, Z_STR_P(prop_ptr), 1);
2235 			if (EXPECTED(retval)) {
2236 				ZVAL_INDIRECT(result, retval);
2237 				return;
2238 			}
2239 		}
2240 	}
2241 	if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
2242 		zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot);
2243 		if (NULL == ptr) {
2244 			if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
2245 use_read_property:
2246 				ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
2247 				if (ptr != result) {
2248 					ZVAL_INDIRECT(result, ptr);
2249 				} else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
2250 					ZVAL_UNREF(ptr);
2251 				}
2252 			} else {
2253 				zend_access_undefined_propery_in_overloaded_object();
2254 				ZVAL_ERROR(result);
2255 			}
2256 		} else {
2257 			ZVAL_INDIRECT(result, ptr);
2258 		}
2259 	} else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
2260 		goto use_read_property;
2261 	} else {
2262 		zend_unsupported_property_reference();
2263 		ZVAL_ERROR(result);
2264 	}
2265 }
2266 
zend_fetch_this_var(int type OPLINE_DC EXECUTE_DATA_DC)2267 static zend_never_inline void zend_fetch_this_var(int type OPLINE_DC EXECUTE_DATA_DC)
2268 {
2269 	zval *result = EX_VAR(opline->result.var);
2270 
2271 	switch (type) {
2272 		case BP_VAR_R:
2273 			if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
2274 				ZVAL_OBJ(result, Z_OBJ(EX(This)));
2275 				Z_ADDREF_P(result);
2276 			} else {
2277 				ZVAL_NULL(result);
2278 				zend_error(E_NOTICE,"Undefined variable: this");
2279 			}
2280 			break;
2281 		case BP_VAR_IS:
2282 			if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
2283 				ZVAL_OBJ(result, Z_OBJ(EX(This)));
2284 				Z_ADDREF_P(result);
2285 			} else {
2286 				ZVAL_NULL(result);
2287 			}
2288 			break;
2289 		case BP_VAR_RW:
2290 		case BP_VAR_W:
2291 			ZVAL_UNDEF(result);
2292 			zend_throw_error(NULL, "Cannot re-assign $this");
2293 			break;
2294 		case BP_VAR_UNSET:
2295 			ZVAL_UNDEF(result);
2296 			zend_throw_error(NULL, "Cannot unset $this");
2297 			break;
2298 		EMPTY_SWITCH_DEFAULT_CASE()
2299 	}
2300 }
2301 
2302 
2303 #if ZEND_INTENSIVE_DEBUGGING
2304 
2305 #define CHECK_SYMBOL_TABLES()													\
2306 	zend_hash_apply(&EG(symbol_table), zend_check_symbol);			\
2307 	if (&EG(symbol_table)!=EX(symbol_table)) {							\
2308 		zend_hash_apply(EX(symbol_table), zend_check_symbol);	\
2309 	}
2310 
zend_check_symbol(zval * pz)2311 static int zend_check_symbol(zval *pz)
2312 {
2313 	if (Z_TYPE_P(pz) == IS_INDIRECT) {
2314 		pz = Z_INDIRECT_P(pz);
2315 	}
2316 	if (Z_TYPE_P(pz) > 10) {
2317 		fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
2318 /* See http://support.microsoft.com/kb/190351 */
2319 #ifdef ZEND_WIN32
2320 		fflush(stderr);
2321 #endif
2322 	} else if (Z_TYPE_P(pz) == IS_ARRAY) {
2323 		zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol);
2324 	} else if (Z_TYPE_P(pz) == IS_OBJECT) {
2325 		/* OBJ-TBI - doesn't support new object model! */
2326 		zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol);
2327 	}
2328 
2329 	return 0;
2330 }
2331 
2332 
2333 #else
2334 #define CHECK_SYMBOL_TABLES()
2335 #endif
2336 
execute_internal(zend_execute_data * execute_data,zval * return_value)2337 ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value)
2338 {
2339 	execute_data->func->internal_function.handler(execute_data, return_value);
2340 }
2341 
zend_clean_and_cache_symbol_table(zend_array * symbol_table)2342 ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{ */
2343 {
2344 	if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
2345 		zend_array_destroy(symbol_table);
2346 	} else {
2347 		/* clean before putting into the cache, since clean
2348 		   could call dtors, which could use cached hash */
2349 		zend_symtable_clean(symbol_table);
2350 		*(++EG(symtable_cache_ptr)) = symbol_table;
2351 	}
2352 }
2353 /* }}} */
2354 
i_free_compiled_variables(zend_execute_data * execute_data)2355 static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
2356 {
2357 	zval *cv = EX_VAR_NUM(0);
2358 	int count = EX(func)->op_array.last_var;
2359 	while (EXPECTED(count != 0)) {
2360 		if (Z_REFCOUNTED_P(cv)) {
2361 			zend_refcounted *r = Z_COUNTED_P(cv);
2362 			if (!GC_DELREF(r)) {
2363 				ZVAL_NULL(cv);
2364 				rc_dtor_func(r);
2365 			} else {
2366 				gc_check_possible_root(r);
2367 			}
2368 		}
2369 		cv++;
2370 		count--;
2371 	}
2372 }
2373 /* }}} */
2374 
zend_free_compiled_variables(zend_execute_data * execute_data)2375 ZEND_API void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
2376 {
2377 	i_free_compiled_variables(execute_data);
2378 }
2379 /* }}} */
2380 
2381 #define ZEND_VM_INTERRUPT_CHECK() do { \
2382 		if (UNEXPECTED(EG(vm_interrupt))) { \
2383 			ZEND_VM_INTERRUPT(); \
2384 		} \
2385 	} while (0)
2386 
2387 #define ZEND_VM_LOOP_INTERRUPT_CHECK() do { \
2388 		if (UNEXPECTED(EG(vm_interrupt))) { \
2389 			ZEND_VM_LOOP_INTERRUPT(); \
2390 		} \
2391 	} while (0)
2392 
2393 /*
2394  * Stack Frame Layout (the whole stack frame is allocated at once)
2395  * ==================
2396  *
2397  *                             +========================================+
2398  * EG(current_execute_data) -> | zend_execute_data                      |
2399  *                             +----------------------------------------+
2400  *     EX_CV_NUM(0) ---------> | VAR[0] = ARG[1]                        |
2401  *                             | ...                                    |
2402  *                             | VAR[op_array->num_args-1] = ARG[N]     |
2403  *                             | ...                                    |
2404  *                             | VAR[op_array->last_var-1]              |
2405  *                             | VAR[op_array->last_var] = TMP[0]       |
2406  *                             | ...                                    |
2407  *                             | VAR[op_array->last_var+op_array->T-1]  |
2408  *                             | ARG[N+1] (extra_args)                  |
2409  *                             | ...                                    |
2410  *                             +----------------------------------------+
2411  */
2412 
zend_copy_extra_args(EXECUTE_DATA_D)2413 static zend_never_inline void zend_copy_extra_args(EXECUTE_DATA_D)
2414 {
2415 	zend_op_array *op_array = &EX(func)->op_array;
2416 	uint32_t first_extra_arg = op_array->num_args;
2417 	uint32_t num_args = EX_NUM_ARGS();
2418 	zval *src;
2419 	size_t delta;
2420 	uint32_t count;
2421 	uint32_t type_flags = 0;
2422 
2423 	if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2424 		/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2425 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
2426 		opline += first_extra_arg;
2427 #else
2428 		EX(opline) += first_extra_arg;
2429 #endif
2430 
2431 	}
2432 
2433 	/* move extra args into separate array after all CV and TMP vars */
2434 	src = EX_VAR_NUM(num_args - 1);
2435 	delta = op_array->last_var + op_array->T - first_extra_arg;
2436 	count = num_args - first_extra_arg;
2437 	if (EXPECTED(delta != 0)) {
2438 		delta *= sizeof(zval);
2439 		do {
2440 			type_flags |= Z_TYPE_INFO_P(src);
2441 			ZVAL_COPY_VALUE((zval*)(((char*)src) + delta), src);
2442 			ZVAL_UNDEF(src);
2443 			src--;
2444 		} while (--count);
2445 		if (Z_TYPE_INFO_REFCOUNTED(type_flags)) {
2446 			ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
2447 		}
2448 	} else {
2449 		do {
2450 			if (Z_REFCOUNTED_P(src)) {
2451 				ZEND_ADD_CALL_FLAG(execute_data, ZEND_CALL_FREE_EXTRA_ARGS);
2452 				break;
2453 			}
2454 			src--;
2455 		} while (--count);
2456 	}
2457 }
2458 
zend_init_cvs(uint32_t first,uint32_t last EXECUTE_DATA_DC)2459 static zend_always_inline void zend_init_cvs(uint32_t first, uint32_t last EXECUTE_DATA_DC)
2460 {
2461 	if (EXPECTED(first < last)) {
2462 		uint32_t count = last - first;
2463 		zval *var = EX_VAR_NUM(first);
2464 
2465 		do {
2466 			ZVAL_UNDEF(var);
2467 			var++;
2468 		} while (--count);
2469 	}
2470 }
2471 
i_init_func_execute_data(zend_op_array * op_array,zval * return_value,zend_bool may_be_trampoline EXECUTE_DATA_DC)2472 static zend_always_inline void i_init_func_execute_data(zend_op_array *op_array, zval *return_value, zend_bool may_be_trampoline EXECUTE_DATA_DC) /* {{{ */
2473 {
2474 	uint32_t first_extra_arg, num_args;
2475 	ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2476 
2477 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
2478 	opline = op_array->opcodes;
2479 #else
2480 	EX(opline) = op_array->opcodes;
2481 #endif
2482 	EX(call) = NULL;
2483 	EX(return_value) = return_value;
2484 
2485 	/* Handle arguments */
2486 	first_extra_arg = op_array->num_args;
2487 	num_args = EX_NUM_ARGS();
2488 	if (UNEXPECTED(num_args > first_extra_arg)) {
2489 		if (!may_be_trampoline || EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
2490 			zend_copy_extra_args(EXECUTE_DATA_C);
2491 		}
2492 	} else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2493 		/* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2494 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
2495 		opline += num_args;
2496 #else
2497 		EX(opline) += num_args;
2498 #endif
2499 	}
2500 
2501 	/* Initialize CV variables (skip arguments) */
2502 	zend_init_cvs(num_args, op_array->last_var EXECUTE_DATA_CC);
2503 
2504 	EX_LOAD_RUN_TIME_CACHE(op_array);
2505 
2506 	EG(current_execute_data) = execute_data;
2507 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
2508 	EX(opline) = opline;
2509 #endif
2510 }
2511 /* }}} */
2512 
init_func_run_time_cache(zend_op_array * op_array)2513 static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
2514 {
2515 	ZEND_ASSERT(op_array->run_time_cache == NULL);
2516 	op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2517 	memset(op_array->run_time_cache, 0, op_array->cache_size);
2518 }
2519 /* }}} */
2520 
init_func_run_time_cache_i(zval * zv)2521 static zend_always_inline zend_function* ZEND_FASTCALL init_func_run_time_cache_i(zval *zv) /* {{{ */
2522 {
2523 	zend_op_array *op_array = Z_PTR_P(zv);
2524 
2525 	ZEND_ASSERT(op_array->run_time_cache == NULL);
2526 	if (op_array->fn_flags & ZEND_ACC_IMMUTABLE) {
2527 		zend_op_array *new_op_array = zend_arena_alloc(&CG(arena), sizeof(zend_op_array) + op_array->cache_size);
2528 
2529 		Z_PTR_P(zv) = new_op_array;
2530 		memcpy(new_op_array, op_array, sizeof(zend_op_array));
2531 		new_op_array->fn_flags &= ~ZEND_ACC_IMMUTABLE;
2532 		new_op_array->run_time_cache = (void**)(new_op_array + 1);
2533 		memset(new_op_array->run_time_cache, 0, new_op_array->cache_size);
2534 		return (zend_function*)new_op_array;
2535 	} else {
2536 		op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2537 		memset(op_array->run_time_cache, 0, op_array->cache_size);
2538 		return (zend_function*)op_array;
2539 	}
2540 }
2541 /* }}} */
2542 
init_func_run_time_cache_ex(zval * zv)2543 static zend_never_inline zend_function* init_func_run_time_cache_ex(zval *zv) /* {{{ */
2544 {
2545 	return init_func_run_time_cache_i(zv);
2546 }
2547 /* }}} */
2548 
zend_fetch_function(zend_string * name)2549 ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function(zend_string *name) /* {{{ */
2550 {
2551 	zval *zv = zend_hash_find(EG(function_table), name);
2552 
2553 	if (EXPECTED(zv != NULL)) {
2554 		zend_function *fbc = Z_FUNC_P(zv);
2555 
2556 		if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
2557 			fbc = (zend_function*)init_func_run_time_cache_i(zv);
2558 		}
2559 		return fbc;
2560 	}
2561 	return NULL;
2562 } /* }}} */
2563 
zend_fetch_function_str(const char * name,size_t len)2564 ZEND_API zend_function * ZEND_FASTCALL zend_fetch_function_str(const char *name, size_t len) /* {{{ */
2565 {
2566 	zval *zv = zend_hash_str_find(EG(function_table), name, len);
2567 
2568 	if (EXPECTED(zv != NULL)) {
2569 		zend_function *fbc = Z_FUNC_P(zv);
2570 
2571 		if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
2572 			fbc = (zend_function*)init_func_run_time_cache_i(zv);
2573 		}
2574 		return fbc;
2575 	}
2576 	return NULL;
2577 } /* }}} */
2578 
i_init_code_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2579 static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2580 {
2581 	ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2582 
2583 	EX(opline) = op_array->opcodes;
2584 	EX(call) = NULL;
2585 	EX(return_value) = return_value;
2586 
2587 	zend_attach_symbol_table(execute_data);
2588 
2589 	if (!op_array->run_time_cache) {
2590 		op_array->run_time_cache = emalloc(op_array->cache_size);
2591 		memset(op_array->run_time_cache, 0, op_array->cache_size);
2592 	}
2593 	EX_LOAD_RUN_TIME_CACHE(op_array);
2594 
2595 	EG(current_execute_data) = execute_data;
2596 }
2597 /* }}} */
2598 
zend_init_func_execute_data(zend_execute_data * ex,zend_op_array * op_array,zval * return_value)2599 ZEND_API void zend_init_func_execute_data(zend_execute_data *ex, zend_op_array *op_array, zval *return_value) /* {{{ */
2600 {
2601 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
2602 	zend_execute_data *orig_execute_data = execute_data;
2603 	const zend_op *orig_opline = opline;
2604 	execute_data = ex;
2605 #else
2606 	zend_execute_data *execute_data = ex;
2607 #endif
2608 
2609 	EX(prev_execute_data) = EG(current_execute_data);
2610 	if (!op_array->run_time_cache) {
2611 		init_func_run_time_cache(op_array);
2612 	}
2613 	i_init_func_execute_data(op_array, return_value, 1 EXECUTE_DATA_CC);
2614 
2615 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
2616     EX(opline) = opline;
2617 	opline = orig_opline;
2618 	execute_data = orig_execute_data;
2619 #endif
2620 }
2621 /* }}} */
2622 
zend_init_code_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2623 ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2624 {
2625 	EX(prev_execute_data) = EG(current_execute_data);
2626 	if (!op_array->run_time_cache) {
2627 		op_array->run_time_cache = emalloc(op_array->cache_size);
2628 		memset(op_array->run_time_cache, 0, op_array->cache_size);
2629 	}
2630 	i_init_code_execute_data(execute_data, op_array, return_value);
2631 }
2632 /* }}} */
2633 
zend_init_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2634 ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2635 {
2636 	if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
2637 		zend_init_code_execute_data(execute_data, op_array, return_value);
2638 	} else {
2639 		zend_init_func_execute_data(execute_data, op_array, return_value);
2640 	}
2641 }
2642 /* }}} */
2643 
zend_is_by_ref_func_arg_fetch(uint32_t arg_num,zend_function * func)2644 static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(uint32_t arg_num, zend_function *func) /* {{{ */
2645 {
2646 	if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
2647 		return QUICK_ARG_SHOULD_BE_SENT_BY_REF(func, arg_num);
2648 	}
2649 	return ARG_SHOULD_BE_SENT_BY_REF(func, arg_num);
2650 }
2651 /* }}} */
2652 
zend_vm_stack_copy_call_frame(zend_execute_data * call,uint32_t passed_args,uint32_t additional_args)2653 static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
2654 {
2655 	zend_execute_data *new_call;
2656 	int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
2657 
2658 	/* copy call frame into new stack segment */
2659 	new_call = zend_vm_stack_extend(used_stack * sizeof(zval));
2660 	*new_call = *call;
2661 	ZEND_ADD_CALL_FLAG(new_call, ZEND_CALL_ALLOCATED);
2662 
2663 	if (passed_args) {
2664 		zval *src = ZEND_CALL_ARG(call, 1);
2665 		zval *dst = ZEND_CALL_ARG(new_call, 1);
2666 		do {
2667 			ZVAL_COPY_VALUE(dst, src);
2668 			passed_args--;
2669 			src++;
2670 			dst++;
2671 		} while (passed_args);
2672 	}
2673 
2674 	/* delete old call_frame from previous stack segment */
2675 	EG(vm_stack)->prev->top = (zval*)call;
2676 
2677 	/* delete previous stack segment if it becames empty */
2678 	if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMENTS(EG(vm_stack)->prev))) {
2679 		zend_vm_stack r = EG(vm_stack)->prev;
2680 
2681 		EG(vm_stack)->prev = r->prev;
2682 		efree(r);
2683 	}
2684 
2685 	return new_call;
2686 }
2687 /* }}} */
2688 
zend_vm_stack_extend_call_frame(zend_execute_data ** call,uint32_t passed_args,uint32_t additional_args)2689 static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
2690 {
2691 	if (EXPECTED((uint32_t)(EG(vm_stack_end) - EG(vm_stack_top)) > additional_args)) {
2692 		EG(vm_stack_top) += additional_args;
2693 	} else {
2694 		*call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args);
2695 	}
2696 }
2697 /* }}} */
2698 
zend_get_running_generator(EXECUTE_DATA_D)2699 static zend_always_inline zend_generator *zend_get_running_generator(EXECUTE_DATA_D) /* {{{ */
2700 {
2701 	/* The generator object is stored in EX(return_value) */
2702 	zend_generator *generator = (zend_generator *) EX(return_value);
2703 	/* However control may currently be delegated to another generator.
2704 	 * That's the one we're interested in. */
2705 	return generator;
2706 }
2707 /* }}} */
2708 
cleanup_unfinished_calls(zend_execute_data * execute_data,uint32_t op_num)2709 static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t op_num) /* {{{ */
2710 {
2711 	if (UNEXPECTED(EX(call))) {
2712 		zend_execute_data *call = EX(call);
2713 		zend_op *opline = EX(func)->op_array.opcodes + op_num;
2714 		int level;
2715 		int do_exit;
2716 
2717 		if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
2718 			opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
2719 			opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
2720 			opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
2721 			opline->opcode == ZEND_INIT_USER_CALL ||
2722 			opline->opcode == ZEND_INIT_METHOD_CALL ||
2723 			opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
2724 			opline->opcode == ZEND_NEW)) {
2725 			ZEND_ASSERT(op_num);
2726 			opline--;
2727 		}
2728 
2729 		do {
2730 			/* If the exception was thrown during a function call there might be
2731 			 * arguments pushed to the stack that have to be dtor'ed. */
2732 
2733 			/* find the number of actually passed arguments */
2734 			level = 0;
2735 			do_exit = 0;
2736 			do {
2737 				switch (opline->opcode) {
2738 					case ZEND_DO_FCALL:
2739 					case ZEND_DO_ICALL:
2740 					case ZEND_DO_UCALL:
2741 					case ZEND_DO_FCALL_BY_NAME:
2742 						level++;
2743 						break;
2744 					case ZEND_INIT_FCALL:
2745 					case ZEND_INIT_FCALL_BY_NAME:
2746 					case ZEND_INIT_NS_FCALL_BY_NAME:
2747 					case ZEND_INIT_DYNAMIC_CALL:
2748 					case ZEND_INIT_USER_CALL:
2749 					case ZEND_INIT_METHOD_CALL:
2750 					case ZEND_INIT_STATIC_METHOD_CALL:
2751 					case ZEND_NEW:
2752 						if (level == 0) {
2753 							ZEND_CALL_NUM_ARGS(call) = 0;
2754 							do_exit = 1;
2755 						}
2756 						level--;
2757 						break;
2758 					case ZEND_SEND_VAL:
2759 					case ZEND_SEND_VAL_EX:
2760 					case ZEND_SEND_VAR:
2761 					case ZEND_SEND_VAR_EX:
2762 					case ZEND_SEND_FUNC_ARG:
2763 					case ZEND_SEND_REF:
2764 					case ZEND_SEND_VAR_NO_REF:
2765 					case ZEND_SEND_VAR_NO_REF_EX:
2766 					case ZEND_SEND_USER:
2767 						if (level == 0) {
2768 							ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
2769 							do_exit = 1;
2770 						}
2771 						break;
2772 					case ZEND_SEND_ARRAY:
2773 					case ZEND_SEND_UNPACK:
2774 						if (level == 0) {
2775 							do_exit = 1;
2776 						}
2777 						break;
2778 				}
2779 				if (!do_exit) {
2780 					opline--;
2781 				}
2782 			} while (!do_exit);
2783 			if (call->prev_execute_data) {
2784 				/* skip current call region */
2785 				level = 0;
2786 				do_exit = 0;
2787 				do {
2788 					switch (opline->opcode) {
2789 						case ZEND_DO_FCALL:
2790 						case ZEND_DO_ICALL:
2791 						case ZEND_DO_UCALL:
2792 						case ZEND_DO_FCALL_BY_NAME:
2793 							level++;
2794 							break;
2795 						case ZEND_INIT_FCALL:
2796 						case ZEND_INIT_FCALL_BY_NAME:
2797 						case ZEND_INIT_NS_FCALL_BY_NAME:
2798 						case ZEND_INIT_DYNAMIC_CALL:
2799 						case ZEND_INIT_USER_CALL:
2800 						case ZEND_INIT_METHOD_CALL:
2801 						case ZEND_INIT_STATIC_METHOD_CALL:
2802 						case ZEND_NEW:
2803 							if (level == 0) {
2804 								do_exit = 1;
2805 							}
2806 							level--;
2807 							break;
2808 					}
2809 					opline--;
2810 				} while (!do_exit);
2811 			}
2812 
2813 			zend_vm_stack_free_args(EX(call));
2814 
2815 			if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
2816 				if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
2817 					GC_DELREF(Z_OBJ(call->This));
2818 					if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
2819 						zend_object_store_ctor_failed(Z_OBJ(call->This));
2820 					}
2821 				}
2822 				OBJ_RELEASE(Z_OBJ(call->This));
2823 			}
2824 			if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2825 				zend_object_release(ZEND_CLOSURE_OBJECT(call->func));
2826 			} else if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2827 				zend_string_release_ex(call->func->common.function_name, 0);
2828 				zend_free_trampoline(call->func);
2829 			}
2830 
2831 			EX(call) = call->prev_execute_data;
2832 			zend_vm_stack_free_call_frame(call);
2833 			call = EX(call);
2834 		} while (call);
2835 	}
2836 }
2837 /* }}} */
2838 
find_live_range(const zend_op_array * op_array,uint32_t op_num,uint32_t var_num)2839 static const zend_live_range *find_live_range(const zend_op_array *op_array, uint32_t op_num, uint32_t var_num) /* {{{ */
2840 {
2841 	int i;
2842 	for (i = 0; i < op_array->last_live_range; i++) {
2843 		const zend_live_range *range = &op_array->live_range[i];
2844 		if (op_num >= range->start && op_num < range->end
2845 				&& var_num == (range->var & ~ZEND_LIVE_MASK)) {
2846 			return range;
2847 		}
2848 	}
2849 	return NULL;
2850 }
2851 /* }}} */
2852 
cleanup_live_vars(zend_execute_data * execute_data,uint32_t op_num,uint32_t catch_op_num)2853 static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
2854 {
2855 	int i;
2856 
2857 	for (i = 0; i < EX(func)->op_array.last_live_range; i++) {
2858 		const zend_live_range *range = &EX(func)->op_array.live_range[i];
2859 		if (range->start > op_num) {
2860 			/* further blocks will not be relevant... */
2861 			break;
2862 		} else if (op_num < range->end) {
2863 			if (!catch_op_num || catch_op_num >= range->end) {
2864 				uint32_t kind = range->var & ZEND_LIVE_MASK;
2865 				uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
2866 				zval *var = EX_VAR(var_num);
2867 
2868 				if (kind == ZEND_LIVE_TMPVAR) {
2869 					zval_ptr_dtor_nogc(var);
2870 				} else if (kind == ZEND_LIVE_LOOP) {
2871 					if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
2872 						zend_hash_iterator_del(Z_FE_ITER_P(var));
2873 					}
2874 					zval_ptr_dtor_nogc(var);
2875 				} else if (kind == ZEND_LIVE_ROPE) {
2876 					zend_string **rope = (zend_string **)var;
2877 					zend_op *last = EX(func)->op_array.opcodes + op_num;
2878 					while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
2879 							|| last->result.var != var_num) {
2880 						ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
2881 						last--;
2882 					}
2883 					if (last->opcode == ZEND_ROPE_INIT) {
2884 						zend_string_release_ex(*rope, 0);
2885 					} else {
2886 						int j = last->extended_value;
2887 						do {
2888 							zend_string_release_ex(rope[j], 0);
2889 						} while (j--);
2890 					}
2891 				} else if (kind == ZEND_LIVE_SILENCE) {
2892 					/* restore previous error_reporting value */
2893 					if (!EG(error_reporting) && Z_LVAL_P(var) != 0) {
2894 						EG(error_reporting) = Z_LVAL_P(var);
2895 					}
2896 				}
2897 			}
2898 		}
2899 	}
2900 }
2901 /* }}} */
2902 
zend_cleanup_unfinished_execution(zend_execute_data * execute_data,uint32_t op_num,uint32_t catch_op_num)2903 ZEND_API void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) {
2904 	cleanup_unfinished_calls(execute_data, op_num);
2905 	cleanup_live_vars(execute_data, op_num, catch_op_num);
2906 }
2907 
zend_swap_operands(zend_op * op)2908 static void zend_swap_operands(zend_op *op) /* {{{ */
2909 {
2910 	znode_op     tmp;
2911 	zend_uchar   tmp_type;
2912 
2913 	tmp          = op->op1;
2914 	tmp_type     = op->op1_type;
2915 	op->op1      = op->op2;
2916 	op->op1_type = op->op2_type;
2917 	op->op2      = tmp;
2918 	op->op2_type = tmp_type;
2919 }
2920 /* }}} */
2921 
zend_init_dynamic_call_string(zend_string * function,uint32_t num_args)2922 static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
2923 {
2924 	zend_function *fbc;
2925 	zval *func;
2926 	zend_class_entry *called_scope;
2927 	zend_string *lcname;
2928 	const char *colon;
2929 
2930 	if ((colon = zend_memrchr(ZSTR_VAL(function), ':', ZSTR_LEN(function))) != NULL &&
2931 		colon > ZSTR_VAL(function) &&
2932 		*(colon-1) == ':'
2933 	) {
2934 		zend_string *mname;
2935 		size_t cname_length = colon - ZSTR_VAL(function) - 1;
2936 		size_t mname_length = ZSTR_LEN(function) - cname_length - (sizeof("::") - 1);
2937 
2938 		lcname = zend_string_init(ZSTR_VAL(function), cname_length, 0);
2939 
2940 		called_scope = zend_fetch_class_by_name(lcname, NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
2941 		if (UNEXPECTED(called_scope == NULL)) {
2942 			zend_string_release_ex(lcname, 0);
2943 			return NULL;
2944 		}
2945 
2946 		mname = zend_string_init(ZSTR_VAL(function) + (cname_length + sizeof("::") - 1), mname_length, 0);
2947 
2948 		if (called_scope->get_static_method) {
2949 			fbc = called_scope->get_static_method(called_scope, mname);
2950 		} else {
2951 			fbc = zend_std_get_static_method(called_scope, mname, NULL);
2952 		}
2953 		if (UNEXPECTED(fbc == NULL)) {
2954 			if (EXPECTED(!EG(exception))) {
2955 				zend_undefined_method(called_scope, mname);
2956 			}
2957 			zend_string_release_ex(lcname, 0);
2958 			zend_string_release_ex(mname, 0);
2959 			return NULL;
2960 		}
2961 
2962 		zend_string_release_ex(lcname, 0);
2963 		zend_string_release_ex(mname, 0);
2964 
2965 		if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
2966 			zend_non_static_method_call(fbc);
2967 			if (UNEXPECTED(EG(exception) != NULL)) {
2968 				return NULL;
2969 			}
2970 		}
2971 		if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
2972 			init_func_run_time_cache(&fbc->op_array);
2973 		}
2974 	} else {
2975 		if (ZSTR_VAL(function)[0] == '\\') {
2976 			lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
2977 			zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
2978 		} else {
2979 			lcname = zend_string_tolower(function);
2980 		}
2981 		if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
2982 			zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
2983 			zend_string_release_ex(lcname, 0);
2984 			return NULL;
2985 		}
2986 		zend_string_release_ex(lcname, 0);
2987 
2988 		fbc = Z_FUNC_P(func);
2989 		if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
2990 			fbc = init_func_run_time_cache_ex(func);
2991 		}
2992 		called_scope = NULL;
2993 	}
2994 
2995 	return zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC,
2996 		fbc, num_args, called_scope, NULL);
2997 }
2998 /* }}} */
2999 
zend_init_dynamic_call_object(zval * function,uint32_t num_args)3000 static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *function, uint32_t num_args) /* {{{ */
3001 {
3002 	zend_function *fbc;
3003 	zend_class_entry *called_scope;
3004 	zend_object *object;
3005 	uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
3006 
3007 	if (EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)) &&
3008 	    EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)(function, &called_scope, &fbc, &object) == SUCCESS)) {
3009 
3010 		if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
3011 			/* Delay closure destruction until its invocation */
3012 			GC_ADDREF(ZEND_CLOSURE_OBJECT(fbc));
3013 			call_info |= ZEND_CALL_CLOSURE;
3014 			if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
3015 				call_info |= ZEND_CALL_FAKE_CLOSURE;
3016 			}
3017 		} else if (object) {
3018 			call_info |= ZEND_CALL_RELEASE_THIS;
3019 			GC_ADDREF(object); /* For $this pointer */
3020 		}
3021 	} else {
3022 		zend_throw_error(NULL, "Function name must be a string");
3023 		return NULL;
3024 	}
3025 
3026 	if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
3027 		init_func_run_time_cache(&fbc->op_array);
3028 	}
3029 
3030 	return zend_vm_stack_push_call_frame(call_info,
3031 		fbc, num_args, called_scope, object);
3032 }
3033 /* }}} */
3034 
zend_init_dynamic_call_array(zend_array * function,uint32_t num_args)3035 static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_array *function, uint32_t num_args) /* {{{ */
3036 {
3037 	zend_function *fbc;
3038 	zend_class_entry *called_scope;
3039 	zend_object *object;
3040 	uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
3041 
3042 	if (zend_hash_num_elements(function) == 2) {
3043 		zval *obj;
3044 		zval *method;
3045 		obj = zend_hash_index_find(function, 0);
3046 		method = zend_hash_index_find(function, 1);
3047 
3048 		if (UNEXPECTED(!obj) || UNEXPECTED(!method)) {
3049 			zend_throw_error(NULL, "Array callback has to contain indices 0 and 1");
3050 			return NULL;
3051 		}
3052 
3053 		ZVAL_DEREF(obj);
3054 		if (UNEXPECTED(Z_TYPE_P(obj) != IS_STRING) && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
3055 			zend_throw_error(NULL, "First array member is not a valid class name or object");
3056 			return NULL;
3057 		}
3058 
3059 		ZVAL_DEREF(method);
3060 		if (UNEXPECTED(Z_TYPE_P(method) != IS_STRING)) {
3061 			zend_throw_error(NULL, "Second array member is not a valid method");
3062 			return NULL;
3063 		}
3064 
3065 		if (Z_TYPE_P(obj) == IS_STRING) {
3066 			object = NULL;
3067 			called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
3068 			if (UNEXPECTED(called_scope == NULL)) {
3069 				return NULL;
3070 			}
3071 
3072 			if (called_scope->get_static_method) {
3073 				fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
3074 			} else {
3075 				fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
3076 			}
3077 			if (UNEXPECTED(fbc == NULL)) {
3078 				if (EXPECTED(!EG(exception))) {
3079 					zend_undefined_method(called_scope, Z_STR_P(method));
3080 				}
3081 				return NULL;
3082 			}
3083 			if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
3084 				zend_non_static_method_call(fbc);
3085 				if (UNEXPECTED(EG(exception) != NULL)) {
3086 					return NULL;
3087 				}
3088 			}
3089 		} else {
3090 			called_scope = Z_OBJCE_P(obj);
3091 			object = Z_OBJ_P(obj);
3092 
3093 			fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
3094 			if (UNEXPECTED(fbc == NULL)) {
3095 				if (EXPECTED(!EG(exception))) {
3096 					zend_undefined_method(object->ce, Z_STR_P(method));
3097 				}
3098 				return NULL;
3099 			}
3100 
3101 			if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
3102 				object = NULL;
3103 			} else {
3104 				call_info |= ZEND_CALL_RELEASE_THIS;
3105 				GC_ADDREF(object); /* For $this pointer */
3106 			}
3107 		}
3108 	} else {
3109 		zend_throw_error(NULL, "Function name must be a string");
3110 		return NULL;
3111 	}
3112 
3113 	if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
3114 		init_func_run_time_cache(&fbc->op_array);
3115 	}
3116 
3117 	return zend_vm_stack_push_call_frame(call_info,
3118 		fbc, num_args, called_scope, object);
3119 }
3120 /* }}} */
3121 
3122 #define ZEND_FAKE_OP_ARRAY ((zend_op_array*)(zend_intptr_t)-1)
3123 
zend_include_or_eval(zval * inc_filename,int type)3124 static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval *inc_filename, int type) /* {{{ */
3125 {
3126 	zend_op_array *new_op_array = NULL;
3127 	zval tmp_inc_filename;
3128 
3129 	ZVAL_UNDEF(&tmp_inc_filename);
3130 	if (Z_TYPE_P(inc_filename) != IS_STRING) {
3131 		ZVAL_STR(&tmp_inc_filename, zval_get_string_func(inc_filename));
3132 		inc_filename = &tmp_inc_filename;
3133 	}
3134 
3135 	switch (type) {
3136 		case ZEND_INCLUDE_ONCE:
3137 		case ZEND_REQUIRE_ONCE: {
3138 				zend_file_handle file_handle;
3139 				zend_string *resolved_path;
3140 
3141 				resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename));
3142 				if (EXPECTED(resolved_path)) {
3143 					if (zend_hash_exists(&EG(included_files), resolved_path)) {
3144 						goto already_compiled;
3145 					}
3146 				} else if (UNEXPECTED(strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename))) {
3147 					zend_message_dispatcher(
3148 						(type == ZEND_INCLUDE_ONCE) ?
3149 							ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN,
3150 							Z_STRVAL_P(inc_filename));
3151 					break;
3152 				} else {
3153 					resolved_path = zend_string_copy(Z_STR_P(inc_filename));
3154 				}
3155 
3156 				if (SUCCESS == zend_stream_open(ZSTR_VAL(resolved_path), &file_handle)) {
3157 
3158 					if (!file_handle.opened_path) {
3159 						file_handle.opened_path = zend_string_copy(resolved_path);
3160 					}
3161 
3162 					if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path)) {
3163 						zend_op_array *op_array = zend_compile_file(&file_handle, (type==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE));
3164 						zend_destroy_file_handle(&file_handle);
3165 						zend_string_release_ex(resolved_path, 0);
3166 						if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
3167 							zval_ptr_dtor_str(&tmp_inc_filename);
3168 						}
3169 						return op_array;
3170 					} else {
3171 						zend_file_handle_dtor(&file_handle);
3172 already_compiled:
3173 						new_op_array = ZEND_FAKE_OP_ARRAY;
3174 					}
3175 				} else {
3176 					zend_message_dispatcher(
3177 						(type == ZEND_INCLUDE_ONCE) ?
3178 							ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN,
3179 							Z_STRVAL_P(inc_filename));
3180 				}
3181 				zend_string_release_ex(resolved_path, 0);
3182 			}
3183 			break;
3184 		case ZEND_INCLUDE:
3185 		case ZEND_REQUIRE:
3186 			if (UNEXPECTED(strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename))) {
3187 				zend_message_dispatcher(
3188 					(type == ZEND_INCLUDE) ?
3189 						ZMSG_FAILED_INCLUDE_FOPEN : ZMSG_FAILED_REQUIRE_FOPEN,
3190 						Z_STRVAL_P(inc_filename));
3191 				break;
3192 			}
3193 			new_op_array = compile_filename(type, inc_filename);
3194 			break;
3195 		case ZEND_EVAL: {
3196 				char *eval_desc = zend_make_compiled_string_description("eval()'d code");
3197 				new_op_array = zend_compile_string(inc_filename, eval_desc);
3198 				efree(eval_desc);
3199 			}
3200 			break;
3201 		EMPTY_SWITCH_DEFAULT_CASE()
3202 	}
3203 
3204 	if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
3205 		zval_ptr_dtor_str(&tmp_inc_filename);
3206 	}
3207 	return new_op_array;
3208 }
3209 /* }}} */
3210 
zend_do_fcall_overloaded(zend_execute_data * call,zval * ret)3211 ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret) /* {{{ */
3212 {
3213 	zend_function *fbc = call->func;
3214 	zend_object *object;
3215 
3216 	/* Not sure what should be done here if it's a static method */
3217 	if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) {
3218 		zend_vm_stack_free_args(call);
3219 		if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
3220 			zend_string_release_ex(fbc->common.function_name, 0);
3221 		}
3222 		efree(fbc);
3223 		zend_vm_stack_free_call_frame(call);
3224 
3225 		zend_throw_error(NULL, "Cannot call overloaded function for non-object");
3226 		return 0;
3227 	}
3228 
3229 	object = Z_OBJ(call->This);
3230 
3231 	ZVAL_NULL(ret);
3232 
3233 	EG(current_execute_data) = call;
3234 	object->handlers->call_method(fbc->common.function_name, object, call, ret);
3235 	EG(current_execute_data) = call->prev_execute_data;
3236 
3237 	zend_vm_stack_free_args(call);
3238 
3239 	if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
3240 		zend_string_release_ex(fbc->common.function_name, 0);
3241 	}
3242 	efree(fbc);
3243 
3244 	return 1;
3245 }
3246 /* }}} */
3247 
zend_fe_reset_iterator(zval * array_ptr,int by_ref OPLINE_DC EXECUTE_DATA_DC)3248 static zend_never_inline zend_bool ZEND_FASTCALL zend_fe_reset_iterator(zval *array_ptr, int by_ref OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
3249 {
3250 	zend_class_entry *ce = Z_OBJCE_P(array_ptr);
3251 	zend_object_iterator *iter = ce->get_iterator(ce, array_ptr, by_ref);
3252 	zend_bool is_empty;
3253 
3254 	if (UNEXPECTED(!iter) || UNEXPECTED(EG(exception))) {
3255 		if (iter) {
3256 			OBJ_RELEASE(&iter->std);
3257 		}
3258 		if (!EG(exception)) {
3259 			zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ZSTR_VAL(ce->name));
3260 		}
3261 		ZVAL_UNDEF(EX_VAR(opline->result.var));
3262 		return 1;
3263 	}
3264 
3265 	iter->index = 0;
3266 	if (iter->funcs->rewind) {
3267 		iter->funcs->rewind(iter);
3268 		if (UNEXPECTED(EG(exception) != NULL)) {
3269 			OBJ_RELEASE(&iter->std);
3270 			ZVAL_UNDEF(EX_VAR(opline->result.var));
3271 			return 1;
3272 		}
3273 	}
3274 
3275 	is_empty = iter->funcs->valid(iter) != SUCCESS;
3276 
3277 	if (UNEXPECTED(EG(exception) != NULL)) {
3278 		OBJ_RELEASE(&iter->std);
3279 		ZVAL_UNDEF(EX_VAR(opline->result.var));
3280 		return 1;
3281 	}
3282 	iter->index = -1; /* will be set to 0 before using next handler */
3283 
3284 	ZVAL_OBJ(EX_VAR(opline->result.var), &iter->std);
3285 	Z_FE_ITER_P(EX_VAR(opline->result.var)) = (uint32_t)-1;
3286 
3287 	return is_empty;
3288 }
3289 /* }}} */
3290 
_zend_quick_get_constant(const zval * key,uint32_t flags,int check_defined_only OPLINE_DC EXECUTE_DATA_DC)3291 static zend_always_inline int _zend_quick_get_constant(
3292 		const zval *key, uint32_t flags, int check_defined_only OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
3293 {
3294 	zval *zv;
3295 	const zval *orig_key = key;
3296 	zend_constant *c = NULL;
3297 
3298 	zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1);
3299 	if (zv) {
3300 		c = (zend_constant*)Z_PTR_P(zv);
3301 	} else {
3302 		key++;
3303 		zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1);
3304 		if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) {
3305 			c = (zend_constant*)Z_PTR_P(zv);
3306 		} else {
3307 			if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
3308 				key++;
3309 				zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1);
3310 				if (zv) {
3311 					c = (zend_constant*)Z_PTR_P(zv);
3312 				} else {
3313 				    key++;
3314 					zv = zend_hash_find_ex(EG(zend_constants), Z_STR_P(key), 1);
3315 					if (zv && (ZEND_CONSTANT_FLAGS((zend_constant*)Z_PTR_P(zv)) & CONST_CS) == 0) {
3316 						c = (zend_constant*)Z_PTR_P(zv);
3317 					}
3318 				}
3319 			}
3320 		}
3321 	}
3322 
3323 	if (!c) {
3324 		if (!check_defined_only) {
3325 			if ((opline->op1.num & IS_CONSTANT_UNQUALIFIED) != 0) {
3326 				char *actual = (char *)zend_memrchr(Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)), '\\', Z_STRLEN_P(RT_CONSTANT(opline, opline->op2)));
3327 				if (!actual) {
3328 					ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(RT_CONSTANT(opline, opline->op2)));
3329 				} else {
3330 					actual++;
3331 					ZVAL_STRINGL(EX_VAR(opline->result.var),
3332 							actual, Z_STRLEN_P(RT_CONSTANT(opline, opline->op2)) - (actual - Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))));
3333 				}
3334 				/* non-qualified constant - allow text substitution */
3335 				zend_error(E_WARNING, "Use of undefined constant %s - assumed '%s' (this will throw an Error in a future version of PHP)",
3336 						Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
3337 			} else {
3338 				zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(RT_CONSTANT(opline, opline->op2)));
3339 				ZVAL_UNDEF(EX_VAR(opline->result.var));
3340 			}
3341 		}
3342 		return FAILURE;
3343 	}
3344 
3345 	if (!check_defined_only) {
3346 		ZVAL_COPY_OR_DUP(EX_VAR(opline->result.var), &c->value);
3347 		if (!(ZEND_CONSTANT_FLAGS(c) & (CONST_CS|CONST_CT_SUBST))) {
3348 			const char *ns_sep;
3349 			size_t shortname_offset;
3350 			size_t shortname_len;
3351 			zend_bool is_deprecated;
3352 
3353 			if (flags & IS_CONSTANT_UNQUALIFIED) {
3354 				const zval *access_key;
3355 
3356 				if (!(flags & IS_CONSTANT_IN_NAMESPACE)) {
3357 					access_key = orig_key - 1;
3358 				} else {
3359 					if (key < orig_key + 2) {
3360 						goto check_short_name;
3361 					} else {
3362 						access_key = orig_key + 2;
3363 					}
3364 				}
3365 				is_deprecated = !zend_string_equals(c->name, Z_STR_P(access_key));
3366 			} else {
3367 check_short_name:
3368 				/* Namespaces are always case-insensitive. Only compare shortname. */
3369 				ns_sep = zend_memrchr(ZSTR_VAL(c->name), '\\', ZSTR_LEN(c->name));
3370 				if (ns_sep) {
3371 					shortname_offset = ns_sep - ZSTR_VAL(c->name) + 1;
3372 					shortname_len = ZSTR_LEN(c->name) - shortname_offset;
3373 				} else {
3374 					shortname_offset = 0;
3375 					shortname_len = ZSTR_LEN(c->name);
3376 				}
3377 
3378 				is_deprecated = memcmp(ZSTR_VAL(c->name) + shortname_offset, Z_STRVAL_P(orig_key - 1) + shortname_offset, shortname_len) != 0;
3379 			}
3380 
3381 			if (is_deprecated) {
3382 				zend_error(E_DEPRECATED,
3383 					"Case-insensitive constants are deprecated. "
3384 					"The correct casing for this constant is \"%s\"",
3385 					ZSTR_VAL(c->name));
3386 				return SUCCESS;
3387 			}
3388 		}
3389 	}
3390 
3391 	CACHE_PTR(opline->extended_value, c);
3392 	return SUCCESS;
3393 }
3394 /* }}} */
3395 
zend_quick_get_constant(const zval * key,uint32_t flags OPLINE_DC EXECUTE_DATA_DC)3396 static zend_never_inline void ZEND_FASTCALL zend_quick_get_constant(
3397 		const zval *key, uint32_t flags OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
3398 {
3399 	_zend_quick_get_constant(key, flags, 0 OPLINE_CC EXECUTE_DATA_CC);
3400 } /* }}} */
3401 
zend_quick_check_constant(const zval * key OPLINE_DC EXECUTE_DATA_DC)3402 static zend_never_inline int ZEND_FASTCALL zend_quick_check_constant(
3403 		const zval *key OPLINE_DC EXECUTE_DATA_DC) /* {{{ */
3404 {
3405 	return _zend_quick_get_constant(key, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
3406 } /* }}} */
3407 
3408 #ifdef ZEND_VM_TRACE_HANDLERS
3409 # include "zend_vm_trace_handlers.h"
3410 #elif defined(ZEND_VM_TRACE_MAP)
3411 # include "zend_vm_trace_map.h"
3412 #endif
3413 
3414 #define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
3415 	CHECK_SYMBOL_TABLES() \
3416 	if (check_exception) { \
3417 		OPLINE = EX(opline) + (skip); \
3418 	} else { \
3419 		OPLINE = opline + (skip); \
3420 	} \
3421 	ZEND_VM_CONTINUE()
3422 
3423 #define ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() \
3424 	ZEND_VM_NEXT_OPCODE_EX(1, 1)
3425 
3426 #define ZEND_VM_NEXT_OPCODE() \
3427 	ZEND_VM_NEXT_OPCODE_EX(0, 1)
3428 
3429 #define ZEND_VM_SET_NEXT_OPCODE(new_op) \
3430 	CHECK_SYMBOL_TABLES() \
3431 	OPLINE = new_op
3432 
3433 #define ZEND_VM_SET_OPCODE(new_op) \
3434 	CHECK_SYMBOL_TABLES() \
3435 	OPLINE = new_op; \
3436 	ZEND_VM_INTERRUPT_CHECK()
3437 
3438 #define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
3439 	ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset))
3440 
3441 #define ZEND_VM_JMP_EX(new_op, check_exception) do { \
3442 		if (check_exception && UNEXPECTED(EG(exception))) { \
3443 			HANDLE_EXCEPTION(); \
3444 		} \
3445 		ZEND_VM_SET_OPCODE(new_op); \
3446 		ZEND_VM_CONTINUE(); \
3447 	} while (0)
3448 
3449 #define ZEND_VM_JMP(new_op) \
3450 	ZEND_VM_JMP_EX(new_op, 1)
3451 
3452 #define ZEND_VM_INC_OPCODE() \
3453 	OPLINE++
3454 
3455 
3456 #ifndef VM_SMART_OPCODES
3457 # define VM_SMART_OPCODES 1
3458 #endif
3459 
3460 #if VM_SMART_OPCODES
3461 # define ZEND_VM_REPEATABLE_OPCODE \
3462 	do {
3463 # define ZEND_VM_REPEAT_OPCODE(_opcode) \
3464 	} while (UNEXPECTED((++opline)->opcode == _opcode)); \
3465 	OPLINE = opline; \
3466 	ZEND_VM_CONTINUE()
3467 # define ZEND_VM_SMART_BRANCH(_result, _check) do { \
3468 		int __result; \
3469 		if (EXPECTED((opline+1)->opcode == ZEND_JMPZ)) { \
3470 			__result = (_result); \
3471 		} else if (EXPECTED((opline+1)->opcode == ZEND_JMPNZ)) { \
3472 			__result = !(_result); \
3473 		} else { \
3474 			break; \
3475 		} \
3476 		if ((_check) && UNEXPECTED(EG(exception))) { \
3477 			ZVAL_UNDEF(EX_VAR(opline->result.var)); \
3478 			HANDLE_EXCEPTION(); \
3479 		} \
3480 		if (__result) { \
3481 			ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
3482 		} else { \
3483 			ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
3484 		} \
3485 		ZEND_VM_CONTINUE(); \
3486 	} while (0)
3487 # define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) do { \
3488 		if ((_check) && UNEXPECTED(EG(exception))) { \
3489 			ZVAL_UNDEF(EX_VAR(opline->result.var)); \
3490 			HANDLE_EXCEPTION(); \
3491 		} \
3492 		if (_result) { \
3493 			ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
3494 		} else { \
3495 			ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
3496 		} \
3497 		ZEND_VM_CONTINUE(); \
3498 	} while (0)
3499 # define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) do { \
3500 		if ((_check) && UNEXPECTED(EG(exception))) { \
3501 			ZVAL_UNDEF(EX_VAR(opline->result.var)); \
3502 			HANDLE_EXCEPTION(); \
3503 		} \
3504 		if (!(_result)) { \
3505 			ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
3506 		} else { \
3507 			ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
3508 		} \
3509 		ZEND_VM_CONTINUE(); \
3510 	} while (0)
3511 #else
3512 # define ZEND_VM_REPEATABLE_OPCODE
3513 # define ZEND_VM_REPEAT_OPCODE(_opcode)
3514 # define ZEND_VM_SMART_BRANCH(_result, _check)
3515 # define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check)
3516 # define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check)
3517 #endif
3518 
3519 #ifdef __GNUC__
3520 # define ZEND_VM_GUARD(name) __asm__("#" #name)
3521 #else
3522 # define ZEND_VM_GUARD(name)
3523 #endif
3524 
3525 #define GET_OP1_UNDEF_CV(ptr, type) \
3526 	_get_zval_cv_lookup_ ## type(ptr, opline->op1.var EXECUTE_DATA_CC)
3527 #define GET_OP2_UNDEF_CV(ptr, type) \
3528 	_get_zval_cv_lookup_ ## type(ptr, opline->op2.var EXECUTE_DATA_CC)
3529 
3530 #define UNDEF_RESULT() do { \
3531 		if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { \
3532 			ZVAL_UNDEF(EX_VAR(opline->result.var)); \
3533 		} \
3534 	} while (0)
3535 
3536 #if ZEND_GCC_VERSION >= 4000 && !defined(__clang__)
3537 # pragma GCC push_options
3538 # pragma GCC optimize("no-gcse")
3539 # pragma GCC optimize("no-ivopts")
3540 #endif
3541 
3542 #include "zend_vm_execute.h"
3543 
3544 #if ZEND_GCC_VERSION >= 4000 && !defined(__clang__)
3545 # pragma GCC pop_options
3546 #endif
3547 
zend_set_user_opcode_handler(zend_uchar opcode,user_opcode_handler_t handler)3548 ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
3549 {
3550 	if (opcode != ZEND_USER_OPCODE) {
3551 		if (handler == NULL) {
3552 			/* restore the original handler */
3553 			zend_user_opcodes[opcode] = opcode;
3554 		} else {
3555 			zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
3556 		}
3557 		zend_user_opcode_handlers[opcode] = handler;
3558 		return SUCCESS;
3559 	}
3560 	return FAILURE;
3561 }
3562 
zend_get_user_opcode_handler(zend_uchar opcode)3563 ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
3564 {
3565 	return zend_user_opcode_handlers[opcode];
3566 }
3567 
zend_get_zval_ptr(const zend_op * opline,int op_type,const znode_op * node,const zend_execute_data * execute_data,zend_free_op * should_free,int type)3568 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_free_op *should_free, int type)
3569 {
3570 	zval *ret;
3571 
3572 	switch (op_type) {
3573 		case IS_CONST:
3574 			ret = RT_CONSTANT(opline, *node);
3575 			*should_free = NULL;
3576 			break;
3577 		case IS_TMP_VAR:
3578 		case IS_VAR:
3579 			ret = EX_VAR(node->var);
3580 			*should_free = ret;
3581 			break;
3582 		case IS_CV:
3583 			ret = EX_VAR(node->var);
3584 			*should_free = NULL;
3585 			break;
3586 		default:
3587 			ret = NULL;
3588 			*should_free = ret;
3589 			break;
3590 	}
3591 	return ret;
3592 }
3593 
zend_check_internal_arg_type(zend_function * zf,uint32_t arg_num,zval * arg)3594 ZEND_API void ZEND_FASTCALL zend_check_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
3595 {
3596 	void *dummy_cache_slot = NULL;
3597 
3598 	zend_verify_arg_type(zf, arg_num, arg, NULL, &dummy_cache_slot);
3599 }
3600 
zend_check_arg_type(zend_function * zf,uint32_t arg_num,zval * arg,zval * default_value,void ** cache_slot)3601 ZEND_API int ZEND_FASTCALL zend_check_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
3602 {
3603 	return zend_verify_arg_type(zf, arg_num, arg, default_value, cache_slot);
3604 }
3605 
3606 /*
3607  * Local variables:
3608  * tab-width: 4
3609  * c-basic-offset: 4
3610  * indent-tabs-mode: t
3611  * End:
3612  * vim600: sw=4 ts=4 fdm=marker
3613  * vim<600: sw=4 ts=4
3614  */
3615