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