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