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