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