1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 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: zend_execute.c 281670 2009-06-04 18:20:45Z mattwil $ */
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 :
40 : /* Virtual current working directory support */
41 : #include "tsrm_virtual_cwd.h"
42 :
43 : #define _CONST_CODE 0
44 : #define _TMP_CODE 1
45 : #define _VAR_CODE 2
46 : #define _UNUSED_CODE 3
47 : #define _CV_CODE 4
48 :
49 : typedef int (*incdec_t)(zval *);
50 :
51 : #define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
52 : #define get_zval_ptr_ptr(node, Ts, should_free, type) _get_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
53 : #define get_obj_zval_ptr(node, Ts, should_free, type) _get_obj_zval_ptr(node, Ts, should_free, type TSRMLS_CC)
54 : #define get_obj_zval_ptr_ptr(node, Ts, should_free, type) _get_obj_zval_ptr_ptr(node, Ts, should_free, type TSRMLS_CC)
55 :
56 : /* Prototypes */
57 : static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
58 : static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
59 : static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC);
60 :
61 : #define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED))
62 :
63 : #define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset))
64 : #define T(offset) (*(temp_variable *)((char *) Ts + offset))
65 :
66 : #define TEMP_VAR_STACK_LIMIT 2000
67 :
68 : static zend_always_inline void zend_pzval_unlock_func(zval *z, zend_free_op *should_free, int unref TSRMLS_DC)
69 27864611 : {
70 27864611 : if (!Z_DELREF_P(z)) {
71 15223575 : Z_SET_REFCOUNT_P(z, 1);
72 15223575 : Z_UNSET_ISREF_P(z);
73 15223575 : should_free->var = z;
74 : /* should_free->is_var = 1; */
75 : } else {
76 12641036 : should_free->var = 0;
77 12641036 : if (unref && Z_ISREF_P(z) && Z_REFCOUNT_P(z) == 1) {
78 26163 : Z_UNSET_ISREF_P(z);
79 : }
80 12641036 : GC_ZVAL_CHECK_POSSIBLE_ROOT(z);
81 : }
82 27864611 : }
83 :
84 : static zend_always_inline void zend_pzval_unlock_free_func(zval *z TSRMLS_DC)
85 5575 : {
86 5575 : if (!Z_DELREF_P(z)) {
87 2 : if (z != &EG(uninitialized_zval)) {
88 2 : GC_REMOVE_ZVAL_FROM_BUFFER(z);
89 2 : zval_dtor(z);
90 2 : efree(z);
91 : }
92 : }
93 5575 : }
94 :
95 : #define PZVAL_UNLOCK(z, f) zend_pzval_unlock_func(z, f, 1 TSRMLS_CC)
96 : #define PZVAL_UNLOCK_EX(z, f, u) zend_pzval_unlock_func(z, f, u TSRMLS_CC)
97 : #define PZVAL_UNLOCK_FREE(z) zend_pzval_unlock_free_func(z TSRMLS_CC)
98 : #define PZVAL_LOCK(z) Z_ADDREF_P((z))
99 : #define RETURN_VALUE_UNUSED(pzn) (((pzn)->u.EA.type & EXT_TYPE_UNUSED))
100 : #define SELECTIVE_PZVAL_LOCK(pzv, pzn) if (!RETURN_VALUE_UNUSED(pzn)) { PZVAL_LOCK(pzv); }
101 :
102 : #define AI_USE_PTR(ai) \
103 : if ((ai).ptr_ptr) { \
104 : (ai).ptr = *((ai).ptr_ptr); \
105 : (ai).ptr_ptr = &((ai).ptr); \
106 : } else { \
107 : (ai).ptr = NULL; \
108 : }
109 :
110 : #define AI_SET_PTR(ai, val) \
111 : (ai).ptr = (val); \
112 : (ai).ptr_ptr = &((ai).ptr);
113 :
114 : #define FREE_OP(should_free) \
115 : if (should_free.var) { \
116 : if ((zend_uintptr_t)should_free.var & 1L) { \
117 : zval_dtor((zval*)((zend_uintptr_t)should_free.var & ~1L)); \
118 : } else { \
119 : zval_ptr_dtor(&should_free.var); \
120 : } \
121 : }
122 :
123 : #define FREE_OP_IF_VAR(should_free) \
124 : if (should_free.var != NULL && (((zend_uintptr_t)should_free.var & 1L) == 0)) { \
125 : zval_ptr_dtor(&should_free.var); \
126 : }
127 :
128 : #define FREE_OP_VAR_PTR(should_free) \
129 : if (should_free.var) { \
130 : zval_ptr_dtor(&should_free.var); \
131 : }
132 :
133 : #define TMP_FREE(z) (zval*)(((zend_uintptr_t)(z)) | 1L)
134 :
135 : #define IS_TMP_FREE(should_free) ((zend_uintptr_t)should_free.var & 1L)
136 :
137 : #define INIT_PZVAL_COPY(z,v) \
138 : (z)->value = (v)->value; \
139 : Z_TYPE_P(z) = Z_TYPE_P(v); \
140 : Z_SET_REFCOUNT_P(z, 1); \
141 : Z_UNSET_ISREF_P(z);
142 :
143 : #define MAKE_REAL_ZVAL_PTR(val) \
144 : do { \
145 : zval *_tmp; \
146 : ALLOC_ZVAL(_tmp); \
147 : _tmp->value = (val)->value; \
148 : Z_TYPE_P(_tmp) = Z_TYPE_P(val); \
149 : Z_SET_REFCOUNT_P(_tmp, 1); \
150 : Z_UNSET_ISREF_P(_tmp); \
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 :
170 : ZEND_API zval** zend_get_compiled_variable_value(const zend_execute_data *execute_data_ptr, zend_uint var)
171 0 : {
172 0 : return execute_data_ptr->CVs[var];
173 : }
174 :
175 : static zend_always_inline zval *_get_zval_ptr_tmp(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
176 22487851 : {
177 22487851 : return should_free->var = &T(node->u.var).tmp_var;
178 : }
179 :
180 : static zval *_get_zval_ptr_var_string_offset(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
181 5560 : {
182 5560 : temp_variable *T = &T(node->u.var);
183 5560 : zval *str = T->str_offset.str;
184 : zval *ptr;
185 :
186 : /* string offset */
187 5560 : ALLOC_ZVAL(ptr);
188 5560 : T->str_offset.ptr = ptr;
189 5560 : should_free->var = ptr;
190 :
191 5578 : if (T->str_offset.str->type != IS_STRING
192 : || ((int)T->str_offset.offset < 0)
193 : || (T->str_offset.str->value.str.len <= (int)T->str_offset.offset)) {
194 18 : ptr->value.str.val = STR_EMPTY_ALLOC();
195 18 : ptr->value.str.len = 0;
196 : } else {
197 5542 : ptr->value.str.val = estrndup(str->value.str.val + T->str_offset.offset, 1);
198 5542 : ptr->value.str.len = 1;
199 : }
200 5560 : PZVAL_UNLOCK_FREE(str);
201 5560 : Z_SET_REFCOUNT_P(ptr, 1);
202 5560 : Z_SET_ISREF_P(ptr);
203 5560 : ptr->type = IS_STRING;
204 5560 : return ptr;
205 : }
206 :
207 : static zend_always_inline zval *_get_zval_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
208 22668658 : {
209 22668658 : zval *ptr = T(node->u.var).var.ptr;
210 22668658 : if (EXPECTED(ptr != NULL)) {
211 22663098 : PZVAL_UNLOCK(ptr, should_free);
212 22663098 : return ptr;
213 : } else {
214 5560 : return _get_zval_ptr_var_string_offset(node, Ts, should_free TSRMLS_CC);
215 : }
216 : }
217 :
218 : static zval **_get_zval_cv_lookup(zval ***ptr, zend_uint var, int type TSRMLS_DC)
219 5382335 : {
220 5382335 : zend_compiled_variable *cv = &CV_DEF_OF(var);
221 :
222 5382335 : if (!EG(active_symbol_table) ||
223 : zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
224 5370559 : switch (type) {
225 : case BP_VAR_R:
226 : case BP_VAR_UNSET:
227 581 : zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
228 : /* break missing intentionally */
229 : case BP_VAR_IS:
230 583 : return &EG(uninitialized_zval_ptr);
231 : break;
232 : case BP_VAR_RW:
233 3 : zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
234 : /* break missing intentionally */
235 : case BP_VAR_W:
236 5369976 : Z_ADDREF(EG(uninitialized_zval));
237 5369976 : if (!EG(active_symbol_table)) {
238 4835106 : *ptr = (zval**)EG(current_execute_data)->CVs + (EG(active_op_array)->last_var + var);
239 4835106 : **ptr = &EG(uninitialized_zval);
240 : } else {
241 534870 : 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);
242 : }
243 : break;
244 : }
245 : }
246 5381752 : return *ptr;
247 : }
248 :
249 : static zend_always_inline zval *_get_zval_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
250 39106047 : {
251 39106047 : zval ***ptr = &CV_OF(node->u.var);
252 :
253 39106047 : if (UNEXPECTED(*ptr == NULL)) {
254 11352 : return *_get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
255 : }
256 39094695 : return **ptr;
257 : }
258 :
259 : static inline zval *_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
260 3177209 : {
261 : /* should_free->is_var = 0; */
262 3177209 : switch (node->op_type) {
263 : case IS_CONST:
264 343326 : should_free->var = 0;
265 343326 : return &node->u.constant;
266 : break;
267 : case IS_TMP_VAR:
268 1161391 : should_free->var = TMP_FREE(&T(node->u.var).tmp_var);
269 1161391 : return &T(node->u.var).tmp_var;
270 : break;
271 : case IS_VAR:
272 120088 : return _get_zval_ptr_var(node, Ts, should_free TSRMLS_CC);
273 : break;
274 : case IS_UNUSED:
275 0 : should_free->var = 0;
276 0 : return NULL;
277 : break;
278 : case IS_CV:
279 1552404 : should_free->var = 0;
280 1552404 : return _get_zval_ptr_cv(node, Ts, type TSRMLS_CC);
281 : break;
282 : EMPTY_SWITCH_DEFAULT_CASE()
283 : }
284 0 : return NULL;
285 : }
286 :
287 : static zend_always_inline zval **_get_zval_ptr_ptr_var(const znode *node, const temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
288 5201429 : {
289 5201429 : zval** ptr_ptr = T(node->u.var).var.ptr_ptr;
290 :
291 5201429 : if (EXPECTED(ptr_ptr != NULL)) {
292 5201315 : PZVAL_UNLOCK(*ptr_ptr, should_free);
293 : } else {
294 : /* string offset */
295 114 : PZVAL_UNLOCK(T(node->u.var).str_offset.str, should_free);
296 : }
297 5201429 : return ptr_ptr;
298 : }
299 :
300 : static zend_always_inline zval **_get_zval_ptr_ptr_cv(const znode *node, const temp_variable *Ts, int type TSRMLS_DC)
301 32667497 : {
302 32667497 : zval ***ptr = &CV_OF(node->u.var);
303 :
304 32667497 : if (UNEXPECTED(*ptr == NULL)) {
305 5370983 : return _get_zval_cv_lookup(ptr, node->u.var, type TSRMLS_CC);
306 : }
307 27296514 : return *ptr;
308 : }
309 :
310 : static inline zval **_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
311 3134141 : {
312 3134141 : if (node->op_type == IS_CV) {
313 3134140 : should_free->var = 0;
314 3134140 : return _get_zval_ptr_ptr_cv(node, Ts, type TSRMLS_CC);
315 1 : } else if (node->op_type == IS_VAR) {
316 1 : return _get_zval_ptr_ptr_var(node, Ts, should_free TSRMLS_CC);
317 : } else {
318 0 : should_free->var = 0;
319 0 : return NULL;
320 : }
321 : }
322 :
323 : static zend_always_inline zval *_get_obj_zval_ptr_unused(TSRMLS_D)
324 31017 : {
325 31017 : if (EXPECTED(EG(This) != NULL)) {
326 31016 : return EG(This);
327 : } else {
328 1 : zend_error_noreturn(E_ERROR, "Using $this when not in object context");
329 : return NULL;
330 : }
331 : }
332 :
333 : static inline zval **_get_obj_zval_ptr_ptr(const znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
334 0 : {
335 0 : if (op->op_type == IS_UNUSED) {
336 0 : if (EXPECTED(EG(This) != NULL)) {
337 : /* this should actually never be modified, _ptr_ptr is modified only when
338 : the object is empty */
339 0 : should_free->var = 0;
340 0 : return &EG(This);
341 : } else {
342 0 : zend_error_noreturn(E_ERROR, "Using $this when not in object context");
343 : }
344 : }
345 0 : return get_zval_ptr_ptr(op, Ts, should_free, type);
346 : }
347 :
348 : static zend_always_inline zval **_get_obj_zval_ptr_ptr_unused(TSRMLS_D)
349 9106 : {
350 9106 : if (EXPECTED(EG(This) != NULL)) {
351 9105 : return &EG(This);
352 : } else {
353 1 : zend_error_noreturn(E_ERROR, "Using $this when not in object context");
354 : return NULL;
355 : }
356 : }
357 :
358 : static inline zval *_get_obj_zval_ptr(znode *op, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC)
359 0 : {
360 0 : if (op->op_type == IS_UNUSED) {
361 0 : if (EXPECTED(EG(This) != NULL)) {
362 0 : should_free->var = 0;
363 0 : return EG(This);
364 : } else {
365 0 : zend_error_noreturn(E_ERROR, "Using $this when not in object context");
366 : }
367 : }
368 0 : return get_zval_ptr(op, Ts, should_free, type);
369 : }
370 :
371 : static inline void zend_switch_free(temp_variable *T, int extended_value TSRMLS_DC)
372 54947 : {
373 54947 : if (T->var.ptr) {
374 54932 : if (extended_value & ZEND_FE_RESET_VARIABLE) { /* foreach() free */
375 54674 : Z_DELREF_P(T->var.ptr);
376 : }
377 54932 : zval_ptr_dtor(&T->var.ptr);
378 15 : } else if (!T->var.ptr_ptr) {
379 : /* perform the equivalent of equivalent of a
380 : * quick & silent get_zval_ptr, and FREE_OP
381 : */
382 15 : PZVAL_UNLOCK_FREE(T->str_offset.str);
383 : }
384 54947 : }
385 :
386 : static void zend_assign_to_variable_reference(zval **variable_ptr_ptr, zval **value_ptr_ptr TSRMLS_DC)
387 591649 : {
388 591649 : zval *variable_ptr = *variable_ptr_ptr;
389 591649 : zval *value_ptr = *value_ptr_ptr;
390 :
391 591660 : if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) {
392 11 : variable_ptr_ptr = &EG(uninitialized_zval_ptr);
393 591638 : } else if (variable_ptr != value_ptr) {
394 580691 : if (!PZVAL_IS_REF(value_ptr)) {
395 : /* break it away */
396 411375 : Z_DELREF_P(value_ptr);
397 411375 : if (Z_REFCOUNT_P(value_ptr)>0) {
398 44 : ALLOC_ZVAL(*value_ptr_ptr);
399 44 : **value_ptr_ptr = *value_ptr;
400 44 : value_ptr = *value_ptr_ptr;
401 44 : zendi_zval_copy_ctor(*value_ptr);
402 : }
403 411375 : Z_SET_REFCOUNT_P(value_ptr, 1);
404 411375 : Z_SET_ISREF_P(value_ptr);
405 : }
406 :
407 580691 : *variable_ptr_ptr = value_ptr;
408 580691 : Z_ADDREF_P(value_ptr);
409 :
410 580691 : zval_ptr_dtor(&variable_ptr);
411 10947 : } else if (!Z_ISREF_P(variable_ptr)) {
412 842 : if (variable_ptr_ptr == value_ptr_ptr) {
413 580 : SEPARATE_ZVAL(variable_ptr_ptr);
414 262 : } else if (variable_ptr==EG(uninitialized_zval_ptr)
415 : || Z_REFCOUNT_P(variable_ptr)>2) {
416 : /* we need to separate */
417 260 : Z_SET_REFCOUNT_P(variable_ptr, Z_REFCOUNT_P(variable_ptr) - 2);
418 260 : ALLOC_ZVAL(*variable_ptr_ptr);
419 260 : **variable_ptr_ptr = *variable_ptr;
420 260 : zval_copy_ctor(*variable_ptr_ptr);
421 260 : *value_ptr_ptr = *variable_ptr_ptr;
422 260 : Z_SET_REFCOUNT_PP(variable_ptr_ptr, 2);
423 : }
424 842 : Z_SET_ISREF_PP(variable_ptr_ptr);
425 : }
426 591649 : }
427 :
428 : /* this should modify object only if it's empty */
429 : static inline void make_real_object(zval **object_ptr TSRMLS_DC)
430 4285 : {
431 4285 : if (Z_TYPE_PP(object_ptr) == IS_NULL
432 : || (Z_TYPE_PP(object_ptr) == IS_BOOL && Z_LVAL_PP(object_ptr) == 0)
433 : || (Z_TYPE_PP(object_ptr) == IS_STRING && Z_STRLEN_PP(object_ptr) == 0)
434 : ) {
435 6 : zend_error(E_STRICT, "Creating default object from empty value");
436 :
437 6 : SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
438 6 : zval_dtor(*object_ptr);
439 6 : object_init(*object_ptr);
440 : }
441 4285 : }
442 :
443 : static inline 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)
444 1304 : {
445 1304 : *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);
446 :
447 1304 : *class_name = (*pce) ? (*pce)->name: cur_arg_info->class_name;
448 1304 : if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
449 586 : return "implement interface ";
450 : } else {
451 718 : return "be an instance of ";
452 : }
453 : }
454 :
455 : static inline int zend_verify_arg_error(const zend_function *zf, zend_uint arg_num, const zend_arg_info *cur_arg_info, const char *need_msg, const char *need_kind, const char *given_msg, char *given_kind TSRMLS_DC)
456 34 : {
457 34 : zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
458 34 : char *fname = zf->common.function_name;
459 : char *fsep;
460 : char *fclass;
461 :
462 34 : if (zf->common.scope) {
463 19 : fsep = "::";
464 19 : fclass = zf->common.scope->name;
465 : } else {
466 15 : fsep = "";
467 15 : fclass = "";
468 : }
469 :
470 36 : if (ptr && ptr->op_array) {
471 18 : zend_error(E_RECOVERABLE_ERROR, "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);
472 : } else {
473 16 : zend_error(E_RECOVERABLE_ERROR, "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);
474 : }
475 12 : return 0;
476 : }
477 :
478 : static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
479 29210697 : {
480 : zend_arg_info *cur_arg_info;
481 : char *need_msg;
482 : zend_class_entry *ce;
483 :
484 29210697 : if (!zf->common.arg_info
485 : || arg_num>zf->common.num_args) {
486 90826 : return 1;
487 : }
488 :
489 29119871 : cur_arg_info = &zf->common.arg_info[arg_num-1];
490 :
491 29119871 : if (cur_arg_info->class_name) {
492 : const char *class_name;
493 :
494 1319 : if (!arg) {
495 2 : need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
496 2 : return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "none", "" TSRMLS_CC);
497 : }
498 1317 : if (Z_TYPE_P(arg) == IS_OBJECT) {
499 1290 : need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
500 1290 : if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
501 12 : return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name TSRMLS_CC);
502 : }
503 27 : } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
504 12 : need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
505 12 : return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
506 : }
507 29118552 : } else if (cur_arg_info->array_type_hint) {
508 374 : if (!arg) {
509 2 : return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", "none", "" TSRMLS_CC);
510 : }
511 372 : if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
512 6 : return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
513 : }
514 : }
515 29119837 : return 1;
516 : }
517 :
518 : static inline void zend_assign_to_object(znode *result, zval **object_ptr, zval *property_name, znode *value_op, const temp_variable *Ts, int opcode TSRMLS_DC)
519 :
520 15617 : {
521 15617 : zval *object = *object_ptr;
522 : zend_free_op free_value;
523 15617 : zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R);
524 15617 : zval **retval = &T(result->u.var).var.ptr;
525 :
526 15617 : if (Z_TYPE_P(object) != IS_OBJECT) {
527 24 : if (object == EG(error_zval_ptr)) {
528 0 : if (!RETURN_VALUE_UNUSED(result)) {
529 0 : *retval = EG(uninitialized_zval_ptr);
530 0 : PZVAL_LOCK(*retval);
531 : }
532 0 : FREE_OP(free_value);
533 0 : return;
534 : }
535 44 : if (Z_TYPE_P(object) == IS_NULL ||
536 : (Z_TYPE_P(object) == IS_BOOL && Z_LVAL_P(object) == 0) ||
537 : (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0)) {
538 20 : SEPARATE_ZVAL_IF_NOT_REF(object_ptr);
539 20 : zval_dtor(*object_ptr);
540 20 : object_init(*object_ptr);
541 20 : object = *object_ptr;
542 20 : zend_error(E_STRICT, "Creating default object from empty value");
543 : } else {
544 4 : zend_error(E_WARNING, "Attempt to assign property of non-object");
545 4 : if (!RETURN_VALUE_UNUSED(result)) {
546 0 : *retval = EG(uninitialized_zval_ptr);
547 0 : PZVAL_LOCK(*retval);
548 : }
549 4 : FREE_OP(free_value);
550 4 : return;
551 : }
552 : }
553 :
554 : /* separate our value if necessary */
555 15613 : if (value_op->op_type == IS_TMP_VAR) {
556 587 : zval *orig_value = value;
557 :
558 587 : ALLOC_ZVAL(value);
559 587 : *value = *orig_value;
560 587 : Z_UNSET_ISREF_P(value);
561 587 : Z_SET_REFCOUNT_P(value, 0);
562 15026 : } else if (value_op->op_type == IS_CONST) {
563 1226 : zval *orig_value = value;
564 :
565 1226 : ALLOC_ZVAL(value);
566 1226 : *value = *orig_value;
567 1226 : Z_UNSET_ISREF_P(value);
568 1226 : Z_SET_REFCOUNT_P(value, 0);
569 1226 : zval_copy_ctor(value);
570 : }
571 :
572 :
573 15613 : Z_ADDREF_P(value);
574 15613 : if (opcode == ZEND_ASSIGN_OBJ) {
575 15089 : if (!Z_OBJ_HT_P(object)->write_property) {
576 0 : zend_error(E_WARNING, "Attempt to assign property of non-object");
577 0 : if (!RETURN_VALUE_UNUSED(result)) {
578 0 : *retval = EG(uninitialized_zval_ptr);
579 0 : PZVAL_LOCK(*retval);
580 : }
581 0 : if (value_op->op_type == IS_TMP_VAR) {
582 0 : FREE_ZVAL(value);
583 0 : } else if (value_op->op_type == IS_CONST) {
584 0 : zval_ptr_dtor(&value);
585 : }
586 0 : FREE_OP(free_value);
587 0 : return;
588 : }
589 15089 : Z_OBJ_HT_P(object)->write_property(object, property_name, value TSRMLS_CC);
590 : } else {
591 : /* Note: property_name in this case is really the array index! */
592 524 : if (!Z_OBJ_HT_P(object)->write_dimension) {
593 0 : zend_error_noreturn(E_ERROR, "Cannot use object as array");
594 : }
595 524 : Z_OBJ_HT_P(object)->write_dimension(object, property_name, value TSRMLS_CC);
596 : }
597 :
598 15605 : if (!RETURN_VALUE_UNUSED(result) && !EG(exception)) {
599 29 : AI_SET_PTR(T(result->u.var).var, value);
600 29 : PZVAL_LOCK(value);
601 : }
602 15605 : zval_ptr_dtor(&value);
603 15605 : FREE_OP_IF_VAR(free_value);
604 : }
605 :
606 : static inline int zend_assign_to_string_offset(const temp_variable *T, const zval *value, int value_type TSRMLS_DC)
607 107 : {
608 107 : if (Z_TYPE_P(T->str_offset.str) == IS_STRING) {
609 :
610 107 : if (((int)T->str_offset.offset < 0)) {
611 1 : zend_error(E_WARNING, "Illegal string offset: %d", T->str_offset.offset);
612 1 : return 0;
613 : }
614 :
615 106 : if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) {
616 3 : Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1);
617 3 : memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str),
618 : ' ',
619 : T->str_offset.offset - Z_STRLEN_P(T->str_offset.str));
620 3 : Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0;
621 3 : Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1;
622 : }
623 :
624 106 : if (Z_TYPE_P(value) != IS_STRING) {
625 11 : zval tmp = *value;
626 :
627 11 : if (value_type != IS_TMP_VAR) {
628 8 : zval_copy_ctor(&tmp);
629 : }
630 11 : convert_to_string(&tmp);
631 11 : Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL(tmp)[0];
632 11 : STR_FREE(Z_STRVAL(tmp));
633 : } else {
634 95 : Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset] = Z_STRVAL_P(value)[0];
635 95 : if (value_type == IS_TMP_VAR) {
636 : /* we can safely free final_value here
637 : * because separation is done only
638 : * in case value_type == IS_VAR */
639 10 : STR_FREE(Z_STRVAL_P(value));
640 : }
641 : }
642 : /*
643 : * the value of an assignment to a string offset is undefined
644 : T(result->u.var).var = &T->str_offset.str;
645 : */
646 : }
647 106 : return 1;
648 : }
649 :
650 : static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value, int is_tmp_var TSRMLS_DC)
651 15266854 : {
652 15266854 : zval *variable_ptr = *variable_ptr_ptr;
653 : zval garbage;
654 :
655 15266854 : if (variable_ptr == EG(error_zval_ptr)) {
656 14 : if (is_tmp_var) {
657 0 : zval_dtor(value);
658 : }
659 14 : return EG(uninitialized_zval_ptr);
660 : }
661 :
662 15266840 : if (Z_TYPE_P(variable_ptr) == IS_OBJECT && Z_OBJ_HANDLER_P(variable_ptr, set)) {
663 0 : Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC);
664 0 : return variable_ptr;
665 : }
666 :
667 15266840 : if (PZVAL_IS_REF(variable_ptr)) {
668 14690 : if (variable_ptr!=value) {
669 14689 : zend_uint refcount = Z_REFCOUNT_P(variable_ptr);
670 :
671 14689 : garbage = *variable_ptr;
672 14689 : *variable_ptr = *value;
673 14689 : Z_SET_REFCOUNT_P(variable_ptr, refcount);
674 14689 : Z_SET_ISREF_P(variable_ptr);
675 14689 : if (!is_tmp_var) {
676 14371 : zendi_zval_copy_ctor(*variable_ptr);
677 : }
678 14689 : zendi_zval_dtor(garbage);
679 14688 : return variable_ptr;
680 : }
681 : } else {
682 15252150 : if (Z_DELREF_P(variable_ptr)==0) {
683 8801919 : if (!is_tmp_var) {
684 6649106 : if (variable_ptr==value) {
685 153 : Z_ADDREF_P(variable_ptr);
686 6648953 : } else if (PZVAL_IS_REF(value)) {
687 1698848 : garbage = *variable_ptr;
688 1698848 : *variable_ptr = *value;
689 1698848 : INIT_PZVAL(variable_ptr);
690 1698848 : zval_copy_ctor(variable_ptr);
691 1698848 : zendi_zval_dtor(garbage);
692 1698845 : return variable_ptr;
693 : } else {
694 4950105 : Z_ADDREF_P(value);
695 4950105 : *variable_ptr_ptr = value;
696 4950105 : if (variable_ptr != &EG(uninitialized_zval)) {
697 4950105 : GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr);
698 4950105 : zval_dtor(variable_ptr);
699 4950105 : efree(variable_ptr);
700 : }
701 4950105 : return value;
702 : }
703 : } else {
704 2152813 : garbage = *variable_ptr;
705 2152813 : *variable_ptr = *value;
706 2152813 : INIT_PZVAL(variable_ptr);
707 2152813 : zendi_zval_dtor(garbage);
708 2152813 : return variable_ptr;
709 : }
710 : } else { /* we need to split */
711 6450231 : if (!is_tmp_var) {
712 5138347 : if (PZVAL_IS_REF(value) && Z_REFCOUNT_P(value) > 0) {
713 649641 : ALLOC_ZVAL(variable_ptr);
714 649641 : *variable_ptr_ptr = variable_ptr;
715 649641 : *variable_ptr = *value;
716 649641 : zval_copy_ctor(variable_ptr);
717 649641 : Z_SET_REFCOUNT_P(variable_ptr, 1);
718 : } else {
719 3839065 : *variable_ptr_ptr = value;
720 3839065 : Z_ADDREF_P(value);
721 : }
722 : } else {
723 1961525 : ALLOC_ZVAL(*variable_ptr_ptr);
724 1961525 : Z_SET_REFCOUNT_P(value, 1);
725 1961525 : **variable_ptr_ptr = *value;
726 : }
727 : }
728 6450384 : Z_UNSET_ISREF_PP(variable_ptr_ptr);
729 : }
730 :
731 6450385 : return *variable_ptr_ptr;
732 : }
733 :
734 :
735 : /* Utility Functions for Extensions */
736 : static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
737 0 : {
738 0 : if (extension->statement_handler) {
739 0 : extension->statement_handler(op_array);
740 : }
741 0 : }
742 :
743 :
744 : static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
745 0 : {
746 0 : if (extension->fcall_begin_handler) {
747 0 : extension->fcall_begin_handler(op_array);
748 : }
749 0 : }
750 :
751 :
752 : static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC)
753 0 : {
754 0 : if (extension->fcall_end_handler) {
755 0 : extension->fcall_end_handler(op_array);
756 : }
757 0 : }
758 :
759 :
760 : static inline HashTable *zend_get_target_symbol_table(const zend_op *opline, const temp_variable *Ts, int type, const zval *variable TSRMLS_DC)
761 1561874 : {
762 1561874 : switch (opline->op2.u.EA.type) {
763 : case ZEND_FETCH_LOCAL:
764 1005697 : if (!EG(active_symbol_table)) {
765 29612 : zend_rebuild_symbol_table(TSRMLS_C);
766 : }
767 1005697 : return EG(active_symbol_table);
768 : break;
769 : case ZEND_FETCH_GLOBAL:
770 : case ZEND_FETCH_GLOBAL_LOCK:
771 554879 : return &EG(symbol_table);
772 : break;
773 : case ZEND_FETCH_STATIC:
774 1298 : if (!EG(active_op_array)->static_variables) {
775 0 : ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
776 0 : zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
777 : }
778 1298 : return EG(active_op_array)->static_variables;
779 : break;
780 : EMPTY_SWITCH_DEFAULT_CASE()
781 : }
782 0 : return NULL;
783 : }
784 :
785 : static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int type TSRMLS_DC)
786 6135282 : {
787 : zval **retval;
788 : char *offset_key;
789 : int offset_key_length;
790 : long index;
791 :
792 6135282 : switch (dim->type) {
793 : case IS_NULL:
794 10 : offset_key = "";
795 10 : offset_key_length = 0;
796 10 : goto fetch_string_dim;
797 :
798 : case IS_STRING:
799 :
800 3312248 : offset_key = dim->value.str.val;
801 3312248 : offset_key_length = dim->value.str.len;
802 :
803 3312258 : fetch_string_dim:
804 3312258 : if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
805 1574795 : switch (type) {
806 : case BP_VAR_R:
807 99692 : zend_error(E_NOTICE, "Undefined index: %s", offset_key);
808 : /* break missing intentionally */
809 : case BP_VAR_UNSET:
810 : case BP_VAR_IS:
811 99692 : retval = &EG(uninitialized_zval_ptr);
812 99692 : break;
813 : case BP_VAR_RW:
814 1 : zend_error(E_NOTICE,"Undefined index: %s", offset_key);
815 : /* break missing intentionally */
816 : case BP_VAR_W: {
817 1475103 : zval *new_zval = &EG(uninitialized_zval);
818 :
819 1475103 : Z_ADDREF_P(new_zval);
820 1475103 : zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval, sizeof(zval *), (void **) &retval);
821 : }
822 : break;
823 : }
824 : }
825 3312258 : break;
826 : case IS_DOUBLE:
827 51 : index = zend_dval_to_lval(Z_DVAL_P(dim));
828 51 : goto num_index;
829 : case IS_RESOURCE:
830 3 : zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim));
831 : /* Fall Through */
832 : case IS_BOOL:
833 : case IS_LONG:
834 2822967 : index = Z_LVAL_P(dim);
835 2823018 : num_index:
836 2823018 : if (zend_hash_index_find(ht, index, (void **) &retval) == FAILURE) {
837 249381 : switch (type) {
838 : case BP_VAR_R:
839 11 : zend_error(E_NOTICE,"Undefined offset: %ld", index);
840 : /* break missing intentionally */
841 : case BP_VAR_UNSET:
842 : case BP_VAR_IS:
843 12 : retval = &EG(uninitialized_zval_ptr);
844 12 : break;
845 : case BP_VAR_RW:
846 0 : zend_error(E_NOTICE,"Undefined offset: %ld", index);
847 : /* break missing intentionally */
848 : case BP_VAR_W: {
849 249369 : zval *new_zval = &EG(uninitialized_zval);
850 :
851 249369 : Z_ADDREF_P(new_zval);
852 249369 : zend_hash_index_update(ht, index, &new_zval, sizeof(zval *), (void **) &retval);
853 : }
854 : break;
855 : }
856 : }
857 2823018 : break;
858 :
859 : default:
860 6 : zend_error(E_WARNING, "Illegal offset type");
861 6 : return (type == BP_VAR_W || type == BP_VAR_RW) ?
862 : &EG(error_zval_ptr) : &EG(uninitialized_zval_ptr);
863 : }
864 6135276 : return retval;
865 : }
866 :
867 : static void zend_fetch_dimension_address(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
868 3438321 : {
869 3438321 : zval *container = *container_ptr;
870 : zval **retval;
871 :
872 3438321 : switch (Z_TYPE_P(container)) {
873 :
874 : case IS_ARRAY:
875 3437091 : if (type != BP_VAR_UNSET && Z_REFCOUNT_P(container)>1 && !PZVAL_IS_REF(container)) {
876 11402 : SEPARATE_ZVAL(container_ptr);
877 11402 : container = *container_ptr;
878 : }
879 3438145 : fetch_from_array:
880 3438145 : if (dim == NULL) {
881 256035 : zval *new_zval = &EG(uninitialized_zval);
882 :
883 256035 : Z_ADDREF_P(new_zval);
884 256035 : if (zend_hash_next_index_insert(Z_ARRVAL_P(container), &new_zval, sizeof(zval *), (void **) &retval) == FAILURE) {
885 1 : zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
886 1 : retval = &EG(error_zval_ptr);
887 1 : Z_DELREF_P(new_zval);
888 : }
889 : } else {
890 3182110 : retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
891 : }
892 3438145 : result->var.ptr_ptr = retval;
893 3438145 : PZVAL_LOCK(*retval);
894 3438145 : return;
895 : break;
896 :
897 : case IS_NULL:
898 1047 : if (container == EG(error_zval_ptr)) {
899 1 : result->var.ptr_ptr = &EG(error_zval_ptr);
900 1 : PZVAL_LOCK(EG(error_zval_ptr));
901 1046 : } else if (type != BP_VAR_UNSET) {
902 1054 : convert_to_array:
903 1054 : if (!PZVAL_IS_REF(container)) {
904 1053 : SEPARATE_ZVAL(container_ptr);
905 1053 : container = *container_ptr;
906 : }
907 1054 : zval_dtor(container);
908 1054 : array_init(container);
909 1054 : goto fetch_from_array;
910 : } else {
911 : /* for read-mode only */
912 0 : result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
913 0 : PZVAL_LOCK(EG(uninitialized_zval_ptr));
914 : }
915 1 : return;
916 : break;
917 :
918 : case IS_STRING: {
919 : zval tmp;
920 :
921 116 : if (type != BP_VAR_UNSET && Z_STRLEN_P(container)==0) {
922 4 : goto convert_to_array;
923 : }
924 112 : if (dim == NULL) {
925 0 : zend_error_noreturn(E_ERROR, "[] operator not supported for strings");
926 : }
927 :
928 112 : if (Z_TYPE_P(dim) != IS_LONG) {
929 15 : switch(Z_TYPE_P(dim)) {
930 : /* case IS_LONG: */
931 : case IS_STRING:
932 : case IS_DOUBLE:
933 : case IS_NULL:
934 : case IS_BOOL:
935 : /* do nothing */
936 15 : break;
937 : default:
938 0 : zend_error(E_WARNING, "Illegal offset type");
939 : break;
940 : }
941 :
942 15 : tmp = *dim;
943 15 : zval_copy_ctor(&tmp);
944 15 : convert_to_long(&tmp);
945 15 : dim = &tmp;
946 : }
947 112 : if (type != BP_VAR_UNSET) {
948 111 : SEPARATE_ZVAL_IF_NOT_REF(container_ptr);
949 : }
950 112 : container = *container_ptr;
951 112 : result->str_offset.str = container;
952 112 : PZVAL_LOCK(container);
953 112 : result->str_offset.offset = Z_LVAL_P(dim);
954 112 : result->var.ptr_ptr = NULL;
955 112 : result->var.ptr = NULL;
956 112 : return;
957 : }
958 : break;
959 :
960 : case IS_OBJECT:
961 45 : if (!Z_OBJ_HT_P(container)->read_dimension) {
962 0 : zend_error_noreturn(E_ERROR, "Cannot use object as array");
963 : } else {
964 : zval *overloaded_result;
965 :
966 45 : if (dim_is_tmp_var) {
967 0 : zval *orig = dim;
968 0 : MAKE_REAL_ZVAL_PTR(dim);
969 0 : ZVAL_NULL(orig);
970 : }
971 45 : overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
972 :
973 45 : if (overloaded_result) {
974 42 : if (!Z_ISREF_P(overloaded_result)) {
975 39 : if (Z_REFCOUNT_P(overloaded_result) > 0) {
976 8 : zval *tmp = overloaded_result;
977 :
978 8 : ALLOC_ZVAL(overloaded_result);
979 8 : *overloaded_result = *tmp;
980 8 : zval_copy_ctor(overloaded_result);
981 8 : Z_UNSET_ISREF_P(overloaded_result);
982 8 : Z_SET_REFCOUNT_P(overloaded_result, 0);
983 : }
984 39 : if (Z_TYPE_P(overloaded_result) != IS_OBJECT) {
985 8 : zend_class_entry *ce = Z_OBJCE_P(container);
986 8 : zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ce->name);
987 : }
988 : }
989 42 : retval = &overloaded_result;
990 : } else {
991 3 : retval = &EG(error_zval_ptr);
992 : }
993 45 : AI_SET_PTR(result->var, *retval);
994 45 : PZVAL_LOCK(*retval);
995 45 : if (dim_is_tmp_var) {
996 0 : zval_ptr_dtor(&dim);
997 : }
998 : }
999 45 : return;
1000 : break;
1001 :
1002 : case IS_BOOL:
1003 8 : if (type != BP_VAR_UNSET && Z_LVAL_P(container)==0) {
1004 4 : goto convert_to_array;
1005 : }
1006 : /* break missing intentionally */
1007 :
1008 : default:
1009 18 : if (type == BP_VAR_UNSET) {
1010 0 : zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1011 0 : AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
1012 0 : PZVAL_LOCK(EG(uninitialized_zval_ptr));
1013 : } else {
1014 18 : zend_error(E_WARNING, "Cannot use a scalar value as an array");
1015 18 : result->var.ptr_ptr = &EG(error_zval_ptr);
1016 18 : PZVAL_LOCK(EG(error_zval_ptr));
1017 : }
1018 : break;
1019 : }
1020 : }
1021 :
1022 : static void zend_fetch_dimension_address_read(temp_variable *result, zval **container_ptr, zval *dim, int dim_is_tmp_var, int type TSRMLS_DC)
1023 2959589 : {
1024 2959589 : zval *container = *container_ptr;
1025 : zval **retval;
1026 :
1027 2959589 : switch (Z_TYPE_P(container)) {
1028 :
1029 : case IS_ARRAY:
1030 2953151 : retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, type TSRMLS_CC);
1031 2953151 : if (result) {
1032 2953151 : AI_SET_PTR(result->var, *retval);
1033 2953151 : PZVAL_LOCK(*retval);
1034 : }
1035 2953151 : return;
1036 : break;
1037 :
1038 : case IS_NULL:
1039 58 : if (result) {
1040 57 : AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
1041 57 : PZVAL_LOCK(EG(uninitialized_zval_ptr));
1042 : }
1043 58 : return;
1044 : break;
1045 :
1046 : case IS_STRING: {
1047 : zval tmp;
1048 :
1049 5570 : if (Z_TYPE_P(dim) != IS_LONG) {
1050 31 : switch(Z_TYPE_P(dim)) {
1051 : /* case IS_LONG: */
1052 : case IS_STRING:
1053 : case IS_DOUBLE:
1054 : case IS_NULL:
1055 : case IS_BOOL:
1056 : /* do nothing */
1057 28 : break;
1058 : default:
1059 3 : zend_error(E_WARNING, "Illegal offset type");
1060 : break;
1061 : }
1062 :
1063 31 : tmp = *dim;
1064 31 : zval_copy_ctor(&tmp);
1065 31 : convert_to_long(&tmp);
1066 31 : dim = &tmp;
1067 : }
1068 5570 : if (result) {
1069 5563 : if (Z_LVAL_P(dim) < 0 || Z_STRLEN_P(container) <= Z_LVAL_P(dim)) {
1070 19 : zend_error(E_NOTICE, "Uninitialized string offset: %ld", Z_LVAL_P(dim));
1071 : }
1072 5563 : result->str_offset.str = container;
1073 5563 : PZVAL_LOCK(container);
1074 5563 : result->str_offset.offset = Z_LVAL_P(dim);
1075 5563 : result->var.ptr_ptr = NULL;
1076 5563 : result->var.ptr = NULL;
1077 : }
1078 5570 : return;
1079 : }
1080 : break;
1081 :
1082 : case IS_OBJECT:
1083 710 : if (!Z_OBJ_HT_P(container)->read_dimension) {
1084 0 : zend_error_noreturn(E_ERROR, "Cannot use object as array");
1085 : } else {
1086 : zval *overloaded_result;
1087 :
1088 710 : if (dim_is_tmp_var) {
1089 6 : zval *orig = dim;
1090 6 : MAKE_REAL_ZVAL_PTR(dim);
1091 6 : ZVAL_NULL(orig);
1092 : }
1093 710 : overloaded_result = Z_OBJ_HT_P(container)->read_dimension(container, dim, type TSRMLS_CC);
1094 :
1095 707 : if (overloaded_result) {
1096 699 : if (result) {
1097 697 : AI_SET_PTR(result->var, overloaded_result);
1098 697 : PZVAL_LOCK(overloaded_result);
1099 2 : } else if (Z_REFCOUNT_P(overloaded_result) == 0) {
1100 : /* Destroy unused result from offsetGet() magic method */
1101 2 : Z_SET_REFCOUNT_P(overloaded_result, 1);
1102 2 : zval_ptr_dtor(&overloaded_result);
1103 : }
1104 8 : } else if (result) {
1105 7 : AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
1106 7 : PZVAL_LOCK(EG(uninitialized_zval_ptr));
1107 : }
1108 707 : if (dim_is_tmp_var) {
1109 6 : zval_ptr_dtor(&dim);
1110 : }
1111 : }
1112 707 : return;
1113 : break;
1114 :
1115 : default:
1116 100 : if (result) {
1117 100 : AI_SET_PTR(result->var, EG(uninitialized_zval_ptr));
1118 100 : PZVAL_LOCK(EG(uninitialized_zval_ptr));
1119 : }
1120 100 : return;
1121 : break;
1122 : }
1123 : }
1124 :
1125 : static void zend_fetch_property_address(temp_variable *result, zval **container_ptr, zval *prop_ptr, int type TSRMLS_DC)
1126 709 : {
1127 709 : zval *container = *container_ptr;;
1128 :
1129 709 : if (Z_TYPE_P(container) != IS_OBJECT) {
1130 39 : if (container == EG(error_zval_ptr)) {
1131 1 : result->var.ptr_ptr = &EG(error_zval_ptr);
1132 1 : PZVAL_LOCK(*result->var.ptr_ptr);
1133 1 : return;
1134 : }
1135 :
1136 : /* this should modify object only if it's empty */
1137 72 : if (type != BP_VAR_UNSET &&
1138 : ((Z_TYPE_P(container) == IS_NULL ||
1139 : (Z_TYPE_P(container) == IS_BOOL && Z_LVAL_P(container)==0) ||
1140 : (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0)))) {
1141 34 : if (!PZVAL_IS_REF(container)) {
1142 32 : SEPARATE_ZVAL(container_ptr);
1143 32 : container = *container_ptr;
1144 : }
1145 34 : object_init(container);
1146 : } else {
1147 4 : zend_error(E_WARNING, "Attempt to modify property of non-object");
1148 4 : result->var.ptr_ptr = &EG(error_zval_ptr);
1149 4 : PZVAL_LOCK(EG(error_zval_ptr));
1150 4 : return;
1151 : }
1152 : }
1153 :
1154 704 : if (Z_OBJ_HT_P(container)->get_property_ptr_ptr) {
1155 704 : zval **ptr_ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr TSRMLS_CC);
1156 703 : if (NULL == ptr_ptr) {
1157 : zval *ptr;
1158 :
1159 54 : if (Z_OBJ_HT_P(container)->read_property &&
1160 : (ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC)) != NULL) {
1161 54 : AI_SET_PTR(result->var, ptr);
1162 54 : PZVAL_LOCK(ptr);
1163 : } else {
1164 0 : zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access");
1165 : }
1166 : } else {
1167 649 : result->var.ptr_ptr = ptr_ptr;
1168 649 : PZVAL_LOCK(*ptr_ptr);
1169 : }
1170 0 : } else if (Z_OBJ_HT_P(container)->read_property) {
1171 0 : zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC);
1172 :
1173 0 : AI_SET_PTR(result->var, ptr);
1174 0 : PZVAL_LOCK(ptr);
1175 : } else {
1176 0 : zend_error(E_WARNING, "This object doesn't support property references");
1177 0 : result->var.ptr_ptr = &EG(error_zval_ptr);
1178 0 : PZVAL_LOCK(EG(error_zval_ptr));
1179 : }
1180 : }
1181 :
1182 : static inline zend_brk_cont_element* zend_brk_cont(const zval *nest_levels_zval, int array_offset, const zend_op_array *op_array, const temp_variable *Ts TSRMLS_DC)
1183 55354 : {
1184 : zval tmp;
1185 : int nest_levels, original_nest_levels;
1186 : zend_brk_cont_element *jmp_to;
1187 :
1188 55354 : if (nest_levels_zval->type != IS_LONG) {
1189 0 : tmp = *nest_levels_zval;
1190 0 : zval_copy_ctor(&tmp);
1191 0 : convert_to_long(&tmp);
1192 0 : nest_levels = tmp.value.lval;
1193 : } else {
1194 55354 : nest_levels = nest_levels_zval->value.lval;
1195 : }
1196 55354 : original_nest_levels = nest_levels;
1197 : do {
1198 55511 : if (array_offset==-1) {
1199 0 : zend_error_noreturn(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s");
1200 : }
1201 55511 : jmp_to = &op_array->brk_cont_array[array_offset];
1202 55511 : if (nest_levels>1) {
1203 157 : zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
1204 :
1205 157 : switch (brk_opline->opcode) {
1206 : case ZEND_SWITCH_FREE:
1207 2 : if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
1208 0 : zend_switch_free(&T(brk_opline->op1.u.var), brk_opline->extended_value TSRMLS_CC);
1209 : }
1210 2 : break;
1211 : case ZEND_FREE:
1212 0 : if (brk_opline->op1.u.EA.type != EXT_TYPE_FREE_ON_RETURN) {
1213 0 : zendi_zval_dtor(T(brk_opline->op1.u.var).tmp_var);
1214 : }
1215 : break;
1216 : }
1217 : }
1218 55511 : array_offset = jmp_to->parent;
1219 55511 : } while (--nest_levels > 0);
1220 55354 : return jmp_to;
1221 : }
1222 :
1223 : #if ZEND_INTENSIVE_DEBUGGING
1224 :
1225 : #define CHECK_SYMBOL_TABLES() \
1226 : zend_hash_apply(&EG(symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC); \
1227 : if (&EG(symbol_table)!=EG(active_symbol_table)) { \
1228 : zend_hash_apply(EG(active_symbol_table), (apply_func_t) zend_check_symbol TSRMLS_CC); \
1229 : }
1230 :
1231 : static int zend_check_symbol(zval **pz TSRMLS_DC)
1232 : {
1233 : if (Z_TYPE_PP(pz) > 9) {
1234 : fprintf(stderr, "Warning! %x has invalid type!\n", *pz);
1235 : } else if (Z_TYPE_PP(pz) == IS_ARRAY) {
1236 : zend_hash_apply(Z_ARRVAL_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
1237 : } else if (Z_TYPE_PP(pz) == IS_OBJECT) {
1238 :
1239 : /* OBJ-TBI - doesn't support new object model! */
1240 : zend_hash_apply(Z_OBJPROP_PP(pz), (apply_func_t) zend_check_symbol TSRMLS_CC);
1241 : }
1242 :
1243 : return 0;
1244 : }
1245 :
1246 :
1247 : #else
1248 : #define CHECK_SYMBOL_TABLES()
1249 : #endif
1250 :
1251 : ZEND_API opcode_handler_t *zend_opcode_handlers;
1252 :
1253 : ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
1254 0 : {
1255 0 : zval **return_value_ptr = &(*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr;
1256 0 : ((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.return_reference?return_value_ptr:NULL, execute_data_ptr->object, return_value_used TSRMLS_CC);
1257 0 : }
1258 :
1259 : #define ZEND_VM_NEXT_OPCODE() \
1260 : CHECK_SYMBOL_TABLES() \
1261 : EX(opline)++; \
1262 : ZEND_VM_CONTINUE()
1263 :
1264 : #define ZEND_VM_SET_OPCODE(new_op) \
1265 : CHECK_SYMBOL_TABLES() \
1266 : EX(opline) = new_op
1267 :
1268 : #define ZEND_VM_JMP(new_op) \
1269 : CHECK_SYMBOL_TABLES() \
1270 : if (EXPECTED(!EG(exception))) { \
1271 : EX(opline) = new_op; \
1272 : } \
1273 : ZEND_VM_CONTINUE()
1274 :
1275 : #define ZEND_VM_INC_OPCODE() \
1276 : EX(opline)++
1277 :
1278 : #include "zend_vm_execute.h"
1279 :
1280 : ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
1281 0 : {
1282 0 : if (opcode != ZEND_USER_OPCODE) {
1283 0 : zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
1284 0 : zend_user_opcode_handlers[opcode] = handler;
1285 0 : return SUCCESS;
1286 : }
1287 0 : return FAILURE;
1288 : }
1289 :
1290 : ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
1291 0 : {
1292 0 : return zend_user_opcode_handlers[opcode];
1293 : }
1294 :
1295 0 : ZEND_API zval *zend_get_zval_ptr(znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
1296 0 : return get_zval_ptr(node, Ts, should_free, type);
1297 : }
1298 :
1299 0 : ZEND_API zval **zend_get_zval_ptr_ptr(const znode *node, const temp_variable *Ts, zend_free_op *should_free, int type TSRMLS_DC) {
1300 0 : return get_zval_ptr_ptr(node, Ts, should_free, type);
1301 : }
1302 :
1303 : /*
1304 : * Local variables:
1305 : * tab-width: 4
1306 : * c-basic-offset: 4
1307 : * indent-tabs-mode: t
1308 : * End:
1309 : */
|