1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2018 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 | Dmitry Stogov <dmitry@zend.com> |
18 +----------------------------------------------------------------------+
19 */
20
21 /* $Id$ */
22
23 #define ZEND_INTENSIVE_DEBUGGING 0
24
25 #include <stdio.h>
26 #include <signal.h>
27
28 #include "zend.h"
29 #include "zend_compile.h"
30 #include "zend_execute.h"
31 #include "zend_API.h"
32 #include "zend_ptr_stack.h"
33 #include "zend_constants.h"
34 #include "zend_extensions.h"
35 #include "zend_ini.h"
36 #include "zend_exceptions.h"
37 #include "zend_interfaces.h"
38 #include "zend_closures.h"
39 #include "zend_generators.h"
40 #include "zend_vm.h"
41 #include "zend_dtrace.h"
42 #include "zend_inheritance.h"
43 #include "zend_type_info.h"
44
45 /* Virtual current working directory support */
46 #include "zend_virtual_cwd.h"
47
48 #ifdef HAVE_GCC_GLOBAL_REGS
49 # if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
50 # define ZEND_VM_FP_GLOBAL_REG "%esi"
51 # define ZEND_VM_IP_GLOBAL_REG "%edi"
52 # elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
53 # define ZEND_VM_FP_GLOBAL_REG "%r14"
54 # define ZEND_VM_IP_GLOBAL_REG "%r15"
55 # elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
56 # define ZEND_VM_FP_GLOBAL_REG "r28"
57 # define ZEND_VM_IP_GLOBAL_REG "r29"
58 # elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
59 # define ZEND_VM_FP_GLOBAL_REG "r28"
60 # define ZEND_VM_IP_GLOBAL_REG "r29"
61 # endif
62 #endif
63
64 #if defined(ZEND_VM_FP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
65 # pragma GCC diagnostic ignored "-Wvolatile-register-var"
66 register zend_execute_data* volatile execute_data __asm__(ZEND_VM_FP_GLOBAL_REG);
67 # pragma GCC diagnostic warning "-Wvolatile-register-var"
68 # define EXECUTE_DATA_D void
69 # define EXECUTE_DATA_C
70 # define EXECUTE_DATA_DC
71 # define EXECUTE_DATA_CC
72 # define NO_EXECUTE_DATA_CC
73 #else
74 # define EXECUTE_DATA_D zend_execute_data* execute_data
75 # define EXECUTE_DATA_C execute_data
76 # define EXECUTE_DATA_DC , EXECUTE_DATA_D
77 # define EXECUTE_DATA_CC , EXECUTE_DATA_C
78 # define NO_EXECUTE_DATA_CC , NULL
79 #endif
80
81 #if defined(ZEND_VM_IP_GLOBAL_REG) && ((ZEND_VM_KIND == ZEND_VM_KIND_CALL) || (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID))
82 # pragma GCC diagnostic ignored "-Wvolatile-register-var"
83 register const zend_op* volatile opline __asm__(ZEND_VM_IP_GLOBAL_REG);
84 # pragma GCC diagnostic warning "-Wvolatile-register-var"
85 #else
86 #endif
87
88 #define _CONST_CODE 0
89 #define _TMP_CODE 1
90 #define _VAR_CODE 2
91 #define _UNUSED_CODE 3
92 #define _CV_CODE 4
93
94 typedef int (ZEND_FASTCALL *incdec_t)(zval *);
95
96 #define get_zval_ptr(op_type, node, should_free, type) _get_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
97 #define get_zval_ptr_deref(op_type, node, should_free, type) _get_zval_ptr_deref(op_type, node, should_free, type EXECUTE_DATA_CC)
98 #define get_zval_ptr_r(op_type, node, should_free) _get_zval_ptr_r(op_type, node, should_free EXECUTE_DATA_CC)
99 #define get_zval_ptr_r_deref(op_type, node, should_free) _get_zval_ptr_r_deref(op_type, node, should_free EXECUTE_DATA_CC)
100 #define get_zval_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC)
101 #define get_zval_ptr_ptr(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
102 #define get_zval_ptr_ptr_undef(op_type, node, should_free, type) _get_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
103 #define get_obj_zval_ptr(op_type, node, should_free, type) _get_obj_zval_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
104 #define get_obj_zval_ptr_undef(op_type, node, should_free, type) _get_obj_zval_ptr_undef(op_type, node, should_free, type EXECUTE_DATA_CC)
105 #define get_obj_zval_ptr_ptr(op_type, node, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, should_free, type EXECUTE_DATA_CC)
106
107 #define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED)
108
ZEND_FUNCTION(pass)109 static ZEND_FUNCTION(pass)
110 {
111 }
112
113 ZEND_API const zend_internal_function zend_pass_function = {
114 ZEND_INTERNAL_FUNCTION, /* type */
115 {0, 0, 0}, /* arg_flags */
116 0, /* fn_flags */
117 NULL, /* name */
118 NULL, /* scope */
119 NULL, /* prototype */
120 0, /* num_args */
121 0, /* required_num_args */
122 NULL, /* arg_info */
123 ZEND_FN(pass), /* handler */
124 NULL, /* module */
125 {NULL,NULL,NULL,NULL} /* reserved */
126 };
127
128 #undef zval_ptr_dtor
129 #define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC)
130
131 #define READY_TO_DESTROY(zv) \
132 (UNEXPECTED(zv) && Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
133
134 #define EXTRACT_ZVAL_PTR(zv) do { \
135 zval *__zv = (zv); \
136 if (EXPECTED(Z_TYPE_P(__zv) == IS_INDIRECT)) { \
137 ZVAL_COPY(__zv, Z_INDIRECT_P(__zv)); \
138 } \
139 } while (0)
140
141 #define FREE_OP(should_free) \
142 if (should_free) { \
143 zval_ptr_dtor_nogc(should_free); \
144 }
145
146 #define FREE_UNFETCHED_OP(type, var) \
147 if ((type) & (IS_TMP_VAR|IS_VAR)) { \
148 zval_ptr_dtor_nogc(EX_VAR(var)); \
149 }
150
151 #define FREE_OP_VAR_PTR(should_free) \
152 if (should_free) { \
153 zval_ptr_dtor_nogc(should_free); \
154 }
155
156 #define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
157
158 #define ZEND_VM_STACK_PAGE_SLOTS (16 * 1024) /* should be a power of 2 */
159
160 #define ZEND_VM_STACK_PAGE_SIZE (ZEND_VM_STACK_PAGE_SLOTS * sizeof(zval))
161
162 #define ZEND_VM_STACK_FREE_PAGE_SIZE \
163 ((ZEND_VM_STACK_PAGE_SLOTS - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
164
165 #define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size) \
166 (((size) + ZEND_VM_STACK_HEADER_SLOTS * sizeof(zval) \
167 + (ZEND_VM_STACK_PAGE_SIZE - 1)) & ~(ZEND_VM_STACK_PAGE_SIZE - 1))
168
zend_vm_stack_new_page(size_t size,zend_vm_stack prev)169 static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
170 zend_vm_stack page = (zend_vm_stack)emalloc(size);
171
172 page->top = ZEND_VM_STACK_ELEMENTS(page);
173 page->end = (zval*)((char*)page + size);
174 page->prev = prev;
175 return page;
176 }
177
zend_vm_stack_init(void)178 ZEND_API void zend_vm_stack_init(void)
179 {
180 EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE, NULL);
181 EG(vm_stack)->top++;
182 EG(vm_stack_top) = EG(vm_stack)->top;
183 EG(vm_stack_end) = EG(vm_stack)->end;
184 }
185
zend_vm_stack_destroy(void)186 ZEND_API void zend_vm_stack_destroy(void)
187 {
188 zend_vm_stack stack = EG(vm_stack);
189
190 while (stack != NULL) {
191 zend_vm_stack p = stack->prev;
192 efree(stack);
193 stack = p;
194 }
195 }
196
zend_vm_stack_extend(size_t size)197 ZEND_API void* zend_vm_stack_extend(size_t size)
198 {
199 zend_vm_stack stack;
200 void *ptr;
201
202 stack = EG(vm_stack);
203 stack->top = EG(vm_stack_top);
204 EG(vm_stack) = stack = zend_vm_stack_new_page(
205 EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE) ?
206 ZEND_VM_STACK_PAGE_SIZE : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(size),
207 stack);
208 ptr = stack->top;
209 EG(vm_stack_top) = (void*)(((char*)ptr) + size);
210 EG(vm_stack_end) = stack->end;
211 return ptr;
212 }
213
zend_get_compiled_variable_value(const zend_execute_data * execute_data,uint32_t var)214 ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
215 {
216 return EX_VAR(var);
217 }
218
_get_zval_ptr_tmp(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)219 static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
220 {
221 zval *ret = EX_VAR(var);
222 *should_free = ret;
223
224 ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE);
225
226 return ret;
227 }
228
_get_zval_ptr_var(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)229 static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
230 {
231 zval *ret = EX_VAR(var);
232
233 *should_free = ret;
234 return ret;
235 }
236
_get_zval_ptr_var_deref(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)237 static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
238 {
239 zval *ret = EX_VAR(var);
240
241 *should_free = ret;
242 ZVAL_DEREF(ret);
243 return ret;
244 }
245
zval_undefined_cv(uint32_t var EXECUTE_DATA_DC)246 static zend_never_inline ZEND_COLD void zval_undefined_cv(uint32_t var EXECUTE_DATA_DC)
247 {
248 if (EXPECTED(EG(exception) == NULL)) {
249 zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
250 zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
251 }
252 }
253
_get_zval_cv_lookup(zval * ptr,uint32_t var,int type EXECUTE_DATA_DC)254 static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type EXECUTE_DATA_DC)
255 {
256 switch (type) {
257 case BP_VAR_R:
258 case BP_VAR_UNSET:
259 zval_undefined_cv(var EXECUTE_DATA_CC);
260 /* break missing intentionally */
261 case BP_VAR_IS:
262 ptr = &EG(uninitialized_zval);
263 break;
264 case BP_VAR_RW:
265 zval_undefined_cv(var EXECUTE_DATA_CC);
266 /* break missing intentionally */
267 case BP_VAR_W:
268 ZVAL_NULL(ptr);
269 break;
270 }
271 return ptr;
272 }
273
_get_zval_cv_lookup_BP_VAR_R(zval * ptr,uint32_t var EXECUTE_DATA_DC)274 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var EXECUTE_DATA_DC)
275 {
276 zval_undefined_cv(var EXECUTE_DATA_CC);
277 return &EG(uninitialized_zval);
278 }
279
_get_zval_cv_lookup_BP_VAR_UNSET(zval * ptr,uint32_t var EXECUTE_DATA_DC)280 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var EXECUTE_DATA_DC)
281 {
282 zval_undefined_cv(var EXECUTE_DATA_CC);
283 return &EG(uninitialized_zval);
284 }
285
_get_zval_cv_lookup_BP_VAR_RW(zval * ptr,uint32_t var EXECUTE_DATA_DC)286 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var EXECUTE_DATA_DC)
287 {
288 ZVAL_NULL(ptr);
289 zval_undefined_cv(var EXECUTE_DATA_CC);
290 return ptr;
291 }
292
_get_zval_cv_lookup_BP_VAR_W(zval * ptr,uint32_t var EXECUTE_DATA_DC)293 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var EXECUTE_DATA_DC)
294 {
295 ZVAL_NULL(ptr);
296 return ptr;
297 }
298
_get_zval_ptr_cv(uint32_t var,int type EXECUTE_DATA_DC)299 static zend_always_inline zval *_get_zval_ptr_cv(uint32_t var, int type EXECUTE_DATA_DC)
300 {
301 zval *ret = EX_VAR(var);
302
303 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
304 return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
305 }
306 return ret;
307 }
308
_get_zval_ptr_cv_undef(uint32_t var EXECUTE_DATA_DC)309 static zend_always_inline zval *_get_zval_ptr_cv_undef(uint32_t var EXECUTE_DATA_DC)
310 {
311 return EX_VAR(var);
312 }
313
_get_zval_ptr_cv_deref(uint32_t var,int type EXECUTE_DATA_DC)314 static zend_always_inline zval *_get_zval_ptr_cv_deref(uint32_t var, int type EXECUTE_DATA_DC)
315 {
316 zval *ret = EX_VAR(var);
317
318 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
319 return _get_zval_cv_lookup(ret, var, type EXECUTE_DATA_CC);
320 }
321 ZVAL_DEREF(ret);
322 return ret;
323 }
324
_get_zval_ptr_cv_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)325 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
326 {
327 zval *ret = EX_VAR(var);
328
329 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
330 return _get_zval_cv_lookup_BP_VAR_R(ret, var EXECUTE_DATA_CC);
331 }
332 return ret;
333 }
334
_get_zval_ptr_cv_deref_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)335 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(uint32_t var EXECUTE_DATA_DC)
336 {
337 zval *ret = EX_VAR(var);
338
339 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
340 return _get_zval_cv_lookup_BP_VAR_R(ret, var EXECUTE_DATA_CC);
341 }
342 ZVAL_DEREF(ret);
343 return ret;
344 }
345
_get_zval_ptr_cv_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)346 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
347 {
348 zval *ret = EX_VAR(var);
349
350 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
351 return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var EXECUTE_DATA_CC);
352 }
353 return ret;
354 }
355
_get_zval_ptr_cv_deref_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)356 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
357 {
358 zval *ret = EX_VAR(var);
359
360 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
361 return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var EXECUTE_DATA_CC);
362 }
363 ZVAL_DEREF(ret);
364 return ret;
365 }
366
_get_zval_ptr_cv_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)367 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
368 {
369 zval *ret = EX_VAR(var);
370
371 return ret;
372 }
373
_get_zval_ptr_cv_deref_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)374 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(uint32_t var EXECUTE_DATA_DC)
375 {
376 zval *ret = EX_VAR(var);
377
378 ZVAL_DEREF(ret);
379 return ret;
380 }
381
_get_zval_ptr_cv_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)382 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
383 {
384 zval *ret = EX_VAR(var);
385
386 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
387 return _get_zval_cv_lookup_BP_VAR_RW(ret, var EXECUTE_DATA_CC);
388 }
389 return ret;
390 }
391
_get_zval_ptr_cv_deref_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)392 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
393 {
394 zval *ret = EX_VAR(var);
395
396 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
397 return _get_zval_cv_lookup_BP_VAR_RW(ret, var EXECUTE_DATA_CC);
398 }
399 ZVAL_DEREF(ret);
400 return ret;
401 }
402
_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)403 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
404 {
405 zval *ret = EX_VAR(var);
406
407 if (Z_TYPE_P(ret) == IS_UNDEF) {
408 return _get_zval_cv_lookup_BP_VAR_W(ret, var EXECUTE_DATA_CC);
409 }
410 return ret;
411 }
412
_get_zval_ptr_cv_undef_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)413 static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
414 {
415 return EX_VAR(var);
416 }
417
_get_zval_ptr_cv_undef_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)418 static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_RW(uint32_t var EXECUTE_DATA_DC)
419 {
420 return EX_VAR(var);
421 }
422
_get_zval_ptr_cv_undef_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)423 static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_UNSET(uint32_t var EXECUTE_DATA_DC)
424 {
425 return EX_VAR(var);
426 }
427
_get_zval_ptr_cv_deref_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)428 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(uint32_t var EXECUTE_DATA_DC)
429 {
430 zval *ret = EX_VAR(var);
431
432 if (Z_TYPE_P(ret) == IS_UNDEF) {
433 return _get_zval_cv_lookup_BP_VAR_W(ret, var EXECUTE_DATA_CC);
434 }
435 ZVAL_DEREF(ret);
436 return ret;
437 }
438
_get_zval_ptr(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC)439 static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
440 {
441 if (op_type & (IS_TMP_VAR|IS_VAR)) {
442 if (op_type == IS_TMP_VAR) {
443 return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
444 } else {
445 ZEND_ASSERT(op_type == IS_VAR);
446 return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
447 }
448 } else {
449 *should_free = NULL;
450 if (op_type == IS_CONST) {
451 return EX_CONSTANT(node);
452 } else if (op_type == IS_CV) {
453 return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
454 } else {
455 return NULL;
456 }
457 }
458 }
459
_get_zval_ptr_r(int op_type,znode_op node,zend_free_op * should_free EXECUTE_DATA_DC)460 static zend_always_inline zval *_get_zval_ptr_r(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC)
461 {
462 if (op_type & (IS_TMP_VAR|IS_VAR)) {
463 if (op_type == IS_TMP_VAR) {
464 return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
465 } else {
466 ZEND_ASSERT(op_type == IS_VAR);
467 return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
468 }
469 } else {
470 *should_free = NULL;
471 if (op_type == IS_CONST) {
472 return EX_CONSTANT(node);
473 } else if (op_type == IS_CV) {
474 return _get_zval_ptr_cv_BP_VAR_R(node.var EXECUTE_DATA_CC);
475 } else {
476 return NULL;
477 }
478 }
479 }
480
_get_zval_ptr_deref(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC)481 static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
482 {
483 if (op_type & (IS_TMP_VAR|IS_VAR)) {
484 if (op_type == IS_TMP_VAR) {
485 return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
486 } else {
487 ZEND_ASSERT(op_type == IS_VAR);
488 return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC);
489 }
490 } else {
491 *should_free = NULL;
492 if (op_type == IS_CONST) {
493 return EX_CONSTANT(node);
494 } else if (op_type == IS_CV) {
495 return _get_zval_ptr_cv_deref(node.var, type EXECUTE_DATA_CC);
496 } else {
497 return NULL;
498 }
499 }
500 }
501
_get_zval_ptr_r_deref(int op_type,znode_op node,zend_free_op * should_free EXECUTE_DATA_DC)502 static zend_always_inline zval *_get_zval_ptr_r_deref(int op_type, znode_op node, zend_free_op *should_free EXECUTE_DATA_DC)
503 {
504 if (op_type & (IS_TMP_VAR|IS_VAR)) {
505 if (op_type == IS_TMP_VAR) {
506 return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
507 } else {
508 ZEND_ASSERT(op_type == IS_VAR);
509 return _get_zval_ptr_var_deref(node.var, should_free EXECUTE_DATA_CC);
510 }
511 } else {
512 *should_free = NULL;
513 if (op_type == IS_CONST) {
514 return EX_CONSTANT(node);
515 } else if (op_type == IS_CV) {
516 return _get_zval_ptr_cv_deref_BP_VAR_R(node.var EXECUTE_DATA_CC);
517 } else {
518 return NULL;
519 }
520 }
521 }
522
_get_zval_ptr_undef(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC)523 static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
524 {
525 if (op_type & (IS_TMP_VAR|IS_VAR)) {
526 if (op_type == IS_TMP_VAR) {
527 return _get_zval_ptr_tmp(node.var, should_free EXECUTE_DATA_CC);
528 } else {
529 ZEND_ASSERT(op_type == IS_VAR);
530 return _get_zval_ptr_var(node.var, should_free EXECUTE_DATA_CC);
531 }
532 } else {
533 *should_free = NULL;
534 if (op_type == IS_CONST) {
535 return EX_CONSTANT(node);
536 } else if (op_type == IS_CV) {
537 return _get_zval_ptr_cv_undef(node.var EXECUTE_DATA_CC);
538 } else {
539 return NULL;
540 }
541 }
542 }
543
_get_zval_ptr_ptr_var(uint32_t var,zend_free_op * should_free EXECUTE_DATA_DC)544 static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, zend_free_op *should_free EXECUTE_DATA_DC)
545 {
546 zval *ret = EX_VAR(var);
547
548 if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
549 *should_free = NULL;
550 ret = Z_INDIRECT_P(ret);
551 } else {
552 *should_free = ret;
553 }
554 return ret;
555 }
556
_get_zval_ptr_ptr(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC)557 static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
558 {
559 if (op_type == IS_CV) {
560 *should_free = NULL;
561 return _get_zval_ptr_cv(node.var, type EXECUTE_DATA_CC);
562 } else /* if (op_type == IS_VAR) */ {
563 ZEND_ASSERT(op_type == IS_VAR);
564 return _get_zval_ptr_ptr_var(node.var, should_free EXECUTE_DATA_CC);
565 }
566 }
567
_get_obj_zval_ptr_unused(EXECUTE_DATA_D)568 static zend_always_inline zval *_get_obj_zval_ptr_unused(EXECUTE_DATA_D)
569 {
570 return &EX(This);
571 }
572
_get_obj_zval_ptr(int op_type,znode_op op,zend_free_op * should_free,int type EXECUTE_DATA_DC)573 static inline zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC)
574 {
575 if (op_type == IS_UNUSED) {
576 *should_free = NULL;
577 return &EX(This);
578 }
579 return get_zval_ptr(op_type, op, should_free, type);
580 }
581
_get_obj_zval_ptr_undef(int op_type,znode_op op,zend_free_op * should_free,int type EXECUTE_DATA_DC)582 static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_free_op *should_free, int type EXECUTE_DATA_DC)
583 {
584 if (op_type == IS_UNUSED) {
585 *should_free = NULL;
586 return &EX(This);
587 }
588 return get_zval_ptr_undef(op_type, op, should_free, type);
589 }
590
_get_obj_zval_ptr_ptr(int op_type,znode_op node,zend_free_op * should_free,int type EXECUTE_DATA_DC)591 static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_free_op *should_free, int type EXECUTE_DATA_DC)
592 {
593 if (op_type == IS_UNUSED) {
594 *should_free = NULL;
595 return &EX(This);
596 }
597 return get_zval_ptr_ptr(op_type, node, should_free, type);
598 }
599
zend_assign_to_variable_reference(zval * variable_ptr,zval * value_ptr)600 static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr)
601 {
602 zend_reference *ref;
603
604 if (EXPECTED(!Z_ISREF_P(value_ptr))) {
605 ZVAL_NEW_REF(value_ptr, value_ptr);
606 } else if (UNEXPECTED(variable_ptr == value_ptr)) {
607 return;
608 }
609
610 ref = Z_REF_P(value_ptr);
611 GC_REFCOUNT(ref)++;
612 if (Z_REFCOUNTED_P(variable_ptr)) {
613 zend_refcounted *garbage = Z_COUNTED_P(variable_ptr);
614
615 if (--GC_REFCOUNT(garbage) == 0) {
616 ZVAL_REF(variable_ptr, ref);
617 zval_dtor_func(garbage);
618 return;
619 } else {
620 gc_check_possible_root(garbage);
621 }
622 }
623 ZVAL_REF(variable_ptr, ref);
624 }
625
626 /* this should modify object only if it's empty */
make_real_object(zval * object)627 static inline int make_real_object(zval *object)
628 {
629 if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
630 if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE)) {
631 /* nothing to destroy */
632 } else if (EXPECTED((Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
633 zval_ptr_dtor_nogc(object);
634 } else {
635 return 0;
636 }
637 object_init(object);
638 zend_error(E_WARNING, "Creating default object from empty value");
639 }
640 return 1;
641 }
642
zend_verify_type_error_common(const zend_function * zf,const zend_arg_info * arg_info,const zend_class_entry * ce,zval * value,const char ** fname,const char ** fsep,const char ** fclass,const char ** need_msg,const char ** need_kind,const char ** need_or_null,const char ** given_msg,const char ** given_kind)643 static ZEND_COLD void zend_verify_type_error_common(
644 const zend_function *zf, const zend_arg_info *arg_info,
645 const zend_class_entry *ce, zval *value,
646 const char **fname, const char **fsep, const char **fclass,
647 const char **need_msg, const char **need_kind, const char **need_or_null,
648 const char **given_msg, const char **given_kind)
649 {
650 zend_bool is_interface = 0;
651 *fname = ZSTR_VAL(zf->common.function_name);
652 if (zf->common.scope) {
653 *fsep = "::";
654 *fclass = ZSTR_VAL(zf->common.scope->name);
655 } else {
656 *fsep = "";
657 *fclass = "";
658 }
659
660 if (ZEND_TYPE_IS_CLASS(arg_info->type)) {
661 if (ce) {
662 if (ce->ce_flags & ZEND_ACC_INTERFACE) {
663 *need_msg = "implement interface ";
664 is_interface = 1;
665 } else {
666 *need_msg = "be an instance of ";
667 }
668 *need_kind = ZSTR_VAL(ce->name);
669 } else {
670 /* We don't know whether it's a class or interface, assume it's a class */
671
672 *need_msg = "be an instance of ";
673 *need_kind = ZSTR_VAL(ZEND_TYPE_NAME(arg_info->type));
674 }
675 } else {
676 switch (ZEND_TYPE_CODE(arg_info->type)) {
677 case IS_OBJECT:
678 *need_msg = "be an ";
679 *need_kind = "object";
680 break;
681 case IS_CALLABLE:
682 *need_msg = "be callable";
683 *need_kind = "";
684 break;
685 case IS_ITERABLE:
686 *need_msg = "be iterable";
687 *need_kind = "";
688 break;
689 default:
690 *need_msg = "be of the type ";
691 *need_kind = zend_get_type_by_const(ZEND_TYPE_CODE(arg_info->type));
692 break;
693 }
694 }
695
696 if (ZEND_TYPE_ALLOW_NULL(arg_info->type)) {
697 *need_or_null = is_interface ? " or be null" : " or null";
698 } else {
699 *need_or_null = "";
700 }
701
702 if (value) {
703 if (ZEND_TYPE_IS_CLASS(arg_info->type) && Z_TYPE_P(value) == IS_OBJECT) {
704 *given_msg = "instance of ";
705 *given_kind = ZSTR_VAL(Z_OBJCE_P(value)->name);
706 } else {
707 *given_msg = zend_zval_type_name(value);
708 *given_kind = "";
709 }
710 } else {
711 *given_msg = "none";
712 *given_kind = "";
713 }
714 }
715
zend_verify_arg_error(const zend_function * zf,const zend_arg_info * arg_info,int arg_num,const zend_class_entry * ce,zval * value)716 static ZEND_COLD void zend_verify_arg_error(
717 const zend_function *zf, const zend_arg_info *arg_info,
718 int arg_num, const zend_class_entry *ce, zval *value)
719 {
720 zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
721 const char *fname, *fsep, *fclass;
722 const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
723
724 if (value) {
725 zend_verify_type_error_common(
726 zf, arg_info, ce, value,
727 &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
728
729 if (zf->common.type == ZEND_USER_FUNCTION) {
730 if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
731 zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given, called in %s on line %d",
732 arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind,
733 ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
734 } else {
735 zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
736 }
737 } else {
738 zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
739 }
740 } else {
741 zend_missing_arg_error(ptr);
742 }
743 }
744
is_null_constant(zend_class_entry * scope,zval * default_value)745 static int is_null_constant(zend_class_entry *scope, zval *default_value)
746 {
747 if (Z_CONSTANT_P(default_value)) {
748 zval constant;
749
750 ZVAL_COPY(&constant, default_value);
751 if (UNEXPECTED(zval_update_constant_ex(&constant, scope) != SUCCESS)) {
752 return 0;
753 }
754 if (Z_TYPE(constant) == IS_NULL) {
755 return 1;
756 }
757 zval_ptr_dtor(&constant);
758 }
759 return 0;
760 }
761
zend_verify_weak_scalar_type_hint(zend_uchar type_hint,zval * arg)762 static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg)
763 {
764 switch (type_hint) {
765 case _IS_BOOL: {
766 zend_bool dest;
767
768 if (!zend_parse_arg_bool_weak(arg, &dest)) {
769 return 0;
770 }
771 zval_ptr_dtor(arg);
772 ZVAL_BOOL(arg, dest);
773 return 1;
774 }
775 case IS_LONG: {
776 zend_long dest;
777
778 if (!zend_parse_arg_long_weak(arg, &dest)) {
779 return 0;
780 }
781 zval_ptr_dtor(arg);
782 ZVAL_LONG(arg, dest);
783 return 1;
784 }
785 case IS_DOUBLE: {
786 double dest;
787
788 if (!zend_parse_arg_double_weak(arg, &dest)) {
789 return 0;
790 }
791 zval_ptr_dtor(arg);
792 ZVAL_DOUBLE(arg, dest);
793 return 1;
794 }
795 case IS_STRING: {
796 zend_string *dest;
797
798 /* on success "arg" is converted to IS_STRING */
799 if (!zend_parse_arg_str_weak(arg, &dest)) {
800 return 0;
801 }
802 return 1;
803 }
804 default:
805 return 0;
806 }
807 }
808
zend_verify_scalar_type_hint(zend_uchar type_hint,zval * arg,zend_bool strict)809 static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict)
810 {
811 if (UNEXPECTED(strict)) {
812 /* SSTH Exception: IS_LONG may be accepted as IS_DOUBLE (converted) */
813 if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) {
814 return 0;
815 }
816 } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
817 /* NULL may be accepted only by nullable hints (this is already checked) */
818 return 0;
819 }
820 return zend_verify_weak_scalar_type_hint(type_hint, arg);
821 }
822
zend_check_type(zend_type type,zval * arg,zend_class_entry ** ce,void ** cache_slot,zval * default_value,zend_class_entry * scope,zend_bool is_return_type)823 static zend_always_inline zend_bool zend_check_type(
824 zend_type type,
825 zval *arg, zend_class_entry **ce, void **cache_slot,
826 zval *default_value, zend_class_entry *scope,
827 zend_bool is_return_type)
828 {
829 if (!ZEND_TYPE_IS_SET(type)) {
830 return 1;
831 }
832
833 ZVAL_DEREF(arg);
834 if (ZEND_TYPE_IS_CLASS(type)) {
835 if (EXPECTED(*cache_slot)) {
836 *ce = (zend_class_entry *) *cache_slot;
837 } else {
838 *ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
839 if (UNEXPECTED(!*ce)) {
840 return Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)));
841 }
842 *cache_slot = (void *) *ce;
843 }
844 if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
845 return instanceof_function(Z_OBJCE_P(arg), *ce);
846 }
847 return Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)));
848 } else if (EXPECTED(ZEND_TYPE_CODE(type) == Z_TYPE_P(arg))) {
849 return 1;
850 }
851
852 if (Z_TYPE_P(arg) == IS_NULL && (ZEND_TYPE_ALLOW_NULL(type) || (default_value && is_null_constant(scope, default_value)))) {
853 /* Null passed to nullable type */
854 return 1;
855 }
856
857 if (ZEND_TYPE_CODE(type) == IS_CALLABLE) {
858 return zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL);
859 } else if (ZEND_TYPE_CODE(type) == IS_ITERABLE) {
860 return zend_is_iterable(arg);
861 } else if (ZEND_TYPE_CODE(type) == _IS_BOOL &&
862 EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
863 return 1;
864 } else {
865 return zend_verify_scalar_type_hint(ZEND_TYPE_CODE(type), arg,
866 is_return_type ? ZEND_RET_USES_STRICT_TYPES() : ZEND_ARG_USES_STRICT_TYPES());
867 }
868
869 /* Special handling for IS_VOID is not necessary (for return types),
870 * because this case is already checked at compile-time. */
871 }
872
zend_verify_arg_type(zend_function * zf,uint32_t arg_num,zval * arg,zval * default_value,void ** cache_slot)873 static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
874 {
875 zend_arg_info *cur_arg_info;
876 zend_class_entry *ce;
877
878 if (EXPECTED(arg_num <= zf->common.num_args)) {
879 cur_arg_info = &zf->common.arg_info[arg_num-1];
880 } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) {
881 cur_arg_info = &zf->common.arg_info[zf->common.num_args];
882 } else {
883 return 1;
884 }
885
886 if (UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &ce, cache_slot, default_value, zf->common.scope, 0))) {
887 zend_verify_arg_error(zf, cur_arg_info, arg_num, ce, arg);
888 return 0;
889 }
890
891 return 1;
892 }
893
zend_verify_internal_arg_types(zend_function * fbc,zend_execute_data * call)894 static zend_never_inline int zend_verify_internal_arg_types(zend_function *fbc, zend_execute_data *call)
895 {
896 uint32_t i;
897 uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
898 zval *p = ZEND_CALL_ARG(call, 1);
899 void *dummy_cache_slot;
900
901 for (i = 0; i < num_args; ++i) {
902 dummy_cache_slot = NULL;
903 if (UNEXPECTED(!zend_verify_arg_type(fbc, i + 1, p, NULL, &dummy_cache_slot))) {
904 EG(current_execute_data) = call->prev_execute_data;
905 zend_vm_stack_free_args(call);
906 return 0;
907 }
908 p++;
909 }
910 return 1;
911 }
912
zend_missing_arg_error(zend_execute_data * execute_data)913 ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data)
914 {
915 zend_execute_data *ptr = EX(prev_execute_data);
916
917 if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
918 zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed in %s on line %d and %s %d expected",
919 EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
920 EX(func)->common.scope ? "::" : "",
921 ZSTR_VAL(EX(func)->common.function_name),
922 EX_NUM_ARGS(),
923 ZSTR_VAL(ptr->func->op_array.filename),
924 ptr->opline->lineno,
925 EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
926 EX(func)->common.required_num_args);
927 } else {
928 zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed and %s %d expected",
929 EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
930 EX(func)->common.scope ? "::" : "",
931 ZSTR_VAL(EX(func)->common.function_name),
932 EX_NUM_ARGS(),
933 EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
934 EX(func)->common.required_num_args);
935 }
936 }
937
zend_verify_return_error(const zend_function * zf,const zend_class_entry * ce,zval * value)938 static ZEND_COLD void zend_verify_return_error(
939 const zend_function *zf, const zend_class_entry *ce, zval *value)
940 {
941 const zend_arg_info *arg_info = &zf->common.arg_info[-1];
942 const char *fname, *fsep, *fclass;
943 const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
944
945 zend_verify_type_error_common(
946 zf, arg_info, ce, value,
947 &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
948
949 zend_type_error("Return value of %s%s%s() must %s%s%s, %s%s returned",
950 fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
951 }
952
953 #if ZEND_DEBUG
zend_verify_internal_return_error(const zend_function * zf,const zend_class_entry * ce,zval * value)954 static ZEND_COLD void zend_verify_internal_return_error(
955 const zend_function *zf, const zend_class_entry *ce, zval *value)
956 {
957 const zend_arg_info *arg_info = &zf->common.arg_info[-1];
958 const char *fname, *fsep, *fclass;
959 const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
960
961 zend_verify_type_error_common(
962 zf, arg_info, ce, value,
963 &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
964
965 zend_error_noreturn(E_CORE_ERROR, "Return value of %s%s%s() must %s%s%s, %s%s returned",
966 fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
967 }
968
zend_verify_void_return_error(const zend_function * zf,const char * returned_msg,const char * returned_kind)969 static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, const char *returned_msg, const char *returned_kind)
970 {
971 const char *fname = ZSTR_VAL(zf->common.function_name);
972 const char *fsep;
973 const char *fclass;
974
975 if (zf->common.scope) {
976 fsep = "::";
977 fclass = ZSTR_VAL(zf->common.scope->name);
978 } else {
979 fsep = "";
980 fclass = "";
981 }
982
983 zend_type_error("%s%s%s() must not return a value, %s%s returned",
984 fclass, fsep, fname, returned_msg, returned_kind);
985 }
986
zend_verify_internal_return_type(zend_function * zf,zval * ret)987 static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
988 {
989 zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
990 zend_class_entry *ce = NULL;
991 void *dummy_cache_slot = NULL;
992
993 if (ZEND_TYPE_CODE(ret_info->type) == IS_VOID) {
994 if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
995 zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
996 return 0;
997 }
998 return 1;
999 }
1000
1001 if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, &dummy_cache_slot, NULL, NULL, 1))) {
1002 zend_verify_internal_return_error(zf, ce, ret);
1003 return 0;
1004 }
1005
1006 return 1;
1007 }
1008 #endif
1009
zend_verify_return_type(zend_function * zf,zval * ret,void ** cache_slot)1010 static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *ret, void **cache_slot)
1011 {
1012 zend_arg_info *ret_info = zf->common.arg_info - 1;
1013 zend_class_entry *ce = NULL;
1014
1015 if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &ce, cache_slot, NULL, NULL, 1))) {
1016 zend_verify_return_error(zf, ce, ret);
1017 }
1018 }
1019
zend_verify_missing_return_type(zend_function * zf,void ** cache_slot)1020 static ZEND_COLD int zend_verify_missing_return_type(zend_function *zf, void **cache_slot)
1021 {
1022 zend_arg_info *ret_info = zf->common.arg_info - 1;
1023
1024 if (ZEND_TYPE_IS_SET(ret_info->type) && UNEXPECTED(ZEND_TYPE_CODE(ret_info->type) != IS_VOID)) {
1025 zend_class_entry *ce = NULL;
1026 if (ZEND_TYPE_IS_CLASS(ret_info->type)) {
1027 if (EXPECTED(*cache_slot)) {
1028 ce = (zend_class_entry*) *cache_slot;
1029 } else {
1030 ce = zend_fetch_class(ZEND_TYPE_NAME(ret_info->type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
1031 if (ce) {
1032 *cache_slot = (void*)ce;
1033 }
1034 }
1035 }
1036 zend_verify_return_error(zf, ce, NULL);
1037 return 0;
1038 }
1039 return 1;
1040 }
1041
zend_assign_to_object_dim(zval * object,zval * dim,zval * value)1042 static zend_never_inline void zend_assign_to_object_dim(zval *object, zval *dim, zval *value)
1043 {
1044 if (UNEXPECTED(!Z_OBJ_HT_P(object)->write_dimension)) {
1045 zend_throw_error(NULL, "Cannot use object as array");
1046 return;
1047 }
1048
1049 Z_OBJ_HT_P(object)->write_dimension(object, dim, value);
1050 }
1051
zend_binary_assign_op_obj_dim(zval * object,zval * property,zval * value,zval * retval,binary_op_type binary_op EXECUTE_DATA_DC)1052 static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *value, zval *retval, binary_op_type binary_op EXECUTE_DATA_DC)
1053 {
1054 zval *z;
1055 zval rv, res;
1056
1057 if (Z_OBJ_HT_P(object)->read_dimension &&
1058 (z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) {
1059
1060 if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1061 zval rv2;
1062 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1063
1064 if (z == &rv) {
1065 zval_ptr_dtor(&rv);
1066 }
1067 ZVAL_COPY_VALUE(z, value);
1068 }
1069 binary_op(&res, Z_ISREF_P(z) ? Z_REFVAL_P(z) : z, value);
1070 Z_OBJ_HT_P(object)->write_dimension(object, property, &res);
1071 if (z == &rv) {
1072 zval_ptr_dtor(&rv);
1073 }
1074 if (retval) {
1075 ZVAL_COPY(retval, &res);
1076 }
1077 zval_ptr_dtor(&res);
1078 } else {
1079 zend_error(E_WARNING, "Attempt to assign property of non-object");
1080 if (retval) {
1081 ZVAL_NULL(retval);
1082 }
1083 }
1084 }
1085
zend_check_string_offset(zval * dim,int type EXECUTE_DATA_DC)1086 static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type EXECUTE_DATA_DC)
1087 {
1088 zend_long offset;
1089
1090 try_again:
1091 if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1092 switch(Z_TYPE_P(dim)) {
1093 case IS_STRING:
1094 if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1095 break;
1096 }
1097 if (type != BP_VAR_UNSET) {
1098 zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1099 }
1100 break;
1101 case IS_UNDEF:
1102 zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1103 case IS_DOUBLE:
1104 case IS_NULL:
1105 case IS_FALSE:
1106 case IS_TRUE:
1107 zend_error(E_NOTICE, "String offset cast occurred");
1108 break;
1109 case IS_REFERENCE:
1110 dim = Z_REFVAL_P(dim);
1111 goto try_again;
1112 default:
1113 zend_error(E_WARNING, "Illegal offset type");
1114 break;
1115 }
1116
1117 offset = _zval_get_long_func(dim);
1118 } else {
1119 offset = Z_LVAL_P(dim);
1120 }
1121
1122 return offset;
1123 }
1124
zend_wrong_string_offset(EXECUTE_DATA_D)1125 static zend_never_inline ZEND_COLD void zend_wrong_string_offset(EXECUTE_DATA_D)
1126 {
1127 const char *msg = NULL;
1128 const zend_op *opline = EX(opline);
1129 const zend_op *end;
1130 uint32_t var;
1131
1132 switch (opline->opcode) {
1133 case ZEND_ASSIGN_ADD:
1134 case ZEND_ASSIGN_SUB:
1135 case ZEND_ASSIGN_MUL:
1136 case ZEND_ASSIGN_DIV:
1137 case ZEND_ASSIGN_MOD:
1138 case ZEND_ASSIGN_SL:
1139 case ZEND_ASSIGN_SR:
1140 case ZEND_ASSIGN_CONCAT:
1141 case ZEND_ASSIGN_BW_OR:
1142 case ZEND_ASSIGN_BW_AND:
1143 case ZEND_ASSIGN_BW_XOR:
1144 case ZEND_ASSIGN_POW:
1145 msg = "Cannot use assign-op operators with string offsets";
1146 break;
1147 case ZEND_FETCH_DIM_W:
1148 case ZEND_FETCH_DIM_RW:
1149 case ZEND_FETCH_DIM_FUNC_ARG:
1150 case ZEND_FETCH_DIM_UNSET:
1151 /* TODO: Encode the "reason" into opline->extended_value??? */
1152 var = opline->result.var;
1153 opline++;
1154 end = EG(current_execute_data)->func->op_array.opcodes +
1155 EG(current_execute_data)->func->op_array.last;
1156 while (opline < end) {
1157 if (opline->op1_type == IS_VAR && opline->op1.var == var) {
1158 switch (opline->opcode) {
1159 case ZEND_ASSIGN_ADD:
1160 case ZEND_ASSIGN_SUB:
1161 case ZEND_ASSIGN_MUL:
1162 case ZEND_ASSIGN_DIV:
1163 case ZEND_ASSIGN_MOD:
1164 case ZEND_ASSIGN_SL:
1165 case ZEND_ASSIGN_SR:
1166 case ZEND_ASSIGN_CONCAT:
1167 case ZEND_ASSIGN_BW_OR:
1168 case ZEND_ASSIGN_BW_AND:
1169 case ZEND_ASSIGN_BW_XOR:
1170 case ZEND_ASSIGN_POW:
1171 if (opline->extended_value == ZEND_ASSIGN_OBJ) {
1172 msg = "Cannot use string offset as an object";
1173 } else if (opline->extended_value == ZEND_ASSIGN_DIM) {
1174 msg = "Cannot use string offset as an array";
1175 } else {
1176 msg = "Cannot use assign-op operators with string offsets";
1177 }
1178 break;
1179 case ZEND_PRE_INC_OBJ:
1180 case ZEND_PRE_DEC_OBJ:
1181 case ZEND_POST_INC_OBJ:
1182 case ZEND_POST_DEC_OBJ:
1183 case ZEND_PRE_INC:
1184 case ZEND_PRE_DEC:
1185 case ZEND_POST_INC:
1186 case ZEND_POST_DEC:
1187 msg = "Cannot increment/decrement string offsets";
1188 break;
1189 case ZEND_FETCH_DIM_W:
1190 case ZEND_FETCH_DIM_RW:
1191 case ZEND_FETCH_DIM_FUNC_ARG:
1192 case ZEND_FETCH_DIM_UNSET:
1193 case ZEND_ASSIGN_DIM:
1194 msg = "Cannot use string offset as an array";
1195 break;
1196 case ZEND_FETCH_OBJ_W:
1197 case ZEND_FETCH_OBJ_RW:
1198 case ZEND_FETCH_OBJ_FUNC_ARG:
1199 case ZEND_FETCH_OBJ_UNSET:
1200 case ZEND_ASSIGN_OBJ:
1201 msg = "Cannot use string offset as an object";
1202 break;
1203 case ZEND_ASSIGN_REF:
1204 case ZEND_ADD_ARRAY_ELEMENT:
1205 case ZEND_INIT_ARRAY:
1206 case ZEND_MAKE_REF:
1207 msg = "Cannot create references to/from string offsets";
1208 break;
1209 case ZEND_RETURN_BY_REF:
1210 case ZEND_VERIFY_RETURN_TYPE:
1211 msg = "Cannot return string offsets by reference";
1212 break;
1213 case ZEND_UNSET_DIM:
1214 case ZEND_UNSET_OBJ:
1215 msg = "Cannot unset string offsets";
1216 break;
1217 case ZEND_YIELD:
1218 msg = "Cannot yield string offsets by reference";
1219 break;
1220 case ZEND_SEND_REF:
1221 case ZEND_SEND_VAR_EX:
1222 msg = "Only variables can be passed by reference";
1223 break;
1224 case ZEND_FE_RESET_RW:
1225 msg = "Cannot iterate on string offsets by reference";
1226 break;
1227 EMPTY_SWITCH_DEFAULT_CASE();
1228 }
1229 break;
1230 }
1231 if (opline->op2_type == IS_VAR && opline->op2.var == var) {
1232 ZEND_ASSERT(opline->opcode == ZEND_ASSIGN_REF);
1233 msg = "Cannot create references to/from string offsets";
1234 break;
1235 }
1236 }
1237 break;
1238 EMPTY_SWITCH_DEFAULT_CASE();
1239 }
1240 ZEND_ASSERT(msg != NULL);
1241 zend_throw_error(NULL, msg);
1242 }
1243
zend_assign_to_string_offset(zval * str,zval * dim,zval * value,zval * result EXECUTE_DATA_DC)1244 static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value, zval *result EXECUTE_DATA_DC)
1245 {
1246 zend_string *old_str;
1247 zend_uchar c;
1248 size_t string_len;
1249 zend_long offset;
1250
1251 offset = zend_check_string_offset(dim, BP_VAR_W EXECUTE_DATA_CC);
1252 if (offset < -(zend_long)Z_STRLEN_P(str)) {
1253 /* Error on negative offset */
1254 zend_error(E_WARNING, "Illegal string offset: " ZEND_LONG_FMT, offset);
1255 if (result) {
1256 ZVAL_NULL(result);
1257 }
1258 return;
1259 }
1260
1261 if (Z_TYPE_P(value) != IS_STRING) {
1262 /* Convert to string, just the time to pick the 1st byte */
1263 zend_string *tmp = zval_get_string(value);
1264
1265 string_len = ZSTR_LEN(tmp);
1266 c = (zend_uchar)ZSTR_VAL(tmp)[0];
1267 zend_string_release(tmp);
1268 } else {
1269 string_len = Z_STRLEN_P(value);
1270 c = (zend_uchar)Z_STRVAL_P(value)[0];
1271 }
1272
1273 if (string_len == 0) {
1274 /* Error on empty input string */
1275 zend_error(E_WARNING, "Cannot assign an empty string to a string offset");
1276 if (result) {
1277 ZVAL_NULL(result);
1278 }
1279 return;
1280 }
1281
1282 if (offset < 0) { /* Handle negative offset */
1283 offset += (zend_long)Z_STRLEN_P(str);
1284 }
1285
1286 if ((size_t)offset >= Z_STRLEN_P(str)) {
1287 /* Extend string if needed */
1288 zend_long old_len = Z_STRLEN_P(str);
1289 Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
1290 Z_TYPE_INFO_P(str) = IS_STRING_EX;
1291 memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
1292 Z_STRVAL_P(str)[offset+1] = 0;
1293 } else if (!Z_REFCOUNTED_P(str)) {
1294 old_str = Z_STR_P(str);
1295 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
1296 Z_TYPE_INFO_P(str) = IS_STRING_EX;
1297 zend_string_release(old_str);
1298 } else {
1299 SEPARATE_STRING(str);
1300 zend_string_forget_hash_val(Z_STR_P(str));
1301 }
1302
1303 Z_STRVAL_P(str)[offset] = c;
1304
1305 if (result) {
1306 /* Return the new character */
1307 ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
1308 }
1309 }
1310
zend_post_incdec_overloaded_property(zval * object,zval * property,void ** cache_slot,int inc,zval * result)1311 static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
1312 {
1313 if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1314 zval rv, obj;
1315 zval *z;
1316 zval z_copy;
1317
1318 ZVAL_OBJ(&obj, Z_OBJ_P(object));
1319 Z_ADDREF(obj);
1320 z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1321 if (UNEXPECTED(EG(exception))) {
1322 OBJ_RELEASE(Z_OBJ(obj));
1323 ZVAL_UNDEF(result);
1324 return;
1325 }
1326
1327 if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1328 zval rv2;
1329 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1330 if (z == &rv) {
1331 zval_ptr_dtor(&rv);
1332 }
1333 ZVAL_COPY_VALUE(z, value);
1334 }
1335
1336 if (UNEXPECTED(Z_TYPE_P(z) == IS_REFERENCE)) {
1337 ZVAL_COPY(result, Z_REFVAL_P(z));
1338 } else {
1339 ZVAL_COPY(result, z);
1340 }
1341 ZVAL_DUP(&z_copy, result);
1342 if (inc) {
1343 increment_function(&z_copy);
1344 } else {
1345 decrement_function(&z_copy);
1346 }
1347 Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
1348 OBJ_RELEASE(Z_OBJ(obj));
1349 zval_ptr_dtor(&z_copy);
1350 zval_ptr_dtor(z);
1351 } else {
1352 zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1353 ZVAL_NULL(result);
1354 }
1355 }
1356
zend_pre_incdec_overloaded_property(zval * object,zval * property,void ** cache_slot,int inc,zval * result)1357 static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
1358 {
1359 zval rv;
1360
1361 if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1362 zval *z, *zptr, obj;
1363
1364 ZVAL_OBJ(&obj, Z_OBJ_P(object));
1365 Z_ADDREF(obj);
1366 zptr = z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1367 if (UNEXPECTED(EG(exception))) {
1368 OBJ_RELEASE(Z_OBJ(obj));
1369 if (result) {
1370 ZVAL_UNDEF(result);
1371 }
1372 return;
1373 }
1374
1375 if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1376 zval rv2;
1377 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1378
1379 if (z == &rv) {
1380 zval_ptr_dtor(&rv);
1381 }
1382 ZVAL_COPY_VALUE(z, value);
1383 }
1384 ZVAL_DEREF(z);
1385 SEPARATE_ZVAL_NOREF(z);
1386 if (inc) {
1387 increment_function(z);
1388 } else {
1389 decrement_function(z);
1390 }
1391 if (UNEXPECTED(result)) {
1392 ZVAL_COPY(result, z);
1393 }
1394 Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
1395 OBJ_RELEASE(Z_OBJ(obj));
1396 zval_ptr_dtor(zptr);
1397 } else {
1398 zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1399 if (UNEXPECTED(result)) {
1400 ZVAL_NULL(result);
1401 }
1402 }
1403 }
1404
zend_assign_op_overloaded_property(zval * object,zval * property,void ** cache_slot,zval * value,binary_op_type binary_op,zval * result)1405 static zend_never_inline void zend_assign_op_overloaded_property(zval *object, zval *property, void **cache_slot, zval *value, binary_op_type binary_op, zval *result)
1406 {
1407 zval *z;
1408 zval rv, obj;
1409 zval *zptr;
1410
1411 ZVAL_OBJ(&obj, Z_OBJ_P(object));
1412 Z_ADDREF(obj);
1413 if (EXPECTED(Z_OBJ_HT(obj)->read_property)) {
1414 z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1415 if (UNEXPECTED(EG(exception))) {
1416 OBJ_RELEASE(Z_OBJ(obj));
1417 if (result) {
1418 ZVAL_UNDEF(result);
1419 }
1420 return;
1421 }
1422 if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1423 zval rv2;
1424 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1425
1426 if (z == &rv) {
1427 zval_ptr_dtor(&rv);
1428 }
1429 ZVAL_COPY_VALUE(z, value);
1430 }
1431 zptr = z;
1432 ZVAL_DEREF(z);
1433 SEPARATE_ZVAL_NOREF(z);
1434 binary_op(z, z, value);
1435 Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
1436 if (UNEXPECTED(result)) {
1437 ZVAL_COPY(result, z);
1438 }
1439 zval_ptr_dtor(zptr);
1440 } else {
1441 zend_error(E_WARNING, "Attempt to assign property of non-object");
1442 if (UNEXPECTED(result)) {
1443 ZVAL_NULL(result);
1444 }
1445 }
1446 OBJ_RELEASE(Z_OBJ(obj));
1447 }
1448
1449 /* Utility Functions for Extensions */
zend_extension_statement_handler(const zend_extension * extension,zend_execute_data * frame)1450 static void zend_extension_statement_handler(const zend_extension *extension, zend_execute_data *frame)
1451 {
1452 if (extension->statement_handler) {
1453 extension->statement_handler(frame);
1454 }
1455 }
1456
1457
zend_extension_fcall_begin_handler(const zend_extension * extension,zend_execute_data * frame)1458 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_execute_data *frame)
1459 {
1460 if (extension->fcall_begin_handler) {
1461 extension->fcall_begin_handler(frame);
1462 }
1463 }
1464
1465
zend_extension_fcall_end_handler(const zend_extension * extension,zend_execute_data * frame)1466 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_execute_data *frame)
1467 {
1468 if (extension->fcall_end_handler) {
1469 extension->fcall_end_handler(frame);
1470 }
1471 }
1472
1473
zend_get_target_symbol_table(int fetch_type EXECUTE_DATA_DC)1474 static zend_always_inline HashTable *zend_get_target_symbol_table(int fetch_type EXECUTE_DATA_DC)
1475 {
1476 HashTable *ht;
1477
1478 if (EXPECTED(fetch_type == ZEND_FETCH_GLOBAL_LOCK) ||
1479 EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) {
1480 ht = &EG(symbol_table);
1481 } else {
1482 ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL);
1483 if (!(EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE)) {
1484 zend_rebuild_symbol_table();
1485 }
1486 ht = EX(symbol_table);
1487 }
1488 return ht;
1489 }
1490
zend_fetch_dimension_address_inner(HashTable * ht,const zval * dim,int dim_type,int type EXECUTE_DATA_DC)1491 static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type EXECUTE_DATA_DC)
1492 {
1493 zval *retval;
1494 zend_string *offset_key;
1495 zend_ulong hval;
1496
1497 try_again:
1498 if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
1499 hval = Z_LVAL_P(dim);
1500 num_index:
1501 ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
1502 return retval;
1503 num_undef:
1504 switch (type) {
1505 case BP_VAR_R:
1506 zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
1507 /* break missing intentionally */
1508 case BP_VAR_UNSET:
1509 case BP_VAR_IS:
1510 retval = &EG(uninitialized_zval);
1511 break;
1512 case BP_VAR_RW:
1513 zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
1514 retval = zend_hash_index_update(ht, hval, &EG(uninitialized_zval));
1515 break;
1516 case BP_VAR_W:
1517 retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
1518 break;
1519 }
1520 } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
1521 offset_key = Z_STR_P(dim);
1522 if (dim_type != IS_CONST) {
1523 if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
1524 goto num_index;
1525 }
1526 }
1527 str_index:
1528 retval = zend_hash_find(ht, offset_key);
1529 if (retval) {
1530 /* support for $GLOBALS[...] */
1531 if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
1532 retval = Z_INDIRECT_P(retval);
1533 if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
1534 switch (type) {
1535 case BP_VAR_R:
1536 zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
1537 /* break missing intentionally */
1538 case BP_VAR_UNSET:
1539 case BP_VAR_IS:
1540 retval = &EG(uninitialized_zval);
1541 break;
1542 case BP_VAR_RW:
1543 zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key));
1544 /* break missing intentionally */
1545 case BP_VAR_W:
1546 ZVAL_NULL(retval);
1547 break;
1548 }
1549 }
1550 }
1551 } else {
1552 switch (type) {
1553 case BP_VAR_R:
1554 zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
1555 /* break missing intentionally */
1556 case BP_VAR_UNSET:
1557 case BP_VAR_IS:
1558 retval = &EG(uninitialized_zval);
1559 break;
1560 case BP_VAR_RW:
1561 zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key));
1562 retval = zend_hash_update(ht, offset_key, &EG(uninitialized_zval));
1563 break;
1564 case BP_VAR_W:
1565 retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
1566 break;
1567 }
1568 }
1569 } else {
1570 switch (Z_TYPE_P(dim)) {
1571 case IS_UNDEF:
1572 zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1573 /* break missing intentionally */
1574 case IS_NULL:
1575 offset_key = ZSTR_EMPTY_ALLOC();
1576 goto str_index;
1577 case IS_DOUBLE:
1578 hval = zend_dval_to_lval(Z_DVAL_P(dim));
1579 goto num_index;
1580 case IS_RESOURCE:
1581 zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
1582 hval = Z_RES_HANDLE_P(dim);
1583 goto num_index;
1584 case IS_FALSE:
1585 hval = 0;
1586 goto num_index;
1587 case IS_TRUE:
1588 hval = 1;
1589 goto num_index;
1590 case IS_REFERENCE:
1591 dim = Z_REFVAL_P(dim);
1592 goto try_again;
1593 default:
1594 zend_error(E_WARNING, "Illegal offset type");
1595 retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
1596 NULL : &EG(uninitialized_zval);
1597 }
1598 }
1599 return retval;
1600 }
1601
zend_fetch_dimension_address_inner_W(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1602 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1603 {
1604 return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_W EXECUTE_DATA_CC);
1605 }
1606
zend_fetch_dimension_address_inner_W_CONST(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1607 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_W_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1608 {
1609 return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_W EXECUTE_DATA_CC);
1610 }
1611
zend_fetch_dimension_address_inner_RW(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1612 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1613 {
1614 return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_RW EXECUTE_DATA_CC);
1615 }
1616
zend_fetch_dimension_address_inner_RW_CONST(HashTable * ht,const zval * dim EXECUTE_DATA_DC)1617 static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW_CONST(HashTable *ht, const zval *dim EXECUTE_DATA_DC)
1618 {
1619 return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_RW EXECUTE_DATA_CC);
1620 }
1621
zend_fetch_dimension_address(zval * result,zval * container,zval * dim,int dim_type,int type EXECUTE_DATA_DC)1622 static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type EXECUTE_DATA_DC)
1623 {
1624 zval *retval;
1625
1626 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1627 try_array:
1628 SEPARATE_ARRAY(container);
1629 fetch_from_array:
1630 if (dim == NULL) {
1631 retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
1632 if (UNEXPECTED(retval == NULL)) {
1633 zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1634 ZVAL_ERROR(result);
1635 return;
1636 }
1637 } else {
1638 retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
1639 if (UNEXPECTED(!retval)) {
1640 ZVAL_ERROR(result);
1641 return;
1642 }
1643 }
1644 ZVAL_INDIRECT(result, retval);
1645 return;
1646 } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1647 container = Z_REFVAL_P(container);
1648 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1649 goto try_array;
1650 }
1651 }
1652 if (UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1653 if (dim == NULL) {
1654 zend_throw_error(NULL, "[] operator not supported for strings");
1655 } else {
1656 zend_check_string_offset(dim, type EXECUTE_DATA_CC);
1657 if (EXPECTED(EG(exception) == NULL)) {
1658 zend_wrong_string_offset(EXECUTE_DATA_C);
1659 }
1660 }
1661 ZVAL_ERROR(result);
1662 } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1663 if (/*dim_type == IS_CV &&*/ dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
1664 zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1665 dim = &EG(uninitialized_zval);
1666 }
1667 if (!Z_OBJ_HT_P(container)->read_dimension) {
1668 zend_throw_error(NULL, "Cannot use object as array");
1669 ZVAL_ERROR(result);
1670 } else {
1671 retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
1672
1673 if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1674 zend_class_entry *ce = Z_OBJCE_P(container);
1675
1676 ZVAL_NULL(result);
1677 zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1678 } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1679 if (!Z_ISREF_P(retval)) {
1680 if (result != retval) {
1681 ZVAL_COPY(result, retval);
1682 retval = result;
1683 }
1684 if (Z_TYPE_P(retval) != IS_OBJECT) {
1685 zend_class_entry *ce = Z_OBJCE_P(container);
1686 zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1687 }
1688 } else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
1689 ZVAL_UNREF(retval);
1690 }
1691 if (result != retval) {
1692 ZVAL_INDIRECT(result, retval);
1693 }
1694 } else {
1695 ZVAL_ERROR(result);
1696 }
1697 }
1698 } else {
1699 if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
1700 zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
1701 }
1702 if (/*dim_type == IS_CV &&*/ dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
1703 zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1704 }
1705 if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
1706 if (type != BP_VAR_UNSET) {
1707 ZVAL_NEW_ARR(container);
1708 zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
1709 goto fetch_from_array;
1710 } else {
1711 /* for read-mode only */
1712 ZVAL_NULL(result);
1713 }
1714 } else if (EXPECTED(Z_ISERROR_P(container))) {
1715 ZVAL_ERROR(result);
1716 } else {
1717 if (type == BP_VAR_UNSET) {
1718 zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1719 ZVAL_NULL(result);
1720 } else {
1721 zend_error(E_WARNING, "Cannot use a scalar value as an array");
1722 ZVAL_ERROR(result);
1723 }
1724 }
1725 }
1726 }
1727
zend_fetch_dimension_address_W(zval * result,zval * container_ptr,zval * dim,int dim_type EXECUTE_DATA_DC)1728 static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type EXECUTE_DATA_DC)
1729 {
1730 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W EXECUTE_DATA_CC);
1731 }
1732
zend_fetch_dimension_address_RW(zval * result,zval * container_ptr,zval * dim,int dim_type EXECUTE_DATA_DC)1733 static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type EXECUTE_DATA_DC)
1734 {
1735 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW EXECUTE_DATA_CC);
1736 }
1737
zend_fetch_dimension_address_UNSET(zval * result,zval * container_ptr,zval * dim,int dim_type EXECUTE_DATA_DC)1738 static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type EXECUTE_DATA_DC)
1739 {
1740 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET EXECUTE_DATA_CC);
1741 }
1742
zend_fetch_dimension_address_read(zval * result,zval * container,zval * dim,int dim_type,int type,int support_strings,int slow EXECUTE_DATA_DC)1743 static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, int support_strings, int slow EXECUTE_DATA_DC)
1744 {
1745 zval *retval;
1746
1747 if (!slow) {
1748 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1749 try_array:
1750 retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type EXECUTE_DATA_CC);
1751 ZVAL_COPY(result, retval);
1752 return;
1753 } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1754 container = Z_REFVAL_P(container);
1755 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1756 goto try_array;
1757 }
1758 }
1759 }
1760 if (support_strings && EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1761 zend_long offset;
1762
1763 try_string_offset:
1764 if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1765 switch (Z_TYPE_P(dim)) {
1766 /* case IS_LONG: */
1767 case IS_STRING:
1768 if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1769 break;
1770 }
1771 if (type == BP_VAR_IS) {
1772 ZVAL_NULL(result);
1773 return;
1774 }
1775 zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1776 break;
1777 case IS_UNDEF:
1778 zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1779 case IS_DOUBLE:
1780 case IS_NULL:
1781 case IS_FALSE:
1782 case IS_TRUE:
1783 if (type != BP_VAR_IS) {
1784 zend_error(E_NOTICE, "String offset cast occurred");
1785 }
1786 break;
1787 case IS_REFERENCE:
1788 dim = Z_REFVAL_P(dim);
1789 goto try_string_offset;
1790 default:
1791 zend_error(E_WARNING, "Illegal offset type");
1792 break;
1793 }
1794
1795 offset = _zval_get_long_func(dim);
1796 } else {
1797 offset = Z_LVAL_P(dim);
1798 }
1799
1800 if (UNEXPECTED(Z_STRLEN_P(container) < (size_t)((offset < 0) ? -offset : (offset + 1)))) {
1801 if (type != BP_VAR_IS) {
1802 zend_error(E_NOTICE, "Uninitialized string offset: " ZEND_LONG_FMT, offset);
1803 ZVAL_EMPTY_STRING(result);
1804 } else {
1805 ZVAL_NULL(result);
1806 }
1807 } else {
1808 zend_uchar c;
1809 zend_long real_offset;
1810
1811 real_offset = (UNEXPECTED(offset < 0)) /* Handle negative offset */
1812 ? (zend_long)Z_STRLEN_P(container) + offset : offset;
1813 c = (zend_uchar)Z_STRVAL_P(container)[real_offset];
1814
1815 ZVAL_INTERNED_STR(result, ZSTR_CHAR(c));
1816 }
1817 } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1818 if (/*dim_type == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
1819 zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1820 dim = &EG(uninitialized_zval);
1821 }
1822 if (!Z_OBJ_HT_P(container)->read_dimension) {
1823 zend_throw_error(NULL, "Cannot use object as array");
1824 ZVAL_NULL(result);
1825 } else {
1826 retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
1827
1828 ZEND_ASSERT(result != NULL);
1829 if (retval) {
1830 if (result != retval) {
1831 ZVAL_COPY(result, retval);
1832 }
1833 } else {
1834 ZVAL_NULL(result);
1835 }
1836 }
1837 } else {
1838 if (type != BP_VAR_IS && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
1839 zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
1840 }
1841 if (/*dim_type == IS_CV &&*/ UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
1842 zval_undefined_cv(EX(opline)->op2.var EXECUTE_DATA_CC);
1843 }
1844 ZVAL_NULL(result);
1845 }
1846 }
1847
zend_fetch_dimension_address_read_R(zval * result,zval * container,zval * dim,int dim_type EXECUTE_DATA_DC)1848 static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type EXECUTE_DATA_DC)
1849 {
1850 zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R, 1, 0 EXECUTE_DATA_CC);
1851 }
1852
zend_fetch_dimension_address_read_R_slow(zval * result,zval * container,zval * dim EXECUTE_DATA_DC)1853 static zend_never_inline void zend_fetch_dimension_address_read_R_slow(zval *result, zval *container, zval *dim EXECUTE_DATA_DC)
1854 {
1855 zend_fetch_dimension_address_read(result, container, dim, IS_CV, BP_VAR_R, 1, 1 EXECUTE_DATA_CC);
1856 }
1857
zend_fetch_dimension_address_read_IS(zval * result,zval * container,zval * dim,int dim_type EXECUTE_DATA_DC)1858 static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type EXECUTE_DATA_DC)
1859 {
1860 zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS, 1, 0 EXECUTE_DATA_CC);
1861 }
1862
zend_fetch_dimension_address_read_LIST(zval * result,zval * container,zval * dim EXECUTE_DATA_DC)1863 static zend_never_inline void zend_fetch_dimension_address_read_LIST(zval *result, zval *container, zval *dim EXECUTE_DATA_DC)
1864 {
1865 zend_fetch_dimension_address_read(result, container, dim, IS_TMP_VAR, BP_VAR_R, 0, 0 EXECUTE_DATA_CC);
1866 }
1867
zend_fetch_dimension_const(zval * result,zval * container,zval * dim,int type)1868 ZEND_API void zend_fetch_dimension_const(zval *result, zval *container, zval *dim, int type)
1869 {
1870 if (type == BP_VAR_IS) {
1871 zend_fetch_dimension_address_read_IS(result, container, dim, IS_CONST NO_EXECUTE_DATA_CC);
1872 } else {
1873 zend_fetch_dimension_address_read_R(result, container, dim, IS_CONST NO_EXECUTE_DATA_CC);
1874 }
1875 }
1876
zend_fetch_property_address(zval * result,zval * container,uint32_t container_op_type,zval * prop_ptr,uint32_t prop_op_type,void ** cache_slot,int type)1877 static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type)
1878 {
1879 if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1880 do {
1881 if (Z_ISREF_P(container)) {
1882 container = Z_REFVAL_P(container);
1883 if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1884 break;
1885 }
1886 }
1887
1888 /* this should modify object only if it's empty */
1889 if (type != BP_VAR_UNSET &&
1890 EXPECTED(Z_TYPE_P(container) <= IS_FALSE ||
1891 (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0))) {
1892 zval_ptr_dtor_nogc(container);
1893 object_init(container);
1894 } else {
1895 if (container_op_type != IS_VAR || EXPECTED(!Z_ISERROR_P(container))) {
1896 zend_string *property_name = zval_get_string(prop_ptr);
1897 zend_error(E_WARNING, "Attempt to modify property '%s' of non-object", ZSTR_VAL(property_name));
1898 zend_string_release(property_name);
1899 }
1900 ZVAL_ERROR(result);
1901 return;
1902 }
1903 } while (0);
1904 }
1905 if (prop_op_type == IS_CONST &&
1906 EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) {
1907 uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
1908 zend_object *zobj = Z_OBJ_P(container);
1909 zval *retval;
1910
1911 if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
1912 retval = OBJ_PROP(zobj, prop_offset);
1913 if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
1914 ZVAL_INDIRECT(result, retval);
1915 return;
1916 }
1917 } else if (EXPECTED(zobj->properties != NULL)) {
1918 if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
1919 if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
1920 GC_REFCOUNT(zobj->properties)--;
1921 }
1922 zobj->properties = zend_array_dup(zobj->properties);
1923 }
1924 retval = zend_hash_find(zobj->properties, Z_STR_P(prop_ptr));
1925 if (EXPECTED(retval)) {
1926 ZVAL_INDIRECT(result, retval);
1927 return;
1928 }
1929 }
1930 }
1931 if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
1932 zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot);
1933 if (NULL == ptr) {
1934 if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1935 use_read_property:
1936 ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
1937 if (ptr != result) {
1938 ZVAL_INDIRECT(result, ptr);
1939 } else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
1940 ZVAL_UNREF(ptr);
1941 }
1942 } else {
1943 zend_throw_error(NULL, "Cannot access undefined property for object with overloaded property access");
1944 ZVAL_ERROR(result);
1945 }
1946 } else {
1947 ZVAL_INDIRECT(result, ptr);
1948 }
1949 } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1950 goto use_read_property;
1951 } else {
1952 zend_error(E_WARNING, "This object doesn't support property references");
1953 ZVAL_ERROR(result);
1954 }
1955 }
1956
zend_fetch_static_property_address(zval * varname,zend_uchar varname_type,znode_op op2,zend_uchar op2_type,int type EXECUTE_DATA_DC)1957 static zend_always_inline zval* zend_fetch_static_property_address(zval *varname, zend_uchar varname_type, znode_op op2, zend_uchar op2_type, int type EXECUTE_DATA_DC)
1958 {
1959 zval *retval;
1960 zend_string *name;
1961 zend_class_entry *ce;
1962
1963 if (varname_type == IS_CONST) {
1964 name = Z_STR_P(varname);
1965 } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
1966 name = Z_STR_P(varname);
1967 zend_string_addref(name);
1968 } else {
1969 if (varname_type == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
1970 zval_undefined_cv(EX(opline)->op1.var EXECUTE_DATA_CC);
1971 }
1972 name = zval_get_string(varname);
1973 }
1974
1975 if (op2_type == IS_CONST) {
1976 if (varname_type == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(varname))) != NULL)) {
1977 retval = CACHED_PTR(Z_CACHE_SLOT_P(varname) + sizeof(void*));
1978
1979 /* check if static properties were destoyed */
1980 if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
1981 if (type != BP_VAR_IS) {
1982 zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
1983 }
1984 return NULL;
1985 }
1986
1987 return retval;
1988 } else {
1989 zval *class_name = EX_CONSTANT(op2);
1990
1991 if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(class_name))) == NULL)) {
1992 ce = zend_fetch_class_by_name(Z_STR_P(class_name), class_name + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
1993 if (UNEXPECTED(ce == NULL)) {
1994 if (varname_type != IS_CONST) {
1995 zend_string_release(name);
1996 }
1997 return NULL;
1998 }
1999 CACHE_PTR(Z_CACHE_SLOT_P(class_name), ce);
2000 }
2001 }
2002 } else {
2003 if (op2_type == IS_UNUSED) {
2004 ce = zend_fetch_class(NULL, op2.num);
2005 if (UNEXPECTED(ce == NULL)) {
2006 if (varname_type != IS_CONST) {
2007 zend_string_release(name);
2008 }
2009 return NULL;
2010 }
2011 } else {
2012 ce = Z_CE_P(EX_VAR(op2.var));
2013 }
2014 if (varname_type == IS_CONST &&
2015 EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(varname)) == ce)) {
2016 retval = CACHED_PTR(Z_CACHE_SLOT_P(varname) + sizeof(void*));
2017
2018 /* check if static properties were destoyed */
2019 if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
2020 if (type != BP_VAR_IS) {
2021 zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
2022 }
2023 return NULL;
2024 }
2025
2026 return retval;
2027 }
2028 }
2029
2030 retval = zend_std_get_static_property(ce, name, type == BP_VAR_IS);
2031
2032 if (varname_type != IS_CONST) {
2033 zend_string_release(name);
2034 }
2035
2036 if (UNEXPECTED(retval == NULL)) {
2037 return NULL;
2038 }
2039
2040 if (varname_type == IS_CONST) {
2041 CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(varname), ce, retval);
2042 }
2043
2044 return retval;
2045 }
2046
2047 #if ZEND_INTENSIVE_DEBUGGING
2048
2049 #define CHECK_SYMBOL_TABLES() \
2050 zend_hash_apply(&EG(symbol_table), zend_check_symbol); \
2051 if (&EG(symbol_table)!=EX(symbol_table)) { \
2052 zend_hash_apply(EX(symbol_table), zend_check_symbol); \
2053 }
2054
zend_check_symbol(zval * pz)2055 static int zend_check_symbol(zval *pz)
2056 {
2057 if (Z_TYPE_P(pz) == IS_INDIRECT) {
2058 pz = Z_INDIRECT_P(pz);
2059 }
2060 if (Z_TYPE_P(pz) > 10) {
2061 fprintf(stderr, "Warning! %x has invalid type!\n", *pz);
2062 /* See http://support.microsoft.com/kb/190351 */
2063 #ifdef ZEND_WIN32
2064 fflush(stderr);
2065 #endif
2066 } else if (Z_TYPE_P(pz) == IS_ARRAY) {
2067 zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol);
2068 } else if (Z_TYPE_P(pz) == IS_OBJECT) {
2069 /* OBJ-TBI - doesn't support new object model! */
2070 zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol);
2071 }
2072
2073 return 0;
2074 }
2075
2076
2077 #else
2078 #define CHECK_SYMBOL_TABLES()
2079 #endif
2080
execute_internal(zend_execute_data * execute_data,zval * return_value)2081 ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value)
2082 {
2083 execute_data->func->internal_function.handler(execute_data, return_value);
2084 }
2085
zend_clean_and_cache_symbol_table(zend_array * symbol_table)2086 ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{ */
2087 {
2088 if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
2089 zend_array_destroy(symbol_table);
2090 } else {
2091 /* clean before putting into the cache, since clean
2092 could call dtors, which could use cached hash */
2093 zend_symtable_clean(symbol_table);
2094 *(++EG(symtable_cache_ptr)) = symbol_table;
2095 }
2096 }
2097 /* }}} */
2098
i_free_compiled_variables(zend_execute_data * execute_data)2099 static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
2100 {
2101 zval *cv = EX_VAR_NUM(0);
2102 zval *end = cv + EX(func)->op_array.last_var;
2103 while (EXPECTED(cv != end)) {
2104 if (Z_REFCOUNTED_P(cv)) {
2105 zend_refcounted *r = Z_COUNTED_P(cv);
2106 if (!--GC_REFCOUNT(r)) {
2107 ZVAL_NULL(cv);
2108 zval_dtor_func(r);
2109 } else {
2110 gc_check_possible_root(r);
2111 }
2112 }
2113 cv++;
2114 }
2115 }
2116 /* }}} */
2117
zend_free_compiled_variables(zend_execute_data * execute_data)2118 void zend_free_compiled_variables(zend_execute_data *execute_data) /* {{{ */
2119 {
2120 i_free_compiled_variables(execute_data);
2121 }
2122 /* }}} */
2123
2124 #define ZEND_VM_INTERRUPT_CHECK() do { \
2125 if (UNEXPECTED(EG(vm_interrupt))) { \
2126 ZEND_VM_INTERRUPT(); \
2127 } \
2128 } while (0)
2129
2130 #define ZEND_VM_LOOP_INTERRUPT_CHECK() do { \
2131 if (UNEXPECTED(EG(vm_interrupt))) { \
2132 ZEND_VM_LOOP_INTERRUPT(); \
2133 } \
2134 } while (0)
2135
2136 /*
2137 * Stack Frame Layout (the whole stack frame is allocated at once)
2138 * ==================
2139 *
2140 * +========================================+
2141 * EG(current_execute_data) -> | zend_execute_data |
2142 * +----------------------------------------+
2143 * EX_CV_NUM(0) ---------> | VAR[0] = ARG[1] |
2144 * | ... |
2145 * | VAR[op_array->num_args-1] = ARG[N] |
2146 * | ... |
2147 * | VAR[op_array->last_var-1] |
2148 * | VAR[op_array->last_var] = TMP[0] |
2149 * | ... |
2150 * | VAR[op_array->last_var+op_array->T-1] |
2151 * | ARG[N+1] (extra_args) |
2152 * | ... |
2153 * +----------------------------------------+
2154 */
2155
i_init_func_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2156 static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2157 {
2158 uint32_t first_extra_arg, num_args;
2159 ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2160
2161 EX(opline) = op_array->opcodes;
2162 EX(call) = NULL;
2163 EX(return_value) = return_value;
2164
2165 /* Handle arguments */
2166 first_extra_arg = op_array->num_args;
2167 num_args = EX_NUM_ARGS();
2168 if (UNEXPECTED(num_args > first_extra_arg)) {
2169 if (EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
2170 zval *end, *src, *dst;
2171 uint32_t type_flags = 0;
2172
2173 if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2174 /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2175 EX(opline) += first_extra_arg;
2176 }
2177
2178 /* move extra args into separate array after all CV and TMP vars */
2179 end = EX_VAR_NUM(first_extra_arg - 1);
2180 src = end + (num_args - first_extra_arg);
2181 dst = src + (op_array->last_var + op_array->T - first_extra_arg);
2182 if (EXPECTED(src != dst)) {
2183 do {
2184 type_flags |= Z_TYPE_INFO_P(src);
2185 ZVAL_COPY_VALUE(dst, src);
2186 ZVAL_UNDEF(src);
2187 src--;
2188 dst--;
2189 } while (src != end);
2190 } else {
2191 do {
2192 type_flags |= Z_TYPE_INFO_P(src);
2193 src--;
2194 } while (src != end);
2195 }
2196 ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
2197 }
2198 } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2199 /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
2200 EX(opline) += num_args;
2201 }
2202
2203 /* Initialize CV variables (skip arguments) */
2204 if (EXPECTED((int)num_args < op_array->last_var)) {
2205 zval *var = EX_VAR_NUM(num_args);
2206 zval *end = EX_VAR_NUM(op_array->last_var);
2207
2208 do {
2209 ZVAL_UNDEF(var);
2210 var++;
2211 } while (var != end);
2212 }
2213
2214 EX_LOAD_RUN_TIME_CACHE(op_array);
2215 EX_LOAD_LITERALS(op_array);
2216
2217 EG(current_execute_data) = execute_data;
2218 }
2219 /* }}} */
2220
init_func_run_time_cache(zend_op_array * op_array)2221 static zend_never_inline void ZEND_FASTCALL init_func_run_time_cache(zend_op_array *op_array) /* {{{ */
2222 {
2223 ZEND_ASSERT(op_array->run_time_cache == NULL);
2224 op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2225 memset(op_array->run_time_cache, 0, op_array->cache_size);
2226 }
2227 /* }}} */
2228
i_init_code_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2229 static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2230 {
2231 ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2232
2233 EX(opline) = op_array->opcodes;
2234 EX(call) = NULL;
2235 EX(return_value) = return_value;
2236
2237 zend_attach_symbol_table(execute_data);
2238
2239 if (!op_array->run_time_cache) {
2240 op_array->run_time_cache = emalloc(op_array->cache_size);
2241 memset(op_array->run_time_cache, 0, op_array->cache_size);
2242 }
2243 EX_LOAD_RUN_TIME_CACHE(op_array);
2244 EX_LOAD_LITERALS(op_array);
2245
2246 EG(current_execute_data) = execute_data;
2247 }
2248 /* }}} */
2249
zend_init_func_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2250 ZEND_API void zend_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2251 {
2252 EX(prev_execute_data) = EG(current_execute_data);
2253 if (!op_array->run_time_cache) {
2254 op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2255 memset(op_array->run_time_cache, 0, op_array->cache_size);
2256 }
2257 i_init_func_execute_data(execute_data, op_array, return_value);
2258 }
2259 /* }}} */
2260
zend_init_code_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2261 ZEND_API void zend_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2262 {
2263 EX(prev_execute_data) = EG(current_execute_data);
2264 if (!op_array->run_time_cache) {
2265 op_array->run_time_cache = emalloc(op_array->cache_size);
2266 memset(op_array->run_time_cache, 0, op_array->cache_size);
2267 }
2268 i_init_code_execute_data(execute_data, op_array, return_value);
2269 }
2270 /* }}} */
2271
zend_init_execute_data(zend_execute_data * execute_data,zend_op_array * op_array,zval * return_value)2272 ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
2273 {
2274 if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
2275 zend_init_code_execute_data(execute_data, op_array, return_value);
2276 } else {
2277 zend_init_func_execute_data(execute_data, op_array, return_value);
2278 }
2279 }
2280 /* }}} */
2281
zend_is_by_ref_func_arg_fetch(const zend_op * opline,zend_execute_data * call)2282 static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call) /* {{{ */
2283 {
2284 uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
2285
2286 if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) {
2287 return QUICK_ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
2288 }
2289 return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
2290 }
2291 /* }}} */
2292
zend_vm_stack_copy_call_frame(zend_execute_data * call,uint32_t passed_args,uint32_t additional_args)2293 static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
2294 {
2295 zend_execute_data *new_call;
2296 int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
2297
2298 /* copy call frame into new stack segment */
2299 new_call = zend_vm_stack_extend(used_stack * sizeof(zval));
2300 *new_call = *call;
2301 ZEND_ADD_CALL_FLAG(new_call, ZEND_CALL_ALLOCATED);
2302
2303 if (passed_args) {
2304 zval *src = ZEND_CALL_ARG(call, 1);
2305 zval *dst = ZEND_CALL_ARG(new_call, 1);
2306 do {
2307 ZVAL_COPY_VALUE(dst, src);
2308 passed_args--;
2309 src++;
2310 dst++;
2311 } while (passed_args);
2312 }
2313
2314 /* delete old call_frame from previous stack segment */
2315 EG(vm_stack)->prev->top = (zval*)call;
2316
2317 /* delete previous stack segment if it becames empty */
2318 if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMENTS(EG(vm_stack)->prev))) {
2319 zend_vm_stack r = EG(vm_stack)->prev;
2320
2321 EG(vm_stack)->prev = r->prev;
2322 efree(r);
2323 }
2324
2325 return new_call;
2326 }
2327 /* }}} */
2328
zend_vm_stack_extend_call_frame(zend_execute_data ** call,uint32_t passed_args,uint32_t additional_args)2329 static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args) /* {{{ */
2330 {
2331 if (EXPECTED((uint32_t)(EG(vm_stack_end) - EG(vm_stack_top)) > additional_args)) {
2332 EG(vm_stack_top) += additional_args;
2333 } else {
2334 *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args);
2335 }
2336 }
2337 /* }}} */
2338
zend_get_running_generator(EXECUTE_DATA_D)2339 static zend_always_inline zend_generator *zend_get_running_generator(EXECUTE_DATA_D) /* {{{ */
2340 {
2341 /* The generator object is stored in EX(return_value) */
2342 zend_generator *generator = (zend_generator *) EX(return_value);
2343 /* However control may currently be delegated to another generator.
2344 * That's the one we're interested in. */
2345 return generator;
2346 }
2347 /* }}} */
2348
cleanup_unfinished_calls(zend_execute_data * execute_data,uint32_t op_num)2349 static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t op_num) /* {{{ */
2350 {
2351 if (UNEXPECTED(EX(call))) {
2352 zend_execute_data *call = EX(call);
2353 zend_op *opline = EX(func)->op_array.opcodes + op_num;
2354 int level;
2355 int do_exit;
2356
2357 if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
2358 opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
2359 opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
2360 opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
2361 opline->opcode == ZEND_INIT_USER_CALL ||
2362 opline->opcode == ZEND_INIT_METHOD_CALL ||
2363 opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
2364 opline->opcode == ZEND_NEW)) {
2365 ZEND_ASSERT(op_num);
2366 opline--;
2367 }
2368
2369 do {
2370 /* If the exception was thrown during a function call there might be
2371 * arguments pushed to the stack that have to be dtor'ed. */
2372
2373 /* find the number of actually passed arguments */
2374 level = 0;
2375 do_exit = 0;
2376 do {
2377 switch (opline->opcode) {
2378 case ZEND_DO_FCALL:
2379 case ZEND_DO_ICALL:
2380 case ZEND_DO_UCALL:
2381 case ZEND_DO_FCALL_BY_NAME:
2382 level++;
2383 break;
2384 case ZEND_INIT_FCALL:
2385 case ZEND_INIT_FCALL_BY_NAME:
2386 case ZEND_INIT_NS_FCALL_BY_NAME:
2387 case ZEND_INIT_DYNAMIC_CALL:
2388 case ZEND_INIT_USER_CALL:
2389 case ZEND_INIT_METHOD_CALL:
2390 case ZEND_INIT_STATIC_METHOD_CALL:
2391 case ZEND_NEW:
2392 if (level == 0) {
2393 ZEND_CALL_NUM_ARGS(call) = 0;
2394 do_exit = 1;
2395 }
2396 level--;
2397 break;
2398 case ZEND_SEND_VAL:
2399 case ZEND_SEND_VAL_EX:
2400 case ZEND_SEND_VAR:
2401 case ZEND_SEND_VAR_EX:
2402 case ZEND_SEND_REF:
2403 case ZEND_SEND_VAR_NO_REF:
2404 case ZEND_SEND_VAR_NO_REF_EX:
2405 case ZEND_SEND_USER:
2406 if (level == 0) {
2407 ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
2408 do_exit = 1;
2409 }
2410 break;
2411 case ZEND_SEND_ARRAY:
2412 case ZEND_SEND_UNPACK:
2413 if (level == 0) {
2414 do_exit = 1;
2415 }
2416 break;
2417 }
2418 if (!do_exit) {
2419 opline--;
2420 }
2421 } while (!do_exit);
2422 if (call->prev_execute_data) {
2423 /* skip current call region */
2424 level = 0;
2425 do_exit = 0;
2426 do {
2427 switch (opline->opcode) {
2428 case ZEND_DO_FCALL:
2429 case ZEND_DO_ICALL:
2430 case ZEND_DO_UCALL:
2431 case ZEND_DO_FCALL_BY_NAME:
2432 level++;
2433 break;
2434 case ZEND_INIT_FCALL:
2435 case ZEND_INIT_FCALL_BY_NAME:
2436 case ZEND_INIT_NS_FCALL_BY_NAME:
2437 case ZEND_INIT_DYNAMIC_CALL:
2438 case ZEND_INIT_USER_CALL:
2439 case ZEND_INIT_METHOD_CALL:
2440 case ZEND_INIT_STATIC_METHOD_CALL:
2441 case ZEND_NEW:
2442 if (level == 0) {
2443 do_exit = 1;
2444 }
2445 level--;
2446 break;
2447 }
2448 opline--;
2449 } while (!do_exit);
2450 }
2451
2452 zend_vm_stack_free_args(EX(call));
2453
2454 if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
2455 if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
2456 GC_REFCOUNT(Z_OBJ(call->This))--;
2457 if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
2458 zend_object_store_ctor_failed(Z_OBJ(call->This));
2459 }
2460 }
2461 OBJ_RELEASE(Z_OBJ(call->This));
2462 }
2463 if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2464 zend_object_release((zend_object *) call->func->common.prototype);
2465 } else if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2466 zend_string_release(call->func->common.function_name);
2467 zend_free_trampoline(call->func);
2468 }
2469
2470 EX(call) = call->prev_execute_data;
2471 zend_vm_stack_free_call_frame(call);
2472 call = EX(call);
2473 } while (call);
2474 }
2475 }
2476 /* }}} */
2477
cleanup_live_vars(zend_execute_data * execute_data,uint32_t op_num,uint32_t catch_op_num)2478 static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) /* {{{ */
2479 {
2480 int i;
2481
2482 for (i = 0; i < EX(func)->op_array.last_live_range; i++) {
2483 const zend_live_range *range = &EX(func)->op_array.live_range[i];
2484 if (range->start > op_num) {
2485 /* further blocks will not be relevant... */
2486 break;
2487 } else if (op_num < range->end) {
2488 if (!catch_op_num || catch_op_num >= range->end) {
2489 uint32_t kind = range->var & ZEND_LIVE_MASK;
2490 uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
2491 zval *var = EX_VAR(var_num);
2492
2493 if (kind == ZEND_LIVE_TMPVAR) {
2494 zval_ptr_dtor_nogc(var);
2495 } else if (kind == ZEND_LIVE_LOOP) {
2496 if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
2497 zend_hash_iterator_del(Z_FE_ITER_P(var));
2498 }
2499 zval_ptr_dtor_nogc(var);
2500 } else if (kind == ZEND_LIVE_ROPE) {
2501 zend_string **rope = (zend_string **)var;
2502 zend_op *last = EX(func)->op_array.opcodes + op_num;
2503 while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
2504 || last->result.var != var_num) {
2505 ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
2506 last--;
2507 }
2508 if (last->opcode == ZEND_ROPE_INIT) {
2509 zend_string_release(*rope);
2510 } else {
2511 int j = last->extended_value;
2512 do {
2513 zend_string_release(rope[j]);
2514 } while (j--);
2515 }
2516 } else if (kind == ZEND_LIVE_SILENCE) {
2517 /* restore previous error_reporting value */
2518 if (!EG(error_reporting) && Z_LVAL_P(var) != 0) {
2519 EG(error_reporting) = Z_LVAL_P(var);
2520 }
2521 }
2522 }
2523 }
2524 }
2525 }
2526 /* }}} */
2527
zend_cleanup_unfinished_execution(zend_execute_data * execute_data,uint32_t op_num,uint32_t catch_op_num)2528 void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) {
2529 cleanup_unfinished_calls(execute_data, op_num);
2530 cleanup_live_vars(execute_data, op_num, catch_op_num);
2531 }
2532
zend_swap_operands(zend_op * op)2533 static void zend_swap_operands(zend_op *op) /* {{{ */
2534 {
2535 znode_op tmp;
2536 zend_uchar tmp_type;
2537
2538 tmp = op->op1;
2539 tmp_type = op->op1_type;
2540 op->op1 = op->op2;
2541 op->op1_type = op->op2_type;
2542 op->op2 = tmp;
2543 op->op2_type = tmp_type;
2544 }
2545 /* }}} */
2546
zend_init_dynamic_call_string(zend_string * function,uint32_t num_args)2547 static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_string *function, uint32_t num_args) /* {{{ */
2548 {
2549 zend_function *fbc;
2550 zval *func;
2551 zend_class_entry *called_scope;
2552 zend_string *lcname;
2553 const char *colon;
2554
2555 if ((colon = zend_memrchr(ZSTR_VAL(function), ':', ZSTR_LEN(function))) != NULL &&
2556 colon > ZSTR_VAL(function) &&
2557 *(colon-1) == ':'
2558 ) {
2559 zend_string *mname;
2560 size_t cname_length = colon - ZSTR_VAL(function) - 1;
2561 size_t mname_length = ZSTR_LEN(function) - cname_length - (sizeof("::") - 1);
2562
2563 lcname = zend_string_init(ZSTR_VAL(function), cname_length, 0);
2564
2565 called_scope = zend_fetch_class_by_name(lcname, NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
2566 if (UNEXPECTED(called_scope == NULL)) {
2567 zend_string_release(lcname);
2568 return NULL;
2569 }
2570
2571 mname = zend_string_init(ZSTR_VAL(function) + (cname_length + sizeof("::") - 1), mname_length, 0);
2572
2573 if (called_scope->get_static_method) {
2574 fbc = called_scope->get_static_method(called_scope, mname);
2575 } else {
2576 fbc = zend_std_get_static_method(called_scope, mname, NULL);
2577 }
2578 if (UNEXPECTED(fbc == NULL)) {
2579 if (EXPECTED(!EG(exception))) {
2580 zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(called_scope->name), ZSTR_VAL(mname));
2581 }
2582 zend_string_release(lcname);
2583 zend_string_release(mname);
2584 return NULL;
2585 }
2586
2587 zend_string_release(lcname);
2588 zend_string_release(mname);
2589
2590 if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
2591 if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2592 zend_error(E_DEPRECATED,
2593 "Non-static method %s::%s() should not be called statically",
2594 ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
2595 if (UNEXPECTED(EG(exception) != NULL)) {
2596 return NULL;
2597 }
2598 } else {
2599 zend_throw_error(
2600 zend_ce_error,
2601 "Non-static method %s::%s() cannot be called statically",
2602 ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
2603 return NULL;
2604 }
2605 }
2606 } else {
2607 if (ZSTR_VAL(function)[0] == '\\') {
2608 lcname = zend_string_alloc(ZSTR_LEN(function) - 1, 0);
2609 zend_str_tolower_copy(ZSTR_VAL(lcname), ZSTR_VAL(function) + 1, ZSTR_LEN(function) - 1);
2610 } else {
2611 lcname = zend_string_tolower(function);
2612 }
2613 if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
2614 zend_throw_error(NULL, "Call to undefined function %s()", ZSTR_VAL(function));
2615 zend_string_release(lcname);
2616 return NULL;
2617 }
2618 zend_string_release(lcname);
2619
2620 fbc = Z_FUNC_P(func);
2621 called_scope = NULL;
2622 }
2623
2624 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
2625 init_func_run_time_cache(&fbc->op_array);
2626 }
2627
2628 return zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC,
2629 fbc, num_args, called_scope, NULL);
2630 }
2631 /* }}} */
2632
zend_init_dynamic_call_object(zval * function,uint32_t num_args)2633 static zend_never_inline zend_execute_data *zend_init_dynamic_call_object(zval *function, uint32_t num_args) /* {{{ */
2634 {
2635 zend_function *fbc;
2636 zend_class_entry *called_scope;
2637 zend_object *object;
2638 uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
2639
2640 if (EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)) &&
2641 EXPECTED(Z_OBJ_HANDLER_P(function, get_closure)(function, &called_scope, &fbc, &object) == SUCCESS)) {
2642
2643 if (fbc->common.fn_flags & ZEND_ACC_CLOSURE) {
2644 /* Delay closure destruction until its invocation */
2645 ZEND_ASSERT(GC_TYPE((zend_object*)fbc->common.prototype) == IS_OBJECT);
2646 GC_REFCOUNT((zend_object*)fbc->common.prototype)++;
2647 call_info |= ZEND_CALL_CLOSURE;
2648 if (fbc->common.fn_flags & ZEND_ACC_FAKE_CLOSURE) {
2649 call_info |= ZEND_CALL_FAKE_CLOSURE;
2650 }
2651 } else if (object) {
2652 call_info |= ZEND_CALL_RELEASE_THIS;
2653 GC_REFCOUNT(object)++; /* For $this pointer */
2654 }
2655 } else {
2656 zend_throw_error(NULL, "Function name must be a string");
2657 return NULL;
2658 }
2659
2660 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
2661 init_func_run_time_cache(&fbc->op_array);
2662 }
2663
2664 return zend_vm_stack_push_call_frame(call_info,
2665 fbc, num_args, called_scope, object);
2666 }
2667 /* }}} */
2668
zend_init_dynamic_call_array(zend_array * function,uint32_t num_args)2669 static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_array *function, uint32_t num_args) /* {{{ */
2670 {
2671 zend_function *fbc;
2672 zend_class_entry *called_scope;
2673 zend_object *object;
2674 uint32_t call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_DYNAMIC;
2675
2676 if (zend_hash_num_elements(function) == 2) {
2677 zval *obj;
2678 zval *method;
2679 obj = zend_hash_index_find(function, 0);
2680 method = zend_hash_index_find(function, 1);
2681
2682 if (UNEXPECTED(!obj) || UNEXPECTED(!method)) {
2683 zend_throw_error(NULL, "Array callback has to contain indices 0 and 1");
2684 return NULL;
2685 }
2686
2687 ZVAL_DEREF(obj);
2688 if (UNEXPECTED(Z_TYPE_P(obj) != IS_STRING) && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT)) {
2689 zend_throw_error(NULL, "First array member is not a valid class name or object");
2690 return NULL;
2691 }
2692
2693 ZVAL_DEREF(method);
2694 if (UNEXPECTED(Z_TYPE_P(method) != IS_STRING)) {
2695 zend_throw_error(NULL, "Second array member is not a valid method");
2696 return NULL;
2697 }
2698
2699 if (Z_TYPE_P(obj) == IS_STRING) {
2700 object = NULL;
2701 called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
2702 if (UNEXPECTED(called_scope == NULL)) {
2703 return NULL;
2704 }
2705
2706 if (called_scope->get_static_method) {
2707 fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
2708 } else {
2709 fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
2710 }
2711 if (UNEXPECTED(fbc == NULL)) {
2712 if (EXPECTED(!EG(exception))) {
2713 zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(called_scope->name), Z_STRVAL_P(method));
2714 }
2715 return NULL;
2716 }
2717 if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
2718 if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
2719 zend_error(E_DEPRECATED,
2720 "Non-static method %s::%s() should not be called statically",
2721 ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
2722 if (UNEXPECTED(EG(exception) != NULL)) {
2723 return NULL;
2724 }
2725 } else {
2726 zend_throw_error(
2727 zend_ce_error,
2728 "Non-static method %s::%s() cannot be called statically",
2729 ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
2730 return NULL;
2731 }
2732 }
2733 } else {
2734 called_scope = Z_OBJCE_P(obj);
2735 object = Z_OBJ_P(obj);
2736
2737 fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
2738 if (UNEXPECTED(fbc == NULL)) {
2739 if (EXPECTED(!EG(exception))) {
2740 zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(object->ce->name), Z_STRVAL_P(method));
2741 }
2742 return NULL;
2743 }
2744
2745 if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
2746 object = NULL;
2747 } else {
2748 call_info |= ZEND_CALL_RELEASE_THIS;
2749 GC_REFCOUNT(object)++; /* For $this pointer */
2750 }
2751 }
2752 } else {
2753 zend_throw_error(NULL, "Function name must be a string");
2754 return NULL;
2755 }
2756
2757 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!fbc->op_array.run_time_cache)) {
2758 init_func_run_time_cache(&fbc->op_array);
2759 }
2760
2761 return zend_vm_stack_push_call_frame(call_info,
2762 fbc, num_args, called_scope, object);
2763 }
2764 /* }}} */
2765
2766 #define ZEND_FAKE_OP_ARRAY ((zend_op_array*)(zend_intptr_t)-1)
2767
zend_include_or_eval(zval * inc_filename,int type)2768 static zend_never_inline zend_op_array* ZEND_FASTCALL zend_include_or_eval(zval *inc_filename, int type) /* {{{ */
2769 {
2770 zend_op_array *new_op_array = NULL;
2771 zval tmp_inc_filename;
2772
2773 ZVAL_UNDEF(&tmp_inc_filename);
2774 if (Z_TYPE_P(inc_filename) != IS_STRING) {
2775 ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
2776 inc_filename = &tmp_inc_filename;
2777 }
2778
2779 if (type != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
2780 if (type == ZEND_INCLUDE_ONCE || type == ZEND_INCLUDE) {
2781 zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
2782 } else {
2783 zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
2784 }
2785 } else {
2786 switch (type) {
2787 case ZEND_INCLUDE_ONCE:
2788 case ZEND_REQUIRE_ONCE: {
2789 zend_file_handle file_handle;
2790 zend_string *resolved_path;
2791
2792 resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename));
2793 if (resolved_path) {
2794 if (zend_hash_exists(&EG(included_files), resolved_path)) {
2795 goto already_compiled;
2796 }
2797 } else {
2798 resolved_path = zend_string_copy(Z_STR_P(inc_filename));
2799 }
2800
2801 if (SUCCESS == zend_stream_open(ZSTR_VAL(resolved_path), &file_handle)) {
2802
2803 if (!file_handle.opened_path) {
2804 file_handle.opened_path = zend_string_copy(resolved_path);
2805 }
2806
2807 if (zend_hash_add_empty_element(&EG(included_files), file_handle.opened_path)) {
2808 zend_op_array *op_array = zend_compile_file(&file_handle, (type==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE));
2809 zend_destroy_file_handle(&file_handle);
2810 zend_string_release(resolved_path);
2811 if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
2812 zend_string_release(Z_STR(tmp_inc_filename));
2813 }
2814 return op_array;
2815 } else {
2816 zend_file_handle_dtor(&file_handle);
2817 already_compiled:
2818 new_op_array = ZEND_FAKE_OP_ARRAY;
2819 }
2820 } else {
2821 if (type == ZEND_INCLUDE_ONCE) {
2822 zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
2823 } else {
2824 zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
2825 }
2826 }
2827 zend_string_release(resolved_path);
2828 }
2829 break;
2830 case ZEND_INCLUDE:
2831 case ZEND_REQUIRE:
2832 new_op_array = compile_filename(type, inc_filename);
2833 break;
2834 case ZEND_EVAL: {
2835 char *eval_desc = zend_make_compiled_string_description("eval()'d code");
2836 new_op_array = zend_compile_string(inc_filename, eval_desc);
2837 efree(eval_desc);
2838 }
2839 break;
2840 EMPTY_SWITCH_DEFAULT_CASE()
2841 }
2842 }
2843 if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
2844 zend_string_release(Z_STR(tmp_inc_filename));
2845 }
2846 return new_op_array;
2847 }
2848 /* }}} */
2849
zend_do_fcall_overloaded(zend_execute_data * call,zval * ret)2850 ZEND_API int ZEND_FASTCALL zend_do_fcall_overloaded(zend_execute_data *call, zval *ret) /* {{{ */
2851 {
2852 zend_function *fbc = call->func;
2853 zend_object *object;
2854
2855 /* Not sure what should be done here if it's a static method */
2856 if (UNEXPECTED(Z_TYPE(call->This) != IS_OBJECT)) {
2857 zend_vm_stack_free_args(call);
2858 if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
2859 zend_string_release(fbc->common.function_name);
2860 }
2861 efree(fbc);
2862 zend_vm_stack_free_call_frame(call);
2863
2864 zend_throw_error(NULL, "Cannot call overloaded function for non-object");
2865 return 0;
2866 }
2867
2868 object = Z_OBJ(call->This);
2869
2870 ZVAL_NULL(ret);
2871
2872 EG(current_execute_data) = call;
2873 object->handlers->call_method(fbc->common.function_name, object, call, ret);
2874 EG(current_execute_data) = call->prev_execute_data;
2875
2876 zend_vm_stack_free_args(call);
2877
2878 if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
2879 zend_string_release(fbc->common.function_name);
2880 }
2881 efree(fbc);
2882
2883 return 1;
2884 }
2885 /* }}} */
2886
2887 #define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
2888 CHECK_SYMBOL_TABLES() \
2889 if (check_exception) { \
2890 OPLINE = EX(opline) + (skip); \
2891 } else { \
2892 OPLINE = opline + (skip); \
2893 } \
2894 ZEND_VM_CONTINUE()
2895
2896 #define ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() \
2897 ZEND_VM_NEXT_OPCODE_EX(1, 1)
2898
2899 #define ZEND_VM_NEXT_OPCODE() \
2900 ZEND_VM_NEXT_OPCODE_EX(0, 1)
2901
2902 #define ZEND_VM_SET_NEXT_OPCODE(new_op) \
2903 CHECK_SYMBOL_TABLES() \
2904 OPLINE = new_op
2905
2906 #define ZEND_VM_SET_OPCODE(new_op) \
2907 CHECK_SYMBOL_TABLES() \
2908 OPLINE = new_op; \
2909 ZEND_VM_INTERRUPT_CHECK()
2910
2911 #define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
2912 ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset))
2913
2914 #define ZEND_VM_JMP(new_op) do { \
2915 if (UNEXPECTED(EG(exception))) { \
2916 HANDLE_EXCEPTION(); \
2917 } \
2918 ZEND_VM_SET_OPCODE(new_op); \
2919 ZEND_VM_CONTINUE(); \
2920 } while (0)
2921
2922 #define ZEND_VM_INC_OPCODE() \
2923 OPLINE++
2924
2925
2926 #ifndef VM_SMART_OPCODES
2927 # define VM_SMART_OPCODES 1
2928 #endif
2929
2930 #if VM_SMART_OPCODES
2931 # define ZEND_VM_REPEATABLE_OPCODE \
2932 do {
2933 # define ZEND_VM_REPEAT_OPCODE(_opcode) \
2934 } while (UNEXPECTED((++opline)->opcode == _opcode)); \
2935 OPLINE = opline; \
2936 ZEND_VM_CONTINUE()
2937 # define ZEND_VM_SMART_BRANCH(_result, _check) do { \
2938 int __result; \
2939 if (EXPECTED((opline+1)->opcode == ZEND_JMPZ)) { \
2940 __result = (_result); \
2941 } else if (EXPECTED((opline+1)->opcode == ZEND_JMPNZ)) { \
2942 __result = !(_result); \
2943 } else { \
2944 break; \
2945 } \
2946 if ((_check) && UNEXPECTED(EG(exception))) { \
2947 ZVAL_UNDEF(EX_VAR(opline->result.var)); \
2948 HANDLE_EXCEPTION(); \
2949 } \
2950 if (__result) { \
2951 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
2952 } else { \
2953 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
2954 } \
2955 ZEND_VM_CONTINUE(); \
2956 } while (0)
2957 # define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check) do { \
2958 if ((_check) && UNEXPECTED(EG(exception))) { \
2959 ZVAL_UNDEF(EX_VAR(opline->result.var)); \
2960 HANDLE_EXCEPTION(); \
2961 } \
2962 if (_result) { \
2963 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
2964 } else { \
2965 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
2966 } \
2967 ZEND_VM_CONTINUE(); \
2968 } while (0)
2969 # define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check) do { \
2970 if ((_check) && UNEXPECTED(EG(exception))) { \
2971 ZVAL_UNDEF(EX_VAR(opline->result.var)); \
2972 HANDLE_EXCEPTION(); \
2973 } \
2974 if (!(_result)) { \
2975 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
2976 } else { \
2977 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
2978 } \
2979 ZEND_VM_CONTINUE(); \
2980 } while (0)
2981 #else
2982 # define ZEND_VM_REPEATABLE_OPCODE
2983 # define ZEND_VM_REPEAT_OPCODE(_opcode)
2984 # define ZEND_VM_SMART_BRANCH(_result, _check)
2985 # define ZEND_VM_SMART_BRANCH_JMPZ(_result, _check)
2986 # define ZEND_VM_SMART_BRANCH_JMPNZ(_result, _check)
2987 #endif
2988
2989 #ifdef __GNUC__
2990 # define ZEND_VM_GUARD(name) __asm__("#" #name)
2991 #else
2992 # define ZEND_VM_GUARD(name)
2993 #endif
2994
2995 #define GET_OP1_UNDEF_CV(ptr, type) \
2996 _get_zval_cv_lookup_ ## type(ptr, opline->op1.var EXECUTE_DATA_CC)
2997 #define GET_OP2_UNDEF_CV(ptr, type) \
2998 _get_zval_cv_lookup_ ## type(ptr, opline->op2.var EXECUTE_DATA_CC)
2999
3000 #define UNDEF_RESULT() do { \
3001 if (opline->result_type & (IS_VAR | IS_TMP_VAR)) { \
3002 ZVAL_UNDEF(EX_VAR(opline->result.var)); \
3003 } \
3004 } while (0)
3005
3006 #include "zend_vm_execute.h"
3007
zend_set_user_opcode_handler(zend_uchar opcode,user_opcode_handler_t handler)3008 ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
3009 {
3010 if (opcode != ZEND_USER_OPCODE) {
3011 if (handler == NULL) {
3012 /* restore the original handler */
3013 zend_user_opcodes[opcode] = opcode;
3014 } else {
3015 zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
3016 }
3017 zend_user_opcode_handlers[opcode] = handler;
3018 return SUCCESS;
3019 }
3020 return FAILURE;
3021 }
3022
zend_get_user_opcode_handler(zend_uchar opcode)3023 ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
3024 {
3025 return zend_user_opcode_handlers[opcode];
3026 }
3027
zend_get_zval_ptr(int op_type,const znode_op * node,const zend_execute_data * execute_data,zend_free_op * should_free,int type)3028 ZEND_API zval *zend_get_zval_ptr(int op_type, const znode_op *node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
3029 {
3030 zval *ret;
3031
3032 switch (op_type) {
3033 case IS_CONST:
3034 ret = EX_CONSTANT(*node);
3035 *should_free = NULL;
3036 break;
3037 case IS_TMP_VAR:
3038 case IS_VAR:
3039 ret = EX_VAR(node->var);
3040 *should_free = ret;
3041 break;
3042 case IS_CV:
3043 ret = EX_VAR(node->var);
3044 *should_free = NULL;
3045 break;
3046 default:
3047 ret = NULL;
3048 *should_free = ret;
3049 break;
3050 }
3051 return ret;
3052 }
3053
zend_check_internal_arg_type(zend_function * zf,uint32_t arg_num,zval * arg)3054 ZEND_API void ZEND_FASTCALL zend_check_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
3055 {
3056 void *dummy_cache_slot = NULL;
3057
3058 zend_verify_arg_type(zf, arg_num, arg, NULL, &dummy_cache_slot);
3059 }
3060
zend_check_arg_type(zend_function * zf,uint32_t arg_num,zval * arg,zval * default_value,void ** cache_slot)3061 ZEND_API int ZEND_FASTCALL zend_check_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
3062 {
3063 return zend_verify_arg_type(zf, arg_num, arg, default_value, cache_slot);
3064 }
3065
3066 /*
3067 * Local variables:
3068 * tab-width: 4
3069 * c-basic-offset: 4
3070 * indent-tabs-mode: t
3071 * End:
3072 * vim600: sw=4 ts=4 fdm=marker
3073 * vim<600: sw=4 ts=4
3074 */
3075