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