xref: /PHP-5.4/Zend/zend_execute.c (revision c0d060f5)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2014 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    +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #define ZEND_INTENSIVE_DEBUGGING 0
23 
24 #include <stdio.h>
25 #include <signal.h>
26 
27 #include "zend.h"
28 #include "zend_compile.h"
29 #include "zend_execute.h"
30 #include "zend_API.h"
31 #include "zend_ptr_stack.h"
32 #include "zend_constants.h"
33 #include "zend_extensions.h"
34 #include "zend_ini.h"
35 #include "zend_exceptions.h"
36 #include "zend_interfaces.h"
37 #include "zend_closures.h"
38 #include "zend_vm.h"
39 #include "zend_dtrace.h"
40 
41 /* Virtual current working directory support */
42 #include "tsrm_virtual_cwd.h"
43 
44 #define _CONST_CODE  0
45 #define _TMP_CODE    1
46 #define _VAR_CODE    2
47 #define _UNUSED_CODE 3
48 #define _CV_CODE     4
49 
50 typedef int (*incdec_t)(zval *);
51 
52 #define get_zval_ptr(op_type, node, Ts, should_free, type) _get_zval_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
53 #define get_zval_ptr_ptr(op_type, node, Ts, should_free, type) _get_zval_ptr_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
54 #define get_obj_zval_ptr(op_type, node, Ts, should_free, type) _get_obj_zval_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
55 #define get_obj_zval_ptr_ptr(op_type, node, Ts, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, Ts, should_free, type TSRMLS_CC)
56 
57 /* Prototypes */
58 static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
59 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
60 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
61 
62 #define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
63 
64 #define T(offset) (*(temp_variable *)((char *) Ts + offset))
65 #define CV(var)   CVs[var]
66 
67 #define TEMP_VAR_STACK_LIMIT 2000
68 
zend_pzval_unlock_func(zval * z,zend_free_op * should_free,int unref TSRMLS_DC)69 static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref TSRMLS_DC)
70 {
71 	if (!Z_DELREF_P(z)) {
72 		Z_SET_REFCOUNT_P(z, 1);
73 		Z_UNSET_ISREF_P(z);
74 		should_free->var = z;
75 /*		should_free->is_var = 1; */
76 	} else {
77 		should_free->var = 0;
78 		if (unref && Z_ISREF_P(z) && Z_REFCOUNT_P(z) == 1) {
79 			Z_UNSET_ISREF_P(z);
80 		}
81 		GC_ZVAL_CHECK_POSSIBLE_ROOT(z);
82 	}
83 }
84 
zend_pzval_unlock_free_func(zval * z TSRMLS_DC)85 static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
86 {
87 	if (!Z_DELREF_P(z)) {
88 		if (z != &EG(uninitialized_zval)) {
89 			GC_REMOVE_ZVAL_FROM_BUFFER(z);
90 			zval_dtor(z);
91 			efree(z);
92 		}
93 	}
94 }
95 
96 #undef zval_ptr_dtor
97 #define zval_ptr_dtor(pzv) i_zval_ptr_dtor(*(pzv)  ZEND_FILE_LINE_CC)
98 
99 #define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC)
100 #define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC)
101 #define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z TSRMLS_CC)
102 #define PZVAL_LOCK(z) Z_ADDREF_P((z))
103 #define SELECTIVE_PZVAL_LOCK(pzv, opline)	if (RETURN_VALUE_USED(opline)) { PZVAL_LOCK(pzv); }
104 
105 #define EXTRACT_ZVAL_PTR(t) do {						\
106 		temp_variable *__t = (t);					\
107 		if (__t->var.ptr_ptr) {						\
108 			__t->var.ptr = *__t->var.ptr_ptr;		\
109 			__t->var.ptr_ptr = &__t->var.ptr;		\
110 			if (!PZVAL_IS_REF(__t->var.ptr) && 		\
111 			    Z_REFCOUNT_P(__t->var.ptr) > 2) {	\
112 				SEPARATE_ZVAL(__t->var.ptr_ptr);	\
113 			}										\
114 		}											\
115 	} while (0)
116 
117 #define AI_SET_PTR(t, val) do {				\
118 		temp_variable *__t = (t);			\
119 		__t->var.ptr = (val);				\
120 		__t->var.ptr_ptr = &__t->var.ptr;	\
121 	} while (0)
122 
123 #define FREE_OP(should_free) \
124 	if (should_free.var) { \
125 		if ((zend_uintptr_t)should_free.var & 1L) { \
126 			zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
127 		} else { \
128 			zval_ptr_dtor(&should_free.var); \
129 		} \
130 	}
131 
132 #define FREE_OP_IF_VAR(should_free) \
133 	if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
134 		zval_ptr_dtor(&should_free.var); \
135 	}
136 
137 #define FREE_OP_VAR_PTR(should_free) \
138 	if (should_free.var) { \
139 		zval_ptr_dtor(&should_free.var); \
140 	}
141 
142 #define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
143 
144 #define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
145 
146 #define MAKE_REAL_ZVAL_PTR(val) \
147 	do { \
148 		zval *_tmp; \
149 		ALLOC_ZVAL(_tmp); \
150 		INIT_PZVAL_COPY(_tmp, (val)); \
151 		(val) = _tmp; \
152 	} while (0)
153 
154 /* End of zend_execute_locks.h */
155 
156 #define CV_OF(i)     (EG(current_execute_data)->CVs[i])
157 #define CV_DEF_OF(i) (EG(active_op_array)->vars[i])
158 
159 #define CTOR_CALL_BIT    0x1
160 #define CTOR_USED_BIT    0x2
161 
162 #define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
163 #define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
164 
165 #define ENCODE_CTOR(ce, used) \
166 	((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
167 #define DECODE_CTOR(ce) \
168 	((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
169 
zend_get_compiled_variable_value(const zend_execute_data * execute_data_ptr,zend_uint var)170 ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var)
171 {
172 	return execute_data_ptr->CVs[var];
173 }
174 
_get_zval_ptr_tmp(zend_uint var,const temp_variable * Ts,zend_free_op * should_free TSRMLS_DC)175 static zend_always_inline zval *_get_zval_ptr_tmp(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
176 {
177 	return should_free->var = &T(var).tmp_var;
178 }
179 
_get_zval_ptr_var(zend_uint var,const temp_variable * Ts,zend_free_op * should_free TSRMLS_DC)180 static zend_always_inline zval *_get_zval_ptr_var(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
181 {
182 	zval *ptr = T(var).var.ptr;
183 
184 	PZVAL_UNLOCK(ptr, should_free);
185 	return ptr;
186 }
187 
_get_zval_cv_lookup(zval *** ptr,zend_uint var,int type TSRMLS_DC)188 static zend_never_inline zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC)
189 {
190 	zend_compiled_variable *cv = &CV_DEF_OF(var);
191 
192 	if (!EG(active_symbol_table) ||
193 	    zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
194 		switch (type) {
195 			case BP_VAR_R:
196 			case BP_VAR_UNSET:
197 				zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
198 				/* break missing intentionally */
199 			case BP_VAR_IS:
200 				return &EG(uninitialized_zval_ptr);
201 				break;
202 			case BP_VAR_RW:
203 				zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
204 				/* break missing intentionally */
205 			case BP_VAR_W:
206 				Z_ADDREF(EG(uninitialized_zval));
207 				if (!EG(active_symbol_table)) {
208 					*ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
209 					**ptr = &EG(uninitialized_zval);
210 				} else {
211 					zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
212 				}
213 				break;
214 		}
215 	}
216 	return *ptr;
217 }
218 
_get_zval_cv_lookup_BP_VAR_R(zval *** ptr,zend_uint var TSRMLS_DC)219 static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_R(zval ***ptr, zend_uint var TSRMLS_DC)
220 {
221 	zend_compiled_variable *cv = &CV_DEF_OF(var);
222 
223 	if (!EG(active_symbol_table) ||
224 	    zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
225 		zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
226 		return &EG(uninitialized_zval_ptr);
227 	}
228 	return *ptr;
229 }
230 
_get_zval_cv_lookup_BP_VAR_UNSET(zval *** ptr,zend_uint var TSRMLS_DC)231 static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_UNSET(zval ***ptr, zend_uint var TSRMLS_DC)
232 {
233 	zend_compiled_variable *cv = &CV_DEF_OF(var);
234 
235 	if (!EG(active_symbol_table) ||
236 	    zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
237 		zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
238 		return &EG(uninitialized_zval_ptr);
239 	}
240 	return *ptr;
241 }
242 
_get_zval_cv_lookup_BP_VAR_IS(zval *** ptr,zend_uint var TSRMLS_DC)243 static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_IS(zval ***ptr, zend_uint var TSRMLS_DC)
244 {
245 	zend_compiled_variable *cv = &CV_DEF_OF(var);
246 
247 	if (!EG(active_symbol_table) ||
248 	    zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
249 		return &EG(uninitialized_zval_ptr);
250 	}
251 	return *ptr;
252 }
253 
_get_zval_cv_lookup_BP_VAR_RW(zval *** ptr,zend_uint var TSRMLS_DC)254 static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_RW(zval ***ptr, zend_uint var TSRMLS_DC)
255 {
256 	zend_compiled_variable *cv = &CV_DEF_OF(var);
257 
258 	if (!EG(active_symbol_table)) {
259 		Z_ADDREF(EG(uninitialized_zval));
260 		*ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
261 		**ptr = &EG(uninitialized_zval);
262 		zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
263 	} else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
264 		Z_ADDREF(EG(uninitialized_zval));
265 		zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
266 		zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
267 	}
268 	return *ptr;
269 }
270 
_get_zval_cv_lookup_BP_VAR_W(zval *** ptr,zend_uint var TSRMLS_DC)271 static zend_never_inline zval **_get_zval_cv_lookup_BP_VAR_W(zval ***ptr, zend_uint var TSRMLS_DC)
272 {
273 	zend_compiled_variable *cv = &CV_DEF_OF(var);
274 
275 	if (!EG(active_symbol_table)) {
276 		Z_ADDREF(EG(uninitialized_zval));
277 		*ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
278 		**ptr = &EG(uninitialized_zval);
279 	} else if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
280 		Z_ADDREF(EG(uninitialized_zval));
281 		zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &EG(uninitialized_zval_ptr), sizeof(zval *), (void **)ptr);
282 	}
283 	return *ptr;
284 }
285 
_get_zval_ptr_cv(zend_uint var,int type TSRMLS_DC)286 static zend_always_inline zval *_get_zval_ptr_cv(zend_uint var, int type TSRMLS_DC)
287 {
288 	zval ***ptr = &CV_OF(var);
289 
290 	if (UNEXPECTED(*ptr == NULL)) {
291 		return *_get_zval_cv_lookup(ptr, var, type TSRMLS_CC);
292 	}
293 	return **ptr;
294 }
295 
_get_zval_ptr_cv_BP_VAR_R(zval *** CVs,zend_uint var TSRMLS_DC)296 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint var TSRMLS_DC)
297 {
298 	zval ***ptr = &CV(var);
299 
300 	if (UNEXPECTED(*ptr == NULL)) {
301 		return *_get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC);
302 	}
303 	return **ptr;
304 }
305 
_get_zval_ptr_cv_BP_VAR_UNSET(zval *** CVs,zend_uint var TSRMLS_DC)306 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(zval ***CVs, zend_uint var TSRMLS_DC)
307 {
308 	zval ***ptr = &CV(var);
309 
310 	if (UNEXPECTED(*ptr == NULL)) {
311 		return *_get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC);
312 	}
313 	return **ptr;
314 }
315 
_get_zval_ptr_cv_BP_VAR_IS(zval *** CVs,zend_uint var TSRMLS_DC)316 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(zval ***CVs, zend_uint var TSRMLS_DC)
317 {
318 	zval ***ptr = &CV(var);
319 
320 	if (UNEXPECTED(*ptr == NULL)) {
321 		return *_get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC);
322 	}
323 	return **ptr;
324 }
325 
_get_zval_ptr_cv_BP_VAR_RW(zval *** CVs,zend_uint var TSRMLS_DC)326 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(zval ***CVs, zend_uint var TSRMLS_DC)
327 {
328 	zval ***ptr = &CV(var);
329 
330 	if (UNEXPECTED(*ptr == NULL)) {
331 		return *_get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC);
332 	}
333 	return **ptr;
334 }
335 
_get_zval_ptr_cv_BP_VAR_W(zval *** CVs,zend_uint var TSRMLS_DC)336 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(zval ***CVs, zend_uint var TSRMLS_DC)
337 {
338 	zval ***ptr = &CV(var);
339 
340 	if (UNEXPECTED(*ptr == NULL)) {
341 		return *_get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC);
342 	}
343 	return **ptr;
344 }
345 
_get_zval_ptr(int op_type,const znode_op * node,const temp_variable * Ts,zend_free_op * should_free,int type TSRMLS_DC)346 static inline zval *_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
347 {
348 /*	should_free->is_var = 0; */
349 	switch (op_type) {
350 		case IS_CONST:
351 			should_free->var = 0;
352 			return node->zv;
353 			break;
354 		case IS_TMP_VAR:
355 			should_free->var = TMP_FREE(&T(node->var).tmp_var);
356 			return &T(node->var).tmp_var;
357 			break;
358 		case IS_VAR:
359 			return _get_zval_ptr_var(node->var, Ts, should_free TSRMLS_CC);
360 			break;
361 		case IS_UNUSED:
362 			should_free->var = 0;
363 			return NULL;
364 			break;
365 		case IS_CV:
366 			should_free->var = 0;
367 			return _get_zval_ptr_cv(node->var, type TSRMLS_CC);
368 			break;
369 		EMPTY_SWITCH_DEFAULT_CASE()
370 	}
371 	return NULL;
372 }
373 
_get_zval_ptr_ptr_var(zend_uint var,const temp_variable * Ts,zend_free_op * should_free TSRMLS_DC)374 static zend_always_inline zval **_get_zval_ptr_ptr_var(zend_uint var, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
375 {
376 	zval** ptr_ptr = T(var).var.ptr_ptr;
377 
378 	if (EXPECTED(ptr_ptr != NULL)) {
379 		PZVAL_UNLOCK(*ptr_ptr, should_free);
380 	} else {
381 		/* string offset */
382 		PZVAL_UNLOCK(T(var).str_offset.str, should_free);
383 	}
384 	return ptr_ptr;
385 }
386 
_get_zval_ptr_ptr_cv(zend_uint var,int type TSRMLS_DC)387 static zend_always_inline zval **_get_zval_ptr_ptr_cv(zend_uint var, int type TSRMLS_DC)
388 {
389 	zval ***ptr = &CV_OF(var);
390 
391 	if (UNEXPECTED(*ptr == NULL)) {
392 		return _get_zval_cv_lookup(ptr, var, type TSRMLS_CC);
393 	}
394 	return *ptr;
395 }
396 
_get_zval_ptr_ptr_cv_BP_VAR_R(zval *** CVs,zend_uint var TSRMLS_DC)397 static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_R(zval ***CVs, zend_uint var TSRMLS_DC)
398 {
399 	zval ***ptr = &CV(var);
400 
401 	if (UNEXPECTED(*ptr == NULL)) {
402 		return _get_zval_cv_lookup_BP_VAR_R(ptr, var TSRMLS_CC);
403 	}
404 	return *ptr;
405 }
406 
_get_zval_ptr_ptr_cv_BP_VAR_UNSET(zval *** CVs,zend_uint var TSRMLS_DC)407 static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_UNSET(zval ***CVs, zend_uint var TSRMLS_DC)
408 {
409 	zval ***ptr = &CV(var);
410 
411 	if (UNEXPECTED(*ptr == NULL)) {
412 		return _get_zval_cv_lookup_BP_VAR_UNSET(ptr, var TSRMLS_CC);
413 	}
414 	return *ptr;
415 }
416 
_get_zval_ptr_ptr_cv_BP_VAR_IS(zval *** CVs,zend_uint var TSRMLS_DC)417 static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_IS(zval ***CVs, zend_uint var TSRMLS_DC)
418 {
419 	zval ***ptr = &CV(var);
420 
421 	if (UNEXPECTED(*ptr == NULL)) {
422 		return _get_zval_cv_lookup_BP_VAR_IS(ptr, var TSRMLS_CC);
423 	}
424 	return *ptr;
425 }
426 
_get_zval_ptr_ptr_cv_BP_VAR_RW(zval *** CVs,zend_uint var TSRMLS_DC)427 static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_RW(zval ***CVs, zend_uint var TSRMLS_DC)
428 {
429 	zval ***ptr = &CV(var);
430 
431 	if (UNEXPECTED(*ptr == NULL)) {
432 		return _get_zval_cv_lookup_BP_VAR_RW(ptr, var TSRMLS_CC);
433 	}
434 	return *ptr;
435 }
436 
_get_zval_ptr_ptr_cv_BP_VAR_W(zval *** CVs,zend_uint var TSRMLS_DC)437 static zend_always_inline zval **_get_zval_ptr_ptr_cv_BP_VAR_W(zval ***CVs, zend_uint var TSRMLS_DC)
438 {
439 	zval ***ptr = &CV(var);
440 
441 	if (UNEXPECTED(*ptr == NULL)) {
442 		return _get_zval_cv_lookup_BP_VAR_W(ptr, var TSRMLS_CC);
443 	}
444 	return *ptr;
445 }
446 
_get_zval_ptr_ptr(int op_type,const znode_op * node,const temp_variable * Ts,zend_free_op * should_free,int type TSRMLS_DC)447 static inline zval **_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
448 {
449 	if (op_type == IS_CV) {
450 		should_free->var = 0;
451 		return _get_zval_ptr_ptr_cv(node->var, type TSRMLS_CC);
452 	} else if (op_type == IS_VAR) {
453 		return _get_zval_ptr_ptr_var(node->var, Ts, should_free TSRMLS_CC);
454 	} else {
455 		should_free->var = 0;
456 		return NULL;
457 	}
458 }
459 
_get_obj_zval_ptr_unused(TSRMLS_D)460 static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
461 {
462 	if (EXPECTED(EG(This) != NULL)) {
463 		return EG(This);
464 	} else {
465 		zend_error_noreturn(E_ERROR, "Using $this when not in object context");
466 		return NULL;
467 	}
468 }
469 
_get_obj_zval_ptr_ptr(int op_type,const znode_op * op,const temp_variable * Ts,zend_free_op * should_free,int type TSRMLS_DC)470 static inline zval **_get_obj_zval_ptr_ptr(int op_type, const znode_op *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
471 {
472 	if (op_type == IS_UNUSED) {
473 		if (EXPECTED(EG(This) != NULL)) {
474 			/* this should actually never be modified, _ptr_ptr is modified only when
475 			   the object is empty */
476 			should_free->var = 0;
477 			return &EG(This);
478 		} else {
479 			zend_error_noreturn(E_ERROR, "Using $this when not in object context");
480 		}
481 	}
482 	return get_zval_ptr_ptr(op_type, op, Ts, should_free, type);
483 }
484 
_get_obj_zval_ptr_ptr_unused(TSRMLS_D)485 static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D)
486 {
487 	if (EXPECTED(EG(This) != NULL)) {
488 		return &EG(This);
489 	} else {
490 		zend_error_noreturn(E_ERROR, "Using $this when not in object context");
491 		return NULL;
492 	}
493 }
494 
_get_obj_zval_ptr(int op_type,znode_op * op,const temp_variable * Ts,zend_free_op * should_free,int type TSRMLS_DC)495 static inline zval *_get_obj_zval_ptr(int op_type, znode_op *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
496 {
497 	if (op_type == IS_UNUSED) {
498 		if (EXPECTED(EG(This) != NULL)) {
499 			should_free->var = 0;
500 			return EG(This);
501 		} else {
502 			zend_error_noreturn(E_ERROR, "Using $this when not in object context");
503 		}
504 	}
505 	return get_zval_ptr(op_type, op, Ts, should_free, type);
506 }
507 
zend_assign_to_variable_reference(zval ** variable_ptr_ptr,zval ** value_ptr_ptr TSRMLS_DC)508 static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **value_ptr_ptr TSRMLS_DC)
509 {
510 	zval *variable_ptr = *variable_ptr_ptr;
511 	zval *value_ptr = *value_ptr_ptr;
512 
513 	if (variable_ptr == &EG(error_zval) || value_ptr == &EG(error_zval)) {
514 		variable_ptr_ptr = &EG(uninitialized_zval_ptr);
515 	} else if (variable_ptr != value_ptr) {
516 		if (!PZVAL_IS_REF(value_ptr)) {
517 			/* break it away */
518 			Z_DELREF_P(value_ptr);
519 			if (Z_REFCOUNT_P(value_ptr)>0) {
520 				ALLOC_ZVAL(*value_ptr_ptr);
521 				ZVAL_COPY_VALUE(*value_ptr_ptr, value_ptr);
522 				value_ptr = *value_ptr_ptr;
523 				zendi_zval_copy_ctor(*value_ptr);
524 			}
525 			Z_SET_REFCOUNT_P(value_ptr, 1);
526 			Z_SET_ISREF_P(value_ptr);
527 		}
528 
529 		*variable_ptr_ptr = value_ptr;
530 		Z_ADDREF_P(value_ptr);
531 
532 		zval_ptr_dtor(&variable_ptr);
533 	} else if (!Z_ISREF_P(variable_ptr)) {
534 		if (variable_ptr_ptr == value_ptr_ptr) {
535 			SEPARATE_ZVAL(variable_ptr_ptr);
536 		} else if (variable_ptr==&EG(uninitialized_zval)
537 			|| Z_REFCOUNT_P(variable_ptr)>2) {
538 			/* we need to separate */
539 			Z_SET_REFCOUNT_P(variable_ptr, Z_REFCOUNT_P(variable_ptr) - 2);
540 			ALLOC_ZVAL(*variable_ptr_ptr);
541 			ZVAL_COPY_VALUE(*variable_ptr_ptr, variable_ptr);
542 			zval_copy_ctor(*variable_ptr_ptr);
543 			*value_ptr_ptr = *variable_ptr_ptr;
544 			Z_SET_REFCOUNT_PP(variable_ptr_ptr, 2);
545 		}
546 		Z_SET_ISREF_PP(variable_ptr_ptr);
547 	}
548 }
549 
550 /* this should modify object only if it's empty */
make_real_object(zval ** object_ptr TSRMLS_DC)551 static inline void make_real_object(zval **object_ptr TSRMLS_DC)
552 {
553 	if (Z_TYPE_PP(object_ptr) == IS_NULL
554 		|| (Z_TYPE_PP(object_ptr) == IS_BOOL && Z_LVAL_PP(object_ptr) == 0)
555 		|| (Z_TYPE_PP(object_ptr) == IS_STRING && Z_STRLEN_PP(object_ptr) == 0)
556 	) {
557 		SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
558 		zval_dtor(*object_ptr);
559 		object_init(*object_ptr);
560 		zend_error(E_WARNING, "Creating default object from empty value");
561 	}
562 }
563 
zend_verify_arg_class_kind(const zend_arg_info * cur_arg_info,ulong fetch_type,const char ** class_name,zend_class_entry ** pce TSRMLS_DC)564 ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, const char **class_name, zend_class_entry **pce TSRMLS_DC)
565 {
566 	*pce = zend_fetch_class(cur_arg_info->class_name, cur_arg_info->class_name_len, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC);
567 
568 	*class_name = (*pce) ? (*pce)->name: cur_arg_info->class_name;
569 	if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
570 		return "implement interface ";
571 	} else {
572 		return "be an instance of ";
573 	}
574 }
575 
zend_verify_arg_error(int error_type,const zend_function * zf,zend_uint arg_num,const char * need_msg,const char * need_kind,const char * given_msg,const char * given_kind TSRMLS_DC)576 ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
577 {
578 	zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
579 	const char *fname = zf->common.function_name;
580 	char *fsep;
581 	const char *fclass;
582 
583 	if (zf->common.scope) {
584 		fsep =  "::";
585 		fclass = zf->common.scope->name;
586 	} else {
587 		fsep =  "";
588 		fclass = "";
589 	}
590 
591 	if (ptr && ptr->op_array) {
592 		zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->op_array->filename, ptr->opline->lineno);
593 	} else {
594 		zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
595 	}
596 	return 0;
597 }
598 
zend_verify_arg_type(zend_function * zf,zend_uint arg_num,zval * arg,ulong fetch_type TSRMLS_DC)599 static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
600 {
601 	zend_arg_info *cur_arg_info;
602 	char *need_msg;
603 	zend_class_entry *ce;
604 
605 	if (!zf->common.arg_info
606 		|| arg_num>zf->common.num_args) {
607 		return 1;
608 	}
609 
610 	cur_arg_info = &zf->common.arg_info[arg_num-1];
611 
612 	if (cur_arg_info->class_name) {
613 		const char *class_name;
614 
615 		if (!arg) {
616 			need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
617 			return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
618 		}
619 		if (Z_TYPE_P(arg) == IS_OBJECT) {
620 			need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
621 			if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
622 				return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
623 			}
624 		} else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
625 			need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
626 			return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
627 		}
628 	} else if (cur_arg_info->type_hint) {
629 		switch(cur_arg_info->type_hint) {
630 			case IS_ARRAY:
631 				if (!arg) {
632 					return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
633 				}
634 
635 				if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
636 					return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
637 				}
638 				break;
639 
640 			case IS_CALLABLE:
641 				if (!arg) {
642 					return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "" TSRMLS_CC);
643 				}
644 				if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
645 					return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC);
646 				}
647 				break;
648 
649 			default:
650 				zend_error(E_ERROR, "Unknown typehint");
651 		}
652 	}
653 	return 1;
654 }
655 
zend_assign_to_object(zval ** retval,zval ** object_ptr,zval * property_name,int value_type,znode_op * value_op,const temp_variable * Ts,int opcode,const zend_literal * key TSRMLS_DC)656 static inline void zend_assign_to_object(zval **retval, zval **object_ptr, zval *property_name, int value_type, znode_op *value_op, const temp_variable *Ts, int opcode, const zend_literal *key TSRMLS_DC)
657 {
658 	zval *object = *object_ptr;
659 	zend_free_op free_value;
660  	zval *value = get_zval_ptr(value_type, value_op, Ts, &free_value, BP_VAR_R);
661 
662 	if (Z_TYPE_P(object) != IS_OBJECT) {
663 		if (object == &EG(error_zval)) {
664  			if (retval) {
665 				*retval = &EG(uninitialized_zval);
666 				PZVAL_LOCK(*retval);
667 			}
668 			FREE_OP(free_value);
669 			return;
670 		}
671 		if (Z_TYPE_P(object) == IS_NULL ||
672 		    (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) ||
673 		    (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
674 			SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
675 			object = *object_ptr;
676 			Z_ADDREF_P(object);
677 			zend_error(E_WARNING, "Creating default object from empty value");
678 			if (Z_REFCOUNT_P(object) == 1) {
679 				/* object was removed by error handler, nothing to assign to */
680 				zval_ptr_dtor(&object);
681 				if (retval) {
682 					*retval = &EG(uninitialized_zval);
683 					PZVAL_LOCK(*retval);
684 				}
685 				FREE_OP(free_value);
686 				return;
687 			}
688 			Z_DELREF_P(object);
689 			zval_dtor(object);
690 			object_init(object);
691 		} else {
692 			zend_error(E_WARNING, "Attempt to assign property of non-object");
693 			if (retval) {
694 				*retval = &EG(uninitialized_zval);
695 				PZVAL_LOCK(*retval);
696 			}
697 			FREE_OP(free_value);
698 			return;
699 		}
700 	}
701 
702 	/* separate our value if necessary */
703 	if (value_type == IS_TMP_VAR) {
704 		zval *orig_value = value;
705 
706 		ALLOC_ZVAL(value);
707 		ZVAL_COPY_VALUE(value, orig_value);
708 		Z_UNSET_ISREF_P(value);
709 		Z_SET_REFCOUNT_P(value, 0);
710 	} else if (value_type == IS_CONST) {
711 		zval *orig_value = value;
712 
713 		ALLOC_ZVAL(value);
714 		ZVAL_COPY_VALUE(value, orig_value);
715 		Z_UNSET_ISREF_P(value);
716 		Z_SET_REFCOUNT_P(value, 0);
717 		zval_copy_ctor(value);
718 	}
719 
720 
721 	Z_ADDREF_P(value);
722 	if (opcode == ZEND_ASSIGN_OBJ) {
723 		if (!Z_OBJ_HT_P(object)->write_property) {
724 			zend_error(E_WARNING, "Attempt to assign property of non-object");
725 			if (retval) {
726 				*retval = &EG(uninitialized_zval);
727 				PZVAL_LOCK(&EG(uninitialized_zval));
728 			}
729 			if (value_type == IS_TMP_VAR) {
730 				FREE_ZVAL(value);
731 			} else if (value_type == IS_CONST) {
732 				zval_ptr_dtor(&value);
733 			}
734 			FREE_OP(free_value);
735 			return;
736 		}
737 		Z_OBJ_HT_P(object)->write_property(object, property_name, value, key TSRMLS_CC);
738 	} else {
739 		/* Note:  property_name in this case is really the array index! */
740 		if (!Z_OBJ_HT_P(object)->write_dimension) {
741 			zend_error_noreturn(E_ERROR, "Cannot use object as array");
742 		}
743 		Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
744 	}
745 
746 	if (retval && !EG(exception)) {
747 		*retval = value;
748 		PZVAL_LOCK(value);
749 	}
750 	zval_ptr_dtor(&value);
751 	FREE_OP_IF_VAR(free_value);
752 }
753 
zend_assign_to_string_offset(const temp_variable * T,const zval * value,int value_type TSRMLS_DC)754 static inline int zend_assign_to_string_offset(const temp_variable *T, const zval *value, int value_type TSRMLS_DC)
755 {
756 	if (Z_TYPE_P(T->str_offset.str) == IS_STRING) {
757 
758 		if (((int)T->str_offset.offset < 0)) {
759 			zend_error(E_WARNING, "Illegal string offset:  %d", T->str_offset.offset);
760 			return 0;
761 		}
762 
763 		if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) {
764 			if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
765 				char *tmp = (char *) emalloc(T->str_offset.offset+1+1);
766 
767 				memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str)+1);
768 				Z_STRVAL_P(T->str_offset.str) = tmp;
769 			} else {
770 				Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
771 			}
772 			memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str),
773 			       ' ',
774 			       T->str_offset.offset - Z_STRLEN_P(T->str_offset.str));
775 			Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0;
776 			Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1;
777 		} else if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) {
778 			char *tmp = (char *) emalloc(Z_STRLEN_P(T->str_offset.str) + 1);
779 
780 			memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str) + 1);
781 			Z_STRVAL_P(T->str_offset.str) = tmp;
782 		}
783 
784 		if (Z_TYPE_P(value) != IS_STRING) {
785 			zval tmp;
786 
787 			ZVAL_COPY_VALUE(&tmp, value);
788 			if (value_type != IS_TMP_VAR) {
789 				zval_copy_ctor(&tmp);
790 			}
791 			convert_to_string(&tmp);
792 			Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL(tmp)[0];
793 			STR_FREE(Z_STRVAL(tmp));
794 		} else {
795 			Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(value)[0];
796 			if (value_type == IS_TMP_VAR) {
797 				/* we can safely free final_value here
798 				 * because separation is done only
799 				 * in case value_type == IS_VAR */
800 				STR_FREE(Z_STRVAL_P(value));
801 			}
802 		}
803 		/*
804 		 * the value of an assignment to a string offset is undefined
805 		T(result->u.var).var = &T->str_offset.str;
806 		*/
807 	}
808 	return 1;
809 }
810 
811 
zend_assign_tmp_to_variable(zval ** variable_ptr_ptr,zval * value TSRMLS_DC)812 static inline zval* zend_assign_tmp_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
813 {
814 	zval *variable_ptr = *variable_ptr_ptr;
815 	zval garbage;
816 
817 	if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
818 	    UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
819 		Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
820 		return variable_ptr;
821 	}
822 
823  	if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
824  	    EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
825  	    /* we need to split */
826 		Z_DELREF_P(variable_ptr);
827 		GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
828 		ALLOC_ZVAL(variable_ptr);
829 		INIT_PZVAL_COPY(variable_ptr, value);
830 		*variable_ptr_ptr = variable_ptr;
831 		return variable_ptr;
832 	} else {
833 		if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
834 			/* nothing to destroy */
835 			ZVAL_COPY_VALUE(variable_ptr, value);
836 		} else {
837 			ZVAL_COPY_VALUE(&garbage, variable_ptr);
838 			ZVAL_COPY_VALUE(variable_ptr, value);
839 			_zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
840 		}
841 		return variable_ptr;
842 	}
843 }
844 
zend_assign_const_to_variable(zval ** variable_ptr_ptr,zval * value TSRMLS_DC)845 static inline zval* zend_assign_const_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
846 {
847 	zval *variable_ptr = *variable_ptr_ptr;
848 	zval garbage;
849 
850 	if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
851 	    UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
852 		Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
853 		return variable_ptr;
854 	}
855 
856  	if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) &&
857  	    EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
858 		/* we need to split */
859 		Z_DELREF_P(variable_ptr);
860 		GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
861 		ALLOC_ZVAL(variable_ptr);
862 		INIT_PZVAL_COPY(variable_ptr, value);
863 		zval_copy_ctor(variable_ptr);
864 		*variable_ptr_ptr = variable_ptr;
865 		return variable_ptr;
866  	} else {
867 		if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
868 			/* nothing to destroy */
869 			ZVAL_COPY_VALUE(variable_ptr, value);
870 			zendi_zval_copy_ctor(*variable_ptr);
871 		} else {
872 			ZVAL_COPY_VALUE(&garbage, variable_ptr);
873 			ZVAL_COPY_VALUE(variable_ptr, value);
874 			zendi_zval_copy_ctor(*variable_ptr);
875 			_zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
876 		}
877 		return variable_ptr;
878 	}
879 }
880 
zend_assign_to_variable(zval ** variable_ptr_ptr,zval * value TSRMLS_DC)881 static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
882 {
883 	zval *variable_ptr = *variable_ptr_ptr;
884 	zval garbage;
885 
886 	if (Z_TYPE_P(variable_ptr) == IS_OBJECT &&
887 	    UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) {
888 		Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
889 		return variable_ptr;
890 	}
891 
892  	if (EXPECTED(!PZVAL_IS_REF(variable_ptr))) {
893 		if (Z_REFCOUNT_P(variable_ptr)==1) {
894 			if (UNEXPECTED(variable_ptr == value)) {
895 				return variable_ptr;
896 			} else if (EXPECTED(!PZVAL_IS_REF(value))) {
897 				Z_ADDREF_P(value);
898 				*variable_ptr_ptr = value;
899 				if (EXPECTED(variable_ptr != &EG(uninitialized_zval))) {
900 					GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
901 					zval_dtor(variable_ptr);
902 					efree(variable_ptr);
903 				} else {
904 					Z_DELREF_P(variable_ptr);
905 				}
906 				return value;
907 			} else {
908 				goto copy_value;
909 			}
910 		} else { /* we need to split */
911 			Z_DELREF_P(variable_ptr);
912 			GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
913 			if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) {
914 				ALLOC_ZVAL(variable_ptr);
915 				*variable_ptr_ptr = variable_ptr;
916 				INIT_PZVAL_COPY(variable_ptr, value);
917 				zval_copy_ctor(variable_ptr);
918 				return variable_ptr;
919 			} else {
920 				*variable_ptr_ptr = value;
921 				Z_ADDREF_P(value);
922 				Z_UNSET_ISREF_P(value);
923 				return value;
924 			}
925 		}
926  	} else {
927 		if (EXPECTED(variable_ptr != value)) {
928 copy_value:
929 			if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) {
930 				/* nothing to destroy */
931 				ZVAL_COPY_VALUE(variable_ptr, value);
932 				zendi_zval_copy_ctor(*variable_ptr);
933 			} else {
934 				ZVAL_COPY_VALUE(&garbage, variable_ptr);
935 				ZVAL_COPY_VALUE(variable_ptr, value);
936 				zendi_zval_copy_ctor(*variable_ptr);
937 				_zval_dtor_func(&garbage ZEND_FILE_LINE_CC);
938 			}
939 		}
940 		return variable_ptr;
941 	}
942 }
943 
944 /* Utility Functions for Extensions */
zend_extension_statement_handler(const zend_extension * extension,zend_op_array * op_array TSRMLS_DC)945 static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
946 {
947 	if (extension->statement_handler) {
948 		extension->statement_handler(op_array);
949 	}
950 }
951 
952 
zend_extension_fcall_begin_handler(const zend_extension * extension,zend_op_array * op_array TSRMLS_DC)953 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
954 {
955 	if (extension->fcall_begin_handler) {
956 		extension->fcall_begin_handler(op_array);
957 	}
958 }
959 
960 
zend_extension_fcall_end_handler(const zend_extension * extension,zend_op_array * op_array TSRMLS_DC)961 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
962 {
963 	if (extension->fcall_end_handler) {
964 		extension->fcall_end_handler(op_array);
965 	}
966 }
967 
968 
zend_get_target_symbol_table(int fetch_type TSRMLS_DC)969 static inline HashTable *zend_get_target_symbol_table(int fetch_type TSRMLS_DC)
970 {
971 	switch (fetch_type) {
972 		case ZEND_FETCH_LOCAL:
973 			if (!EG(active_symbol_table)) {
974 				zend_rebuild_symbol_table(TSRMLS_C);
975 			}
976 			return EG(active_symbol_table);
977 			break;
978 		case ZEND_FETCH_GLOBAL:
979 		case ZEND_FETCH_GLOBAL_LOCK:
980 			return &EG(symbol_table);
981 			break;
982 		case ZEND_FETCH_STATIC:
983 			if (!EG(active_op_array)->static_variables) {
984 				ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
985 				zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
986 			}
987 			return EG(active_op_array)->static_variables;
988 			break;
989 		EMPTY_SWITCH_DEFAULT_CASE()
990 	}
991 	return NULL;
992 }
993 
zend_fetch_dimension_address_inner(HashTable * ht,const zval * dim,int dim_type,int type TSRMLS_DC)994 static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type TSRMLS_DC)
995 {
996 	zval **retval;
997 	char *offset_key;
998 	int offset_key_length;
999 	ulong hval;
1000 
1001 	switch (dim->type) {
1002 		case IS_NULL:
1003 			offset_key = "";
1004 			offset_key_length = 0;
1005 			hval = zend_inline_hash_func("", 1);
1006 			goto fetch_string_dim;
1007 
1008 		case IS_STRING:
1009 
1010 			offset_key = dim->value.str.val;
1011 			offset_key_length = dim->value.str.len;
1012 
1013 			if (dim_type == IS_CONST) {
1014 				hval = Z_HASH_P(dim);
1015 			} else {
1016 				ZEND_HANDLE_NUMERIC_EX(offset_key, offset_key_length+1, hval, goto num_index);
1017 				if (IS_INTERNED(offset_key)) {
1018 					hval = INTERNED_HASH(offset_key);
1019 				} else {
1020 					hval = zend_hash_func(offset_key, offset_key_length+1);
1021 				}
1022 			}
1023 fetch_string_dim:
1024 			if (zend_hash_quick_find(ht, offset_key, offset_key_length+1, hval, (void **) &retval) == FAILURE) {
1025 				switch (type) {
1026 					case BP_VAR_R:
1027 						zend_error(E_NOTICE, "Undefined index: %s", offset_key);
1028 						/* break missing intentionally */
1029 					case BP_VAR_UNSET:
1030 					case BP_VAR_IS:
1031 						retval = &EG(uninitialized_zval_ptr);
1032 						break;
1033 					case BP_VAR_RW:
1034 						zend_error(E_NOTICE,"Undefined index: %s", offset_key);
1035 						/* break missing intentionally */
1036 					case BP_VAR_W: {
1037 							zval *new_zval = &EG(uninitialized_zval);
1038 
1039 							Z_ADDREF_P(new_zval);
1040 							zend_hash_quick_update(ht, offset_key, offset_key_length+1, hval, &new_zval, sizeof(zval *), (void **) &retval);
1041 						}
1042 						break;
1043 				}
1044 			}
1045 			break;
1046 		case IS_DOUBLE:
1047 			hval = zend_dval_to_lval(Z_DVAL_P(dim));
1048 			goto num_index;
1049 		case IS_RESOURCE:
1050 			zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim));
1051 			/* Fall Through */
1052 		case IS_BOOL:
1053 		case IS_LONG:
1054 			hval = Z_LVAL_P(dim);
1055 num_index:
1056 			if (zend_hash_index_find(ht, hval, (void **) &retval) == FAILURE) {
1057 				switch (type) {
1058 					case BP_VAR_R:
1059 						zend_error(E_NOTICE,"Undefined offset: %ld", hval);
1060 						/* break missing intentionally */
1061 					case BP_VAR_UNSET:
1062 					case BP_VAR_IS:
1063 						retval = &EG(uninitialized_zval_ptr);
1064 						break;
1065 					case BP_VAR_RW:
1066 						zend_error(E_NOTICE,"Undefined offset: %ld", hval);
1067 						/* break missing intentionally */
1068 					case BP_VAR_W: {
1069 						zval *new_zval = &EG(uninitialized_zval);
1070 
1071 						Z_ADDREF_P(new_zval);
1072 						zend_hash_index_update(ht, hval, &new_zval, sizeof(zval *), (void **) &retval);
1073 					}
1074 					break;
1075 				}
1076 			}
1077 			break;
1078 
1079 		default:
1080 			zend_error(E_WARNING, "Illegal offset type");
1081 			return (type == BP_VAR_W || type == BP_VAR_RW) ?
1082 				&EG(error_zval_ptr) : &EG(uninitialized_zval_ptr);
1083 	}
1084 	return retval;
1085 }
1086 
zend_fetch_dimension_address(temp_variable * result,zval ** container_ptr,zval * dim,int dim_type,int type TSRMLS_DC)1087 static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_type, int type TSRMLS_DC)
1088 {
1089 	zval *container = *container_ptr;
1090 	zval **retval;
1091 
1092 	switch (Z_TYPE_P(container)) {
1093 
1094 		case IS_ARRAY:
1095 			if (type != BP_VAR_UNSET && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) {
1096 				SEPARATE_ZVAL(container_ptr);
1097 				container = *container_ptr;
1098 			}
1099 fetch_from_array:
1100 			if (dim == NULL) {
1101 				zval *new_zval = &EG(uninitialized_zval);
1102 
1103 				Z_ADDREF_P(new_zval);
1104 				if (zend_hash_next_index_insert(Z_ARRVAL_P(container), &new_zval, sizeof(zval *), (void **) &retval) == FAILURE) {
1105 					zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1106 					retval = &EG(error_zval_ptr);
1107 					Z_DELREF_P(new_zval);
1108 				}
1109 			} else {
1110 				retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
1111 			}
1112 			result->var.ptr_ptr = retval;
1113 			PZVAL_LOCK(*retval);
1114 			return;
1115 			break;
1116 
1117 		case IS_NULL:
1118 			if (container == &EG(error_zval)) {
1119 				result->var.ptr_ptr = &EG(error_zval_ptr);
1120 				PZVAL_LOCK(EG(error_zval_ptr));
1121 			} else if (type != BP_VAR_UNSET) {
1122 convert_to_array:
1123 				if (!PZVAL_IS_REF(container)) {
1124 					SEPARATE_ZVAL(container_ptr);
1125 					container = *container_ptr;
1126 				}
1127 				zval_dtor(container);
1128 				array_init(container);
1129 				goto fetch_from_array;
1130 			} else {
1131 				/* for read-mode only */
1132 				result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
1133 				PZVAL_LOCK(EG(uninitialized_zval_ptr));
1134 			}
1135 			return;
1136 			break;
1137 
1138 		case IS_STRING: {
1139 				zval tmp;
1140 
1141 				if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) {
1142 					goto convert_to_array;
1143 				}
1144 				if (dim == NULL) {
1145 					zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
1146 				}
1147 
1148 				if (type != BP_VAR_UNSET) {
1149 					SEPARATE_ZVAL_IF_NOT_REF(container_ptr);
1150 				}
1151 
1152 				if (Z_TYPE_P(dim) != IS_LONG) {
1153 
1154 					switch(Z_TYPE_P(dim)) {
1155 						/* case IS_LONG: */
1156 						case IS_STRING:
1157 							if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1158 								break;
1159 							}
1160 							if (type != BP_VAR_UNSET) {
1161 								zend_error(E_WARNING, "Illegal string offset '%s'", dim->value.str.val);
1162 							}
1163 
1164 							break;
1165 						case IS_DOUBLE:
1166 						case IS_NULL:
1167 						case IS_BOOL:
1168 							zend_error(E_NOTICE, "String offset cast occurred");
1169 							break;
1170 						default:
1171 							zend_error(E_WARNING, "Illegal offset type");
1172 							break;
1173 					}
1174 
1175 					tmp = *dim;
1176 					zval_copy_ctor(&tmp);
1177 					convert_to_long(&tmp);
1178 					dim = &tmp;
1179 				}
1180 				container = *container_ptr;
1181 				result->str_offset.str = container;
1182 				PZVAL_LOCK(container);
1183 				result->str_offset.offset = Z_LVAL_P(dim);
1184 				result->str_offset.ptr_ptr = NULL;
1185 				return;
1186 			}
1187 			break;
1188 
1189 		case IS_OBJECT:
1190 			if (!Z_OBJ_HT_P(container)->read_dimension) {
1191 				zend_error_noreturn(E_ERROR, "Cannot use object as array");
1192 			} else {
1193 				zval *overloaded_result;
1194 
1195 				if (dim_type == IS_TMP_VAR) {
1196 					zval *orig = dim;
1197 					MAKE_REAL_ZVAL_PTR(dim);
1198 					ZVAL_NULL(orig);
1199 				}
1200 				overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
1201 
1202 				if (overloaded_result) {
1203 					if (!Z_ISREF_P(overloaded_result)) {
1204 						if (Z_REFCOUNT_P(overloaded_result) > 0) {
1205 							zval *tmp = overloaded_result;
1206 
1207 							ALLOC_ZVAL(overloaded_result);
1208 							ZVAL_COPY_VALUE(overloaded_result, tmp);
1209 							zval_copy_ctor(overloaded_result);
1210 							Z_UNSET_ISREF_P(overloaded_result);
1211 							Z_SET_REFCOUNT_P(overloaded_result, 0);
1212 						}
1213 						if (Z_TYPE_P(overloaded_result) != IS_OBJECT) {
1214 							zend_class_entry *ce = Z_OBJCE_P(container);
1215 							zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
1216 						}
1217 					}
1218 					retval = &overloaded_result;
1219 				} else {
1220 					retval = &EG(error_zval_ptr);
1221 				}
1222 				AI_SET_PTR(result, *retval);
1223 				PZVAL_LOCK(*retval);
1224 				if (dim_type == IS_TMP_VAR) {
1225 					zval_ptr_dtor(&dim);
1226 				}
1227 			}
1228 			return;
1229 			break;
1230 
1231 		case IS_BOOL:
1232 			if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
1233 				goto convert_to_array;
1234 			}
1235 			/* break missing intentionally */
1236 
1237 		default:
1238 			if (type == BP_VAR_UNSET) {
1239 				zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1240 				AI_SET_PTR(result, &EG(uninitialized_zval));
1241 				PZVAL_LOCK(&EG(uninitialized_zval));
1242 			} else {
1243 				zend_error(E_WARNING, "Cannot use a scalar value as an array");
1244 				result->var.ptr_ptr = &EG(error_zval_ptr);
1245 				PZVAL_LOCK(EG(error_zval_ptr));
1246 			}
1247 			break;
1248 	}
1249 }
1250 
zend_fetch_dimension_address_read(temp_variable * result,zval * container,zval * dim,int dim_type,int type TSRMLS_DC)1251 static void zend_fetch_dimension_address_read(temp_variable *result, zval *container, zval *dim, int dim_type, int type TSRMLS_DC)
1252 {
1253 	zval **retval;
1254 
1255 	switch (Z_TYPE_P(container)) {
1256 
1257 		case IS_ARRAY:
1258 			retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type TSRMLS_CC);
1259 			AI_SET_PTR(result, *retval);
1260 			PZVAL_LOCK(*retval);
1261 			return;
1262 
1263 		case IS_NULL:
1264 			AI_SET_PTR(result, &EG(uninitialized_zval));
1265 			PZVAL_LOCK(&EG(uninitialized_zval));
1266 			return;
1267 
1268 		case IS_STRING: {
1269 				zval tmp;
1270 				zval *ptr;
1271 
1272 				if (Z_TYPE_P(dim) != IS_LONG) {
1273 					switch(Z_TYPE_P(dim)) {
1274 						/* case IS_LONG: */
1275 						case IS_STRING:
1276 							if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1277 								break;
1278 							}
1279 							if (type != BP_VAR_IS) {
1280 								zend_error(E_WARNING, "Illegal string offset '%s'", dim->value.str.val);
1281 							}
1282 							break;
1283 						case IS_DOUBLE:
1284 						case IS_NULL:
1285 						case IS_BOOL:
1286 							if (type != BP_VAR_IS) {
1287 								zend_error(E_NOTICE, "String offset cast occurred");
1288 							}
1289 							break;
1290 						default:
1291 							zend_error(E_WARNING, "Illegal offset type");
1292 							break;
1293 					}
1294 
1295 					ZVAL_COPY_VALUE(&tmp, dim);
1296 					zval_copy_ctor(&tmp);
1297 					convert_to_long(&tmp);
1298 					dim = &tmp;
1299 				}
1300 
1301 				ALLOC_ZVAL(ptr);
1302 				INIT_PZVAL(ptr);
1303 				Z_TYPE_P(ptr) = IS_STRING;
1304 
1305 				if (Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) {
1306 					if (type != BP_VAR_IS) {
1307 						zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
1308 					}
1309 					Z_STRVAL_P(ptr) = STR_EMPTY_ALLOC();
1310 					Z_STRLEN_P(ptr) = 0;
1311 				} else {
1312 					Z_STRVAL_P(ptr) = (char*)emalloc(2);
1313 					Z_STRVAL_P(ptr)[0] = Z_STRVAL_P(container)[Z_LVAL_P(dim)];
1314 					Z_STRVAL_P(ptr)[1] = 0;
1315 					Z_STRLEN_P(ptr) = 1;
1316 				}
1317 				AI_SET_PTR(result, ptr);
1318 				return;
1319 			}
1320 			break;
1321 
1322 		case IS_OBJECT:
1323 			if (!Z_OBJ_HT_P(container)->read_dimension) {
1324 				zend_error_noreturn(E_ERROR, "Cannot use object as array");
1325 			} else {
1326 				zval *overloaded_result;
1327 
1328 				if (dim_type == IS_TMP_VAR) {
1329 					zval *orig = dim;
1330 					MAKE_REAL_ZVAL_PTR(dim);
1331 					ZVAL_NULL(orig);
1332 				}
1333 				overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
1334 
1335 				if (overloaded_result) {
1336 					AI_SET_PTR(result, overloaded_result);
1337 					PZVAL_LOCK(overloaded_result);
1338 				} else if (result) {
1339 					AI_SET_PTR(result, &EG(uninitialized_zval));
1340 					PZVAL_LOCK(&EG(uninitialized_zval));
1341 				}
1342 				if (dim_type == IS_TMP_VAR) {
1343 					zval_ptr_dtor(&dim);
1344 				}
1345 			}
1346 			return;
1347 
1348 		default:
1349 			AI_SET_PTR(result, &EG(uninitialized_zval));
1350 			PZVAL_LOCK(&EG(uninitialized_zval));
1351 			return;
1352 	}
1353 }
1354 
zend_fetch_property_address(temp_variable * result,zval ** container_ptr,zval * prop_ptr,const zend_literal * key,int type TSRMLS_DC)1355 static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, const zend_literal *key, int type TSRMLS_DC)
1356 {
1357 	zval *container = *container_ptr;;
1358 
1359 	if (Z_TYPE_P(container) != IS_OBJECT) {
1360 		if (container == &EG(error_zval)) {
1361 			result->var.ptr_ptr = &EG(error_zval_ptr);
1362 			PZVAL_LOCK(EG(error_zval_ptr));
1363 			return;
1364 		}
1365 
1366 		/* this should modify object only if it's empty */
1367 		if (type != BP_VAR_UNSET &&
1368 		    ((Z_TYPE_P(container) == IS_NULL ||
1369 		     (Z_TYPE_P(container) == IS_BOOL && Z_LVAL_P(container)==0) ||
1370 		     (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
1371 			if (!PZVAL_IS_REF(container)) {
1372 				SEPARATE_ZVAL(container_ptr);
1373 				container = *container_ptr;
1374 			}
1375 			object_init(container);
1376 		} else {
1377 			zend_error(E_WARNING, "Attempt to modify property of non-object");
1378 			result->var.ptr_ptr = &EG(error_zval_ptr);
1379 			PZVAL_LOCK(EG(error_zval_ptr));
1380 			return;
1381 		}
1382 	}
1383 
1384 	if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
1385 		zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, key TSRMLS_CC);
1386 		if (NULL == ptr_ptr) {
1387 			zval *ptr;
1388 
1389 			if (Z_OBJ_HT_P(container)->read_property &&
1390 				(ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, key TSRMLS_CC)) != NULL) {
1391 				AI_SET_PTR(result, ptr);
1392 				PZVAL_LOCK(ptr);
1393 			} else {
1394 				zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
1395 			}
1396 		} else {
1397 			result->var.ptr_ptr = ptr_ptr;
1398 			PZVAL_LOCK(*ptr_ptr);
1399 		}
1400 	} else if (Z_OBJ_HT_P(container)->read_property) {
1401 		zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, key TSRMLS_CC);
1402 
1403 		AI_SET_PTR(result, ptr);
1404 		PZVAL_LOCK(ptr);
1405 	} else {
1406 		zend_error(E_WARNING, "This object doesn't support property references");
1407 		result->var.ptr_ptr = &EG(error_zval_ptr);
1408 		PZVAL_LOCK(EG(error_zval_ptr));
1409 	}
1410 }
1411 
zend_brk_cont(int nest_levels,int array_offset,const zend_op_array * op_array,const temp_variable * Ts TSRMLS_DC)1412 static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_offset, const zend_op_array *op_array, const temp_variable *Ts TSRMLS_DC)
1413 {
1414 	int original_nest_levels = nest_levels;
1415 	zend_brk_cont_element *jmp_to;
1416 
1417 	do {
1418 		if (array_offset==-1) {
1419 			zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
1420 		}
1421 		jmp_to = &op_array->brk_cont_array[array_offset];
1422 		if (nest_levels>1) {
1423 			zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
1424 
1425 			switch (brk_opline->opcode) {
1426 				case ZEND_SWITCH_FREE:
1427 					if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
1428 						zval_ptr_dtor(&T(brk_opline->op1.var).var.ptr);
1429 					}
1430 					break;
1431 				case ZEND_FREE:
1432 					if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
1433 						zendi_zval_dtor(T(brk_opline->op1.var).tmp_var);
1434 					}
1435 					break;
1436 			}
1437 		}
1438 		array_offset = jmp_to->parent;
1439 	} while (--nest_levels > 0);
1440 	return jmp_to;
1441 }
1442 
1443 #if ZEND_INTENSIVE_DEBUGGING
1444 
1445 #define CHECK_SYMBOL_TABLES()														\
1446 	zend_hash_apply(&EG(symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);	\
1447 	if (&EG(symbol_table)!=EG(active_symbol_table)) {								\
1448 		zend_hash_apply(EG(active_symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC);	\
1449 	}
1450 
zend_check_symbol(zval ** pz TSRMLS_DC)1451 static int zend_check_symbol(zval **pz TSRMLS_DC)
1452 {
1453 	if (Z_TYPE_PP(pz) > 9) {
1454 		fprintf(stderr, "Warning!  %x has invalid type!\n", *pz);
1455 /* See http://support.microsoft.com/kb/190351 */
1456 #ifdef PHP_WIN32
1457 		fflush(stderr);
1458 #endif
1459 	} else if (Z_TYPE_PP(pz) == IS_ARRAY) {
1460 		zend_hash_apply(Z_ARRVAL_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
1461 	} else if (Z_TYPE_PP(pz) == IS_OBJECT) {
1462 
1463 		/* OBJ-TBI - doesn't support new object model! */
1464 		zend_hash_apply(Z_OBJPROP_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
1465 	}
1466 
1467 	return 0;
1468 }
1469 
1470 
1471 #else
1472 #define CHECK_SYMBOL_TABLES()
1473 #endif
1474 
1475 ZEND_API opcode_handler_t *zend_opcode_handlers;
1476 
execute_internal(zend_execute_data * execute_data_ptr,int return_value_used TSRMLS_DC)1477 ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
1478 {
1479 	zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.var)).var.ptr;
1480 	((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, *return_value_ptr, (execute_data_ptr->function_state.function->common.fn_flags & ZEND_ACC_RETURN_REFERENCE)?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC);
1481 }
1482 
1483 #define ZEND_VM_NEXT_OPCODE() \
1484 	CHECK_SYMBOL_TABLES() \
1485 	ZEND_VM_INC_OPCODE(); \
1486 	ZEND_VM_CONTINUE()
1487 
1488 #define ZEND_VM_SET_OPCODE(new_op) \
1489 	CHECK_SYMBOL_TABLES() \
1490 	OPLINE = new_op
1491 
1492 #define ZEND_VM_JMP(new_op) \
1493 	if (EXPECTED(!EG(exception))) { \
1494 		ZEND_VM_SET_OPCODE(new_op); \
1495 	} else { \
1496 		LOAD_OPLINE(); \
1497 	} \
1498 	ZEND_VM_CONTINUE()
1499 
1500 #define ZEND_VM_INC_OPCODE() \
1501 	OPLINE++
1502 
1503 #ifdef __GNUC__
1504 # define ZEND_VM_GUARD(name) __asm__("#" #name)
1505 #else
1506 # define ZEND_VM_GUARD(name)
1507 #endif
1508 
1509 #include "zend_vm_execute.h"
1510 
zend_set_user_opcode_handler(zend_uchar opcode,user_opcode_handler_t handler)1511 ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
1512 {
1513 	if (opcode != ZEND_USER_OPCODE) {
1514 		if (handler == NULL) {
1515 			/* restore the original handler */
1516 			zend_user_opcodes[opcode] = opcode;
1517 		} else {
1518 			zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
1519 		}
1520 		zend_user_opcode_handlers[opcode] = handler;
1521 		return SUCCESS;
1522 	}
1523 	return FAILURE;
1524 }
1525 
zend_get_user_opcode_handler(zend_uchar opcode)1526 ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
1527 {
1528 	return zend_user_opcode_handlers[opcode];
1529 }
1530 
zend_get_zval_ptr(int op_type,const znode_op * node,const temp_variable * Ts,zend_free_op * should_free,int type TSRMLS_DC)1531 ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
1532 	return get_zval_ptr(op_type, node, Ts, should_free, type);
1533 }
1534 
zend_get_zval_ptr_ptr(int op_type,const znode_op * node,const temp_variable * Ts,zend_free_op * should_free,int type TSRMLS_DC)1535 ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
1536 	return get_zval_ptr_ptr(op_type, node, Ts, should_free, type);
1537 }
1538 
1539 /*
1540  * Local variables:
1541  * tab-width: 4
1542  * c-basic-offset: 4
1543  * indent-tabs-mode: t
1544  * End:
1545  */
1546