This source file includes following definitions.
- ZEND_FUNCTION
- zend_vm_stack_new_page
- zend_vm_stack_init
- zend_vm_stack_destroy
- zend_vm_stack_extend
- zend_get_compiled_variable_value
- _get_zval_ptr_tmp
- _get_zval_ptr_var
- _get_zval_ptr_var_deref
- zval_undefined_cv
- _get_zval_cv_lookup
- _get_zval_cv_lookup_BP_VAR_R
- _get_zval_cv_lookup_BP_VAR_UNSET
- _get_zval_cv_lookup_BP_VAR_RW
- _get_zval_cv_lookup_BP_VAR_W
- _get_zval_ptr_cv
- _get_zval_ptr_cv_undef
- _get_zval_ptr_cv_deref
- _get_zval_ptr_cv_BP_VAR_R
- _get_zval_ptr_cv_deref_BP_VAR_R
- _get_zval_ptr_cv_BP_VAR_UNSET
- _get_zval_ptr_cv_deref_BP_VAR_UNSET
- _get_zval_ptr_cv_BP_VAR_IS
- _get_zval_ptr_cv_deref_BP_VAR_IS
- _get_zval_ptr_cv_BP_VAR_RW
- _get_zval_ptr_cv_deref_BP_VAR_RW
- _get_zval_ptr_cv_BP_VAR_W
- _get_zval_ptr_cv_undef_BP_VAR_W
- _get_zval_ptr_cv_undef_BP_VAR_RW
- _get_zval_ptr_cv_deref_BP_VAR_W
- _get_zval_ptr
- _get_zval_ptr_r
- _get_zval_ptr_deref
- _get_zval_ptr_r_deref
- _get_zval_ptr_undef
- _get_zval_ptr_ptr_var
- _get_zval_ptr_ptr
- _get_obj_zval_ptr_unused
- _get_obj_zval_ptr
- _get_obj_zval_ptr_undef
- _get_obj_zval_ptr_ptr
- zend_assign_to_variable_reference
- make_real_object
- zend_verify_internal_arg_class_kind
- zend_verify_arg_class_kind
- zend_verify_arg_error
- is_null_constant
- zend_verify_weak_scalar_type_hint
- zend_verify_scalar_type_hint
- zend_verify_internal_arg_type
- zend_verify_arg_type
- zend_verify_missing_arg_type
- zend_verify_missing_arg
- zend_verify_return_error
- zend_verify_internal_return_error
- zend_verify_internal_return_type
- zend_verify_return_type
- zend_verify_missing_return_type
- zend_assign_to_object
- zend_assign_to_object_dim
- zend_binary_assign_op_obj_dim
- zend_assign_to_string_offset
- zend_post_incdec_overloaded_property
- zend_pre_incdec_overloaded_property
- zend_assign_op_overloaded_property
- zend_extension_statement_handler
- zend_extension_fcall_begin_handler
- zend_extension_fcall_end_handler
- zend_get_target_symbol_table
- zend_fetch_dimension_address_inner
- zend_check_string_offset
- zend_fetch_string_offset
- zend_fetch_dimension_address
- zend_fetch_dimension_address_W
- zend_fetch_dimension_address_RW
- zend_fetch_dimension_address_UNSET
- zend_fetch_dimension_address_read
- zend_fetch_dimension_address_read_R
- zend_fetch_dimension_address_read_IS
- zend_fetch_dimension_by_zval
- zend_fetch_property_address
- zend_check_symbol
- execute_internal
- zend_clean_and_cache_symbol_table
- i_free_compiled_variables
- zend_free_compiled_variables
- i_init_func_execute_data
- i_init_code_execute_data
- i_init_execute_data
- zend_create_generator_execute_data
- zend_init_execute_data
- zend_is_by_ref_func_arg_fetch
- zend_vm_stack_copy_call_frame
- zend_vm_stack_extend_call_frame
- zend_get_running_generator
- cleanup_unfinished_calls
- cleanup_live_vars
- zend_cleanup_unfinished_execution
- zend_set_user_opcode_handler
- zend_get_user_opcode_handler
- zend_get_zval_ptr
- zend_check_internal_arg_type
- zend_check_arg_type
- zend_check_missing_arg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
44
45 #include "zend_virtual_cwd.h"
46
47 #define _CONST_CODE 0
48 #define _TMP_CODE 1
49 #define _VAR_CODE 2
50 #define _UNUSED_CODE 3
51 #define _CV_CODE 4
52
53 typedef int (ZEND_FASTCALL *incdec_t)(zval *);
54
55 #define get_zval_ptr(op_type, node, ex, should_free, type) _get_zval_ptr(op_type, node, ex, should_free, type)
56 #define get_zval_ptr_deref(op_type, node, ex, should_free, type) _get_zval_ptr_deref(op_type, node, ex, should_free, type)
57 #define get_zval_ptr_r(op_type, node, ex, should_free) _get_zval_ptr_r(op_type, node, ex, should_free)
58 #define get_zval_ptr_r_deref(op_type, node, ex, should_free) _get_zval_ptr_r_deref(op_type, node, ex, should_free)
59 #define get_zval_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_undef(op_type, node, ex, should_free, type)
60 #define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
61 #define get_zval_ptr_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
62 #define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type)
63 #define get_obj_zval_ptr_undef(op_type, node, ex, should_free, type) _get_obj_zval_ptr_undef(op_type, node, ex, should_free, type)
64 #define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type)
65
66
67 static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array);
68 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array);
69 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array);
70
71 #define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED))
72
73 static ZEND_FUNCTION(pass)
74 {
75 }
76
77 static const zend_internal_function zend_pass_function = {
78 ZEND_INTERNAL_FUNCTION,
79 {0, 0, 0},
80 0,
81 NULL,
82 NULL,
83 NULL,
84 0,
85 0,
86 NULL,
87 ZEND_FN(pass),
88 NULL
89 };
90
91 #undef zval_ptr_dtor
92 #define zval_ptr_dtor(zv) i_zval_ptr_dtor(zv ZEND_FILE_LINE_CC)
93
94 #define READY_TO_DESTROY(zv) \
95 (UNEXPECTED(zv) && Z_REFCOUNTED_P(zv) && Z_REFCOUNT_P(zv) == 1)
96
97 #define EXTRACT_ZVAL_PTR(zv, check_null) do { \
98 zval *__zv = (zv); \
99 if (EXPECTED(Z_TYPE_P(__zv) == IS_INDIRECT)) { \
100 if (!(check_null) || \
101 EXPECTED(Z_INDIRECT_P(__zv))) { \
102 ZVAL_COPY(__zv, Z_INDIRECT_P(__zv)); \
103 } \
104 } \
105 } while (0)
106
107 #define FREE_OP(should_free) \
108 if (should_free) { \
109 zval_ptr_dtor_nogc(should_free); \
110 }
111
112 #define FREE_UNFETCHED_OP(type, var) \
113 if ((type) & (IS_TMP_VAR|IS_VAR)) { \
114 zval_ptr_dtor_nogc(EX_VAR(var)); \
115 }
116
117 #define FREE_OP_VAR_PTR(should_free) \
118 if (should_free) { \
119 zval_ptr_dtor_nogc(should_free); \
120 }
121
122
123
124 #define CV_DEF_OF(i) (EX(func)->op_array.vars[i])
125
126 #define CTOR_CALL_BIT 0x1
127 #define CTOR_USED_BIT 0x2
128
129 #define IS_CTOR_CALL(ce) (((zend_uintptr_t)(ce)) & CTOR_CALL_BIT)
130 #define IS_CTOR_USED(ce) (((zend_uintptr_t)(ce)) & CTOR_USED_BIT)
131
132 #define ENCODE_CTOR(ce, used) \
133 ((zend_class_entry*)(((zend_uintptr_t)(ce)) | CTOR_CALL_BIT | ((used) ? CTOR_USED_BIT : 0)))
134 #define DECODE_CTOR(ce) \
135 ((zend_class_entry*)(((zend_uintptr_t)(ce)) & ~(CTOR_CALL_BIT|CTOR_USED_BIT)))
136
137 #define ZEND_VM_MAIN_STACK_PAGE_SLOTS (16 * 1024)
138 #define ZEND_VM_GENERATOR_STACK_PAGE_SLOTS (256)
139
140 #define ZEND_VM_STACK_PAGE_SLOTS(gen) ((gen) ? ZEND_VM_GENERATOR_STACK_PAGE_SLOTS : ZEND_VM_MAIN_STACK_PAGE_SLOTS)
141
142 #define ZEND_VM_STACK_PAGE_SIZE(gen) (ZEND_VM_STACK_PAGE_SLOTS(gen) * sizeof(zval))
143
144 #define ZEND_VM_STACK_FREE_PAGE_SIZE(gen) \
145 ((ZEND_VM_STACK_PAGE_SLOTS(gen) - ZEND_VM_STACK_HEADER_SLOTS) * sizeof(zval))
146
147 #define ZEND_VM_STACK_PAGE_ALIGNED_SIZE(gen, size) \
148 (((size) + (ZEND_VM_STACK_FREE_PAGE_SIZE(gen) - 1)) & ~(ZEND_VM_STACK_PAGE_SIZE(gen) - 1))
149
150 static zend_always_inline zend_vm_stack zend_vm_stack_new_page(size_t size, zend_vm_stack prev) {
151 zend_vm_stack page = (zend_vm_stack)emalloc(size);
152
153 page->top = ZEND_VM_STACK_ELEMETS(page);
154 page->end = (zval*)((char*)page + size);
155 page->prev = prev;
156 return page;
157 }
158
159 ZEND_API void zend_vm_stack_init(void)
160 {
161 EG(vm_stack) = zend_vm_stack_new_page(ZEND_VM_STACK_PAGE_SIZE(0 ), NULL);
162 EG(vm_stack)->top++;
163 EG(vm_stack_top) = EG(vm_stack)->top;
164 EG(vm_stack_end) = EG(vm_stack)->end;
165 }
166
167 ZEND_API void zend_vm_stack_destroy(void)
168 {
169 zend_vm_stack stack = EG(vm_stack);
170
171 while (stack != NULL) {
172 zend_vm_stack p = stack->prev;
173 efree(stack);
174 stack = p;
175 }
176 }
177
178 ZEND_API void* zend_vm_stack_extend(size_t size)
179 {
180 zend_vm_stack stack;
181 void *ptr;
182
183 stack = EG(vm_stack);
184 stack->top = EG(vm_stack_top);
185 EG(vm_stack) = stack = zend_vm_stack_new_page(
186 EXPECTED(size < ZEND_VM_STACK_FREE_PAGE_SIZE(0)) ?
187 ZEND_VM_STACK_PAGE_SIZE(0) : ZEND_VM_STACK_PAGE_ALIGNED_SIZE(0, size),
188 stack);
189 ptr = stack->top;
190 EG(vm_stack_top) = (void*)(((char*)ptr) + size);
191 EG(vm_stack_end) = stack->end;
192 return ptr;
193 }
194
195 ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute_data, uint32_t var)
196 {
197 return EX_VAR(var);
198 }
199
200 static zend_always_inline zval *_get_zval_ptr_tmp(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
201 {
202 zval *ret = EX_VAR(var);
203 *should_free = ret;
204
205 ZEND_ASSERT(Z_TYPE_P(ret) != IS_REFERENCE);
206
207 return ret;
208 }
209
210 static zend_always_inline zval *_get_zval_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
211 {
212 zval *ret = EX_VAR(var);
213
214 *should_free = ret;
215 return ret;
216 }
217
218 static zend_always_inline zval *_get_zval_ptr_var_deref(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
219 {
220 zval *ret = EX_VAR(var);
221
222 *should_free = ret;
223 ZVAL_DEREF(ret);
224 return ret;
225 }
226
227 static zend_never_inline ZEND_COLD void zval_undefined_cv(uint32_t var, const zend_execute_data *execute_data)
228 {
229 zend_string *cv = CV_DEF_OF(EX_VAR_TO_NUM(var));
230
231 zend_error(E_NOTICE, "Undefined variable: %s", ZSTR_VAL(cv));
232 }
233
234 static zend_never_inline zval *_get_zval_cv_lookup(zval *ptr, uint32_t var, int type, const zend_execute_data *execute_data)
235 {
236 switch (type) {
237 case BP_VAR_R:
238 case BP_VAR_UNSET:
239 zval_undefined_cv(var, execute_data);
240
241 case BP_VAR_IS:
242 ptr = &EG(uninitialized_zval);
243 break;
244 case BP_VAR_RW:
245 zval_undefined_cv(var, execute_data);
246
247 case BP_VAR_W:
248 ZVAL_NULL(ptr);
249 break;
250 }
251 return ptr;
252 }
253
254 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_R(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
255 {
256 zval_undefined_cv(var, execute_data);
257 return &EG(uninitialized_zval);
258 }
259
260 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_UNSET(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
261 {
262 zval_undefined_cv(var, execute_data);
263 return &EG(uninitialized_zval);
264 }
265
266 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_RW(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
267 {
268 ZVAL_NULL(ptr);
269 zval_undefined_cv(var, execute_data);
270 return ptr;
271 }
272
273 static zend_always_inline zval *_get_zval_cv_lookup_BP_VAR_W(zval *ptr, uint32_t var, const zend_execute_data *execute_data)
274 {
275 ZVAL_NULL(ptr);
276 return ptr;
277 }
278
279 static zend_always_inline zval *_get_zval_ptr_cv(const zend_execute_data *execute_data, uint32_t var, int type)
280 {
281 zval *ret = EX_VAR(var);
282
283 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
284 return _get_zval_cv_lookup(ret, var, type, execute_data);
285 }
286 return ret;
287 }
288
289 static zend_always_inline zval *_get_zval_ptr_cv_undef(const zend_execute_data *execute_data, uint32_t var)
290 {
291 return EX_VAR(var);
292 }
293
294 static zend_always_inline zval *_get_zval_ptr_cv_deref(const zend_execute_data *execute_data, uint32_t var, int type)
295 {
296 zval *ret = EX_VAR(var);
297
298 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
299 return _get_zval_cv_lookup(ret, var, type, execute_data);
300 }
301 ZVAL_DEREF(ret);
302 return ret;
303 }
304
305 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var)
306 {
307 zval *ret = EX_VAR(var);
308
309 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
310 return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data);
311 }
312 return ret;
313 }
314
315 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_R(const zend_execute_data *execute_data, uint32_t var)
316 {
317 zval *ret = EX_VAR(var);
318
319 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
320 return _get_zval_cv_lookup_BP_VAR_R(ret, var, execute_data);
321 }
322 ZVAL_DEREF(ret);
323 return ret;
324 }
325
326 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var)
327 {
328 zval *ret = EX_VAR(var);
329
330 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
331 return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data);
332 }
333 return ret;
334 }
335
336 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_UNSET(const zend_execute_data *execute_data, uint32_t var)
337 {
338 zval *ret = EX_VAR(var);
339
340 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
341 return _get_zval_cv_lookup_BP_VAR_UNSET(ret, var, execute_data);
342 }
343 ZVAL_DEREF(ret);
344 return ret;
345 }
346
347 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var)
348 {
349 zval *ret = EX_VAR(var);
350
351 return ret;
352 }
353
354 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_IS(const zend_execute_data *execute_data, uint32_t var)
355 {
356 zval *ret = EX_VAR(var);
357
358 ZVAL_DEREF(ret);
359 return ret;
360 }
361
362 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
363 {
364 zval *ret = EX_VAR(var);
365
366 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
367 return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data);
368 }
369 return ret;
370 }
371
372 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
373 {
374 zval *ret = EX_VAR(var);
375
376 if (UNEXPECTED(Z_TYPE_P(ret) == IS_UNDEF)) {
377 return _get_zval_cv_lookup_BP_VAR_RW(ret, var, execute_data);
378 }
379 ZVAL_DEREF(ret);
380 return ret;
381 }
382
383 static zend_always_inline zval *_get_zval_ptr_cv_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
384 {
385 zval *ret = EX_VAR(var);
386
387 if (Z_TYPE_P(ret) == IS_UNDEF) {
388 return _get_zval_cv_lookup_BP_VAR_W(ret, var, execute_data);
389 }
390 return ret;
391 }
392
393 static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
394 {
395 return EX_VAR(var);
396 }
397
398 static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_RW(const zend_execute_data *execute_data, uint32_t var)
399 {
400 return EX_VAR(var);
401 }
402
403 static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, uint32_t var)
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);
409 }
410 ZVAL_DEREF(ret);
411 return ret;
412 }
413
414 static zend_always_inline zval *_get_zval_ptr(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
415 {
416 if (op_type & (IS_TMP_VAR|IS_VAR)) {
417 if (op_type == IS_TMP_VAR) {
418 return _get_zval_ptr_tmp(node.var, execute_data, should_free);
419 } else {
420 ZEND_ASSERT(op_type == IS_VAR);
421 return _get_zval_ptr_var(node.var, execute_data, should_free);
422 }
423 } else {
424 *should_free = NULL;
425 if (op_type == IS_CONST) {
426 return EX_CONSTANT(node);
427 } else if (op_type == IS_CV) {
428 return _get_zval_ptr_cv(execute_data, node.var, type);
429 } else {
430 return NULL;
431 }
432 }
433 }
434
435 static zend_always_inline zval *_get_zval_ptr_r(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free)
436 {
437 if (op_type & (IS_TMP_VAR|IS_VAR)) {
438 if (op_type == IS_TMP_VAR) {
439 return _get_zval_ptr_tmp(node.var, execute_data, should_free);
440 } else {
441 ZEND_ASSERT(op_type == IS_VAR);
442 return _get_zval_ptr_var(node.var, execute_data, should_free);
443 }
444 } else {
445 *should_free = NULL;
446 if (op_type == IS_CONST) {
447 return EX_CONSTANT(node);
448 } else if (op_type == IS_CV) {
449 return _get_zval_ptr_cv_BP_VAR_R(execute_data, node.var);
450 } else {
451 return NULL;
452 }
453 }
454 }
455
456 static zend_always_inline zval *_get_zval_ptr_deref(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
457 {
458 if (op_type & (IS_TMP_VAR|IS_VAR)) {
459 if (op_type == IS_TMP_VAR) {
460 return _get_zval_ptr_tmp(node.var, execute_data, should_free);
461 } else {
462 ZEND_ASSERT(op_type == IS_VAR);
463 return _get_zval_ptr_var_deref(node.var, execute_data, should_free);
464 }
465 } else {
466 *should_free = NULL;
467 if (op_type == IS_CONST) {
468 return EX_CONSTANT(node);
469 } else if (op_type == IS_CV) {
470 return _get_zval_ptr_cv_deref(execute_data, node.var, type);
471 } else {
472 return NULL;
473 }
474 }
475 }
476
477 static zend_always_inline zval *_get_zval_ptr_r_deref(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free)
478 {
479 if (op_type & (IS_TMP_VAR|IS_VAR)) {
480 if (op_type == IS_TMP_VAR) {
481 return _get_zval_ptr_tmp(node.var, execute_data, should_free);
482 } else {
483 ZEND_ASSERT(op_type == IS_VAR);
484 return _get_zval_ptr_var_deref(node.var, execute_data, should_free);
485 }
486 } else {
487 *should_free = NULL;
488 if (op_type == IS_CONST) {
489 return EX_CONSTANT(node);
490 } else if (op_type == IS_CV) {
491 return _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, node.var);
492 } else {
493 return NULL;
494 }
495 }
496 }
497
498 static zend_always_inline zval *_get_zval_ptr_undef(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
499 {
500 if (op_type & (IS_TMP_VAR|IS_VAR)) {
501 if (op_type == IS_TMP_VAR) {
502 return _get_zval_ptr_tmp(node.var, execute_data, should_free);
503 } else {
504 ZEND_ASSERT(op_type == IS_VAR);
505 return _get_zval_ptr_var(node.var, execute_data, should_free);
506 }
507 } else {
508 *should_free = NULL;
509 if (op_type == IS_CONST) {
510 return EX_CONSTANT(node);
511 } else if (op_type == IS_CV) {
512 return _get_zval_ptr_cv_undef(execute_data, node.var);
513 } else {
514 return NULL;
515 }
516 }
517 }
518
519 static zend_always_inline zval *_get_zval_ptr_ptr_var(uint32_t var, const zend_execute_data *execute_data, zend_free_op *should_free)
520 {
521 zval *ret = EX_VAR(var);
522
523 if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
524 *should_free = NULL;
525 ret = Z_INDIRECT_P(ret);
526 } else {
527 *should_free = ret;
528 }
529 return ret;
530 }
531
532 static inline zval *_get_zval_ptr_ptr(int op_type, znode_op node, const zend_execute_data *execute_data, zend_free_op *should_free, int type)
533 {
534 if (op_type == IS_CV) {
535 *should_free = NULL;
536 return _get_zval_ptr_cv(execute_data, node.var, type);
537 } else {
538 ZEND_ASSERT(op_type == IS_VAR);
539 return _get_zval_ptr_ptr_var(node.var, execute_data, should_free);
540 }
541 }
542
543 static zend_always_inline zval *_get_obj_zval_ptr_unused(zend_execute_data *execute_data)
544 {
545 return &EX(This);
546 }
547
548 static inline zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_execute_data *execute_data, zend_free_op *should_free, int type)
549 {
550 if (op_type == IS_UNUSED) {
551 *should_free = NULL;
552 return &EX(This);
553 }
554 return get_zval_ptr(op_type, op, execute_data, should_free, type);
555 }
556
557 static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_execute_data *execute_data, zend_free_op *should_free, int type)
558 {
559 if (op_type == IS_UNUSED) {
560 *should_free = NULL;
561 return &EX(This);
562 }
563 return get_zval_ptr_undef(op_type, op, execute_data, should_free, type);
564 }
565
566 static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_execute_data *execute_data, zend_free_op *should_free, int type)
567 {
568 if (op_type == IS_UNUSED) {
569 *should_free = NULL;
570 return &EX(This);
571 }
572 return get_zval_ptr_ptr(op_type, node, execute_data, should_free, type);
573 }
574
575 static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr)
576 {
577 zend_reference *ref;
578
579 if (EXPECTED(!Z_ISREF_P(value_ptr))) {
580 ZVAL_NEW_REF(value_ptr, value_ptr);
581 } else if (UNEXPECTED(variable_ptr == value_ptr)) {
582 return;
583 }
584
585 ref = Z_REF_P(value_ptr);
586 GC_REFCOUNT(ref)++;
587 zval_ptr_dtor(variable_ptr);
588 ZVAL_REF(variable_ptr, ref);
589 }
590
591
592 static inline int make_real_object(zval *object)
593 {
594 if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
595 if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE)) {
596
597 } else if (EXPECTED((Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
598 zval_ptr_dtor_nogc(object);
599 } else {
600 return 0;
601 }
602 object_init(object);
603 zend_error(E_WARNING, "Creating default object from empty value");
604 }
605 return 1;
606 }
607
608 static char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce)
609 {
610 zend_string *key;
611 ALLOCA_FLAG(use_heap);
612
613 ZSTR_ALLOCA_INIT(key, cur_arg_info->class_name, strlen(cur_arg_info->class_name), use_heap);
614 *pce = zend_fetch_class(key, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
615 ZSTR_ALLOCA_FREE(key, use_heap);
616
617 *class_name = (*pce) ? ZSTR_VAL((*pce)->name) : (char*)cur_arg_info->class_name;
618 if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
619 return "implement interface ";
620 } else {
621 return "be an instance of ";
622 }
623 }
624
625 static zend_always_inline zend_class_entry* zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info)
626 {
627 return zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
628 }
629
630 static ZEND_COLD void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg)
631 {
632 zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
633 const char *fname = ZSTR_VAL(zf->common.function_name);
634 const char *fsep;
635 const char *fclass;
636
637 if (zf->common.scope) {
638 fsep = "::";
639 fclass = ZSTR_VAL(zf->common.scope->name);
640 } else {
641 fsep = "";
642 fclass = "";
643 }
644
645 if (zf->common.type == ZEND_USER_FUNCTION) {
646 if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
647 zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d",
648 arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind,
649 ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
650 } else {
651 zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
652 }
653 } else {
654 zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
655 }
656 }
657
658 static int is_null_constant(zval *default_value)
659 {
660 if (Z_CONSTANT_P(default_value)) {
661 zval constant;
662
663 ZVAL_COPY_VALUE(&constant, default_value);
664 if (UNEXPECTED(zval_update_constant_ex(&constant, 0, NULL) != SUCCESS)) {
665 return 0;
666 }
667 if (Z_TYPE(constant) == IS_NULL) {
668 return 1;
669 }
670 zval_dtor(&constant);
671 }
672 return 0;
673 }
674
675 static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg)
676 {
677 switch (type_hint) {
678 case _IS_BOOL: {
679 zend_bool dest;
680
681 if (!zend_parse_arg_bool_weak(arg, &dest)) {
682 return 0;
683 }
684 zval_ptr_dtor(arg);
685 ZVAL_BOOL(arg, dest);
686 return 1;
687 }
688 case IS_LONG: {
689 zend_long dest;
690
691 if (!zend_parse_arg_long_weak(arg, &dest)) {
692 return 0;
693 }
694 zval_ptr_dtor(arg);
695 ZVAL_LONG(arg, dest);
696 return 1;
697 }
698 case IS_DOUBLE: {
699 double dest;
700
701 if (!zend_parse_arg_double_weak(arg, &dest)) {
702 return 0;
703 }
704 zval_ptr_dtor(arg);
705 ZVAL_DOUBLE(arg, dest);
706 return 1;
707 }
708 case IS_STRING: {
709 zend_string *dest;
710
711
712 if (!zend_parse_arg_str_weak(arg, &dest)) {
713 return 0;
714 }
715 return 1;
716 }
717 default:
718 return 0;
719 }
720 }
721
722 static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict)
723 {
724 if (UNEXPECTED(strict)) {
725
726 if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) {
727 return 0;
728 }
729 } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
730
731 return 0;
732 }
733 return zend_verify_weak_scalar_type_hint(type_hint, arg);
734 }
735
736 static int zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
737 {
738 zend_internal_arg_info *cur_arg_info;
739 char *need_msg, *class_name;
740 zend_class_entry *ce;
741
742 if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
743 cur_arg_info = &zf->internal_function.arg_info[arg_num-1];
744 } else if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) {
745 cur_arg_info = &zf->internal_function.arg_info[zf->internal_function.num_args];
746 } else {
747 return 1;
748 }
749
750 if (cur_arg_info->type_hint) {
751 ZVAL_DEREF(arg);
752 if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) {
753 if (cur_arg_info->class_name) {
754 need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
755 if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
756 zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
757 return 0;
758 }
759 }
760 } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
761 if (cur_arg_info->class_name) {
762 need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
763 zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
764 return 0;
765 } else if (cur_arg_info->type_hint == IS_CALLABLE) {
766 if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) {
767 zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
768 return 0;
769 }
770 } else if (cur_arg_info->type_hint == _IS_BOOL &&
771 EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
772
773 } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) {
774 zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
775 return 0;
776 }
777 }
778 }
779 return 1;
780 }
781
782 static zend_always_inline int zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
783 {
784 zend_arg_info *cur_arg_info;
785 char *need_msg;
786 zend_class_entry *ce;
787
788 if (EXPECTED(arg_num <= zf->common.num_args)) {
789 cur_arg_info = &zf->common.arg_info[arg_num-1];
790 } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) {
791 cur_arg_info = &zf->common.arg_info[zf->common.num_args];
792 } else {
793 return 1;
794 }
795
796 if (cur_arg_info->type_hint) {
797 ZVAL_DEREF(arg);
798 if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) {
799 if (cur_arg_info->class_name) {
800 if (EXPECTED(*cache_slot)) {
801 ce = (zend_class_entry*)*cache_slot;
802 } else {
803 ce = zend_verify_arg_class_kind(cur_arg_info);
804 if (UNEXPECTED(!ce)) {
805 zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
806 return 0;
807 }
808 *cache_slot = (void*)ce;
809 }
810 if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(arg), ce))) {
811 need_msg =
812 (ce->ce_flags & ZEND_ACC_INTERFACE) ?
813 "implement interface " : "be an instance of ";
814 zend_verify_arg_error(zf, arg_num, need_msg, ZSTR_VAL(ce->name), "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
815 return 0;
816 }
817 }
818 } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) {
819 if (cur_arg_info->class_name) {
820 if (EXPECTED(*cache_slot)) {
821 ce = (zend_class_entry*)*cache_slot;
822 } else {
823 ce = zend_verify_arg_class_kind(cur_arg_info);
824 if (UNEXPECTED(!ce)) {
825 if (Z_TYPE_P(arg) == IS_OBJECT) {
826 zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "instance of ", ZSTR_VAL(Z_OBJCE_P(arg)->name), arg);
827 } else {
828 zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "", zend_zval_type_name(arg), arg);
829 }
830 return 0;
831 }
832 *cache_slot = (void*)ce;
833 }
834 need_msg =
835 (ce->ce_flags & ZEND_ACC_INTERFACE) ?
836 "implement interface " : "be an instance of ";
837 zend_verify_arg_error(zf, arg_num, need_msg, ZSTR_VAL(ce->name), zend_zval_type_name(arg), "", arg);
838 return 0;
839 } else if (cur_arg_info->type_hint == IS_CALLABLE) {
840 if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) {
841 zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
842 return 0;
843 }
844 } else if (cur_arg_info->type_hint == _IS_BOOL &&
845 EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
846
847 } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_ARG_USES_STRICT_TYPES()))) {
848 zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
849 return 0;
850 }
851 }
852 }
853 return 1;
854 }
855
856 static zend_always_inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num, void **cache_slot)
857 {
858 zend_arg_info *cur_arg_info;
859 char *need_msg;
860 zend_class_entry *ce;
861
862 if (EXPECTED(arg_num <= zf->common.num_args)) {
863 cur_arg_info = &zf->common.arg_info[arg_num-1];
864 } else if (UNEXPECTED(zf->common.fn_flags & ZEND_ACC_VARIADIC)) {
865 cur_arg_info = &zf->common.arg_info[zf->common.num_args];
866 } else {
867 return 1;
868 }
869
870 if (cur_arg_info->type_hint) {
871 if (cur_arg_info->class_name) {
872 if (EXPECTED(*cache_slot)) {
873 ce = (zend_class_entry*)*cache_slot;
874 } else {
875 ce = zend_verify_arg_class_kind(cur_arg_info);
876 if (UNEXPECTED(!ce)) {
877 zend_verify_arg_error(zf, arg_num, "be an instance of ", ZSTR_VAL(cur_arg_info->class_name), "none", "", NULL);
878 return 0;
879 }
880 *cache_slot = (void*)ce;
881 }
882 need_msg =
883 (ce->ce_flags & ZEND_ACC_INTERFACE) ?
884 "implement interface " : "be an instance of ";
885 zend_verify_arg_error(zf, arg_num, need_msg, ZSTR_VAL(ce->name), "none", "", NULL);
886 } else if (cur_arg_info->type_hint == IS_CALLABLE) {
887 zend_verify_arg_error(zf, arg_num, "be callable", "", "none", "", NULL);
888 } else {
889 zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "", NULL);
890 }
891 return 0;
892 }
893 return 1;
894 }
895
896 static ZEND_COLD void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num, void **cache_slot)
897 {
898 if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
899 UNEXPECTED(zend_verify_missing_arg_type(EX(func), arg_num, cache_slot))) {
900 const char *class_name = EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "";
901 const char *space = EX(func)->common.scope ? "::" : "";
902 const char *func_name = EX(func)->common.function_name ? ZSTR_VAL(EX(func)->common.function_name) : "main";
903 zend_execute_data *ptr = EX(prev_execute_data);
904
905 if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
906 zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", arg_num, class_name, space, func_name, ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
907 } else {
908 zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
909 }
910 }
911 }
912
913 static ZEND_COLD void zend_verify_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind)
914 {
915 const char *fname = ZSTR_VAL(zf->common.function_name);
916 const char *fsep;
917 const char *fclass;
918
919 if (zf->common.scope) {
920 fsep = "::";
921 fclass = ZSTR_VAL(zf->common.scope->name);
922 } else {
923 fsep = "";
924 fclass = "";
925 }
926
927 zend_type_error("Return value of %s%s%s() must %s%s, %s%s returned",
928 fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind);
929 }
930
931 static ZEND_COLD void zend_verify_internal_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind)
932 {
933 const char *fname = ZSTR_VAL(zf->common.function_name);
934 const char *fsep;
935 const char *fclass;
936
937 if (zf->common.scope) {
938 fsep = "::";
939 fclass = ZSTR_VAL(zf->common.scope->name);
940 } else {
941 fsep = "";
942 fclass = "";
943 }
944
945 zend_error_noreturn(E_CORE_ERROR, "Return value of %s%s%s() must %s%s, %s%s returned",
946 fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind);
947 }
948
949 #if ZEND_DEBUG
950 static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
951 {
952 zend_arg_info *ret_info = zf->common.arg_info - 1;
953 char *need_msg, *class_name;
954 zend_class_entry *ce;
955
956
957 if (ret_info->type_hint) {
958 if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) {
959 if (ret_info->class_name) {
960 need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
961 if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
962 zend_verify_internal_return_error(zf, need_msg, class_name, "instance of ", ZSTR_VAL(Z_OBJCE_P(ret)->name));
963 return 0;
964 }
965 }
966 } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
967 if (ret_info->class_name) {
968 need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
969 zend_verify_internal_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
970 } else if (ret_info->type_hint == IS_CALLABLE) {
971 if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
972 zend_verify_internal_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
973 return 0;
974 }
975 } else if (ret_info->type_hint == _IS_BOOL &&
976 EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
977
978 } else {
979
980 zend_verify_internal_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
981 return 0;
982 }
983 }
984 }
985 return 1;
986 }
987 #endif
988
989 static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *ret, void **cache_slot)
990 {
991 zend_arg_info *ret_info = zf->common.arg_info - 1;
992 char *need_msg;
993 zend_class_entry *ce;
994
995 if (ret_info->type_hint) {
996 if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) {
997 if (ret_info->class_name) {
998 if (EXPECTED(*cache_slot)) {
999 ce = (zend_class_entry*)*cache_slot;
1000 } else {
1001 ce = zend_verify_arg_class_kind(ret_info);
1002 if (UNEXPECTED(!ce)) {
1003 zend_verify_return_error(zf, "be an instance of ", ZSTR_VAL(ret_info->class_name), "instance of ", ZSTR_VAL(Z_OBJCE_P(ret)->name));
1004 return;
1005 }
1006 *cache_slot = (void*)ce;
1007 }
1008 if (UNEXPECTED(!instanceof_function(Z_OBJCE_P(ret), ce))) {
1009 need_msg =
1010 (ce->ce_flags & ZEND_ACC_INTERFACE) ?
1011 "implement interface " : "be an instance of ";
1012 zend_verify_return_error(zf, need_msg, ZSTR_VAL(ce->name), "instance of ", ZSTR_VAL(Z_OBJCE_P(ret)->name));
1013 }
1014 }
1015 } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
1016 if (ret_info->class_name) {
1017 if (EXPECTED(*cache_slot)) {
1018 ce = (zend_class_entry*)*cache_slot;
1019 } else {
1020 ce = zend_verify_arg_class_kind(ret_info);
1021 if (UNEXPECTED(!ce)) {
1022 zend_verify_return_error(zf, "be an instance of ", ZSTR_VAL(ret_info->class_name), zend_zval_type_name(ret), "");
1023 return;
1024 }
1025 *cache_slot = (void*)ce;
1026 }
1027 need_msg =
1028 (ce->ce_flags & ZEND_ACC_INTERFACE) ?
1029 "implement interface " : "be an instance of ";
1030 zend_verify_return_error(zf, need_msg, ZSTR_VAL(ce->name), zend_zval_type_name(ret), "");
1031 } else if (ret_info->type_hint == IS_CALLABLE) {
1032 if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL)) {
1033 zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
1034 }
1035 } else if (ret_info->type_hint == _IS_BOOL &&
1036 EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
1037
1038 } else if (UNEXPECTED(!zend_verify_scalar_type_hint(ret_info->type_hint, ret, ZEND_RET_USES_STRICT_TYPES()))) {
1039 zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
1040 }
1041 }
1042 }
1043 }
1044
1045 static ZEND_COLD int zend_verify_missing_return_type(zend_function *zf, void **cache_slot)
1046 {
1047 zend_arg_info *ret_info = zf->common.arg_info - 1;
1048 char *need_msg;
1049 zend_class_entry *ce;
1050
1051 if (ret_info->type_hint) {
1052 if (ret_info->class_name) {
1053 if (EXPECTED(*cache_slot)) {
1054 ce = (zend_class_entry*)*cache_slot;
1055 } else {
1056 ce = zend_verify_arg_class_kind(ret_info);
1057 if (UNEXPECTED(!ce)) {
1058 zend_verify_return_error(zf, "be an instance of ", ZSTR_VAL(ret_info->class_name), "none", "");
1059 return 0;
1060 }
1061 *cache_slot = (void*)ce;
1062 }
1063 need_msg =
1064 (ce->ce_flags & ZEND_ACC_INTERFACE) ?
1065 "implement interface " : "be an instance of ";
1066 zend_verify_return_error(zf, need_msg, ZSTR_VAL(ce->name), "none", "");
1067 return 0;
1068 } else if (ret_info->type_hint == IS_CALLABLE) {
1069 zend_verify_return_error(zf, "be callable", "", "none", "");
1070 } else {
1071 zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), "none", "");
1072 }
1073 return 0;
1074 }
1075 return 1;
1076 }
1077
1078 static zend_always_inline void zend_assign_to_object(zval *retval, zval *object, uint32_t object_op_type, zval *property_name, uint32_t property_op_type, int value_type, znode_op value_op, const zend_execute_data *execute_data, void **cache_slot)
1079 {
1080 zend_free_op free_value;
1081 zval *value = get_zval_ptr_r(value_type, value_op, execute_data, &free_value);
1082 zval tmp;
1083
1084 if (object_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
1085 do {
1086 if (object_op_type == IS_VAR && UNEXPECTED(object == &EG(error_zval))) {
1087 if (retval) {
1088 ZVAL_NULL(retval);
1089 }
1090 FREE_OP(free_value);
1091 return;
1092 }
1093 if (Z_ISREF_P(object)) {
1094 object = Z_REFVAL_P(object);
1095 if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
1096 break;
1097 }
1098 }
1099 if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE ||
1100 (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) {
1101 zend_object *obj;
1102
1103 zval_ptr_dtor(object);
1104 object_init(object);
1105 Z_ADDREF_P(object);
1106 obj = Z_OBJ_P(object);
1107 zend_error(E_WARNING, "Creating default object from empty value");
1108 if (GC_REFCOUNT(obj) == 1) {
1109
1110 if (retval) {
1111 ZVAL_NULL(retval);
1112 }
1113 FREE_OP(free_value);
1114 OBJ_RELEASE(obj);
1115 return;
1116 }
1117 Z_DELREF_P(object);
1118 } else {
1119 zend_error(E_WARNING, "Attempt to assign property of non-object");
1120 if (retval) {
1121 ZVAL_NULL(retval);
1122 }
1123 FREE_OP(free_value);
1124 return;
1125 }
1126 } while (0);
1127 }
1128
1129 if (property_op_type == IS_CONST &&
1130 EXPECTED(Z_OBJCE_P(object) == CACHED_PTR_EX(cache_slot))) {
1131 uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
1132 zend_object *zobj = Z_OBJ_P(object);
1133 zval *property;
1134
1135 if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
1136 property = OBJ_PROP(zobj, prop_offset);
1137 if (Z_TYPE_P(property) != IS_UNDEF) {
1138 fast_assign:
1139 value = zend_assign_to_variable(property, value, value_type);
1140 if (retval && EXPECTED(!EG(exception))) {
1141 ZVAL_COPY(retval, value);
1142 }
1143 return;
1144 }
1145 } else {
1146 if (EXPECTED(zobj->properties != NULL)) {
1147 if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
1148 if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
1149 GC_REFCOUNT(zobj->properties)--;
1150 }
1151 zobj->properties = zend_array_dup(zobj->properties);
1152 }
1153 property = zend_hash_find(zobj->properties, Z_STR_P(property_name));
1154 if (property) {
1155 goto fast_assign;
1156 }
1157 }
1158
1159 if (!zobj->ce->__set) {
1160
1161 if (EXPECTED(zobj->properties == NULL)) {
1162 rebuild_object_properties(zobj);
1163 }
1164
1165 if (value_type == IS_CONST) {
1166 if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
1167 ZVAL_COPY_VALUE(&tmp, value);
1168 zval_copy_ctor_func(&tmp);
1169 value = &tmp;
1170 }
1171 } else if (value_type != IS_TMP_VAR) {
1172 if (Z_ISREF_P(value)) {
1173 if (value_type == IS_VAR) {
1174 zend_reference *ref = Z_REF_P(value);
1175 if (--(GC_REFCOUNT(ref)) == 0) {
1176 ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value));
1177 efree_size(ref, sizeof(zend_reference));
1178 value = &tmp;
1179 } else {
1180 value = Z_REFVAL_P(value);
1181 if (Z_REFCOUNTED_P(value)) {
1182 Z_ADDREF_P(value);
1183 }
1184 }
1185 } else {
1186 value = Z_REFVAL_P(value);
1187 if (Z_REFCOUNTED_P(value)) {
1188 Z_ADDREF_P(value);
1189 }
1190 }
1191 } else if (value_type == IS_CV && Z_REFCOUNTED_P(value)) {
1192 Z_ADDREF_P(value);
1193 }
1194 }
1195 zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value);
1196 if (retval) {
1197 ZVAL_COPY(retval, value);
1198 }
1199 return;
1200 }
1201 }
1202 }
1203
1204 if (!Z_OBJ_HT_P(object)->write_property) {
1205 zend_error(E_WARNING, "Attempt to assign property of non-object");
1206 if (retval) {
1207 ZVAL_NULL(retval);
1208 }
1209 FREE_OP(free_value);
1210 return;
1211 }
1212
1213
1214 if (value_type == IS_CONST) {
1215 if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
1216 ZVAL_COPY_VALUE(&tmp, value);
1217 zval_copy_ctor_func(&tmp);
1218 value = &tmp;
1219 }
1220 } else if (value_type != IS_TMP_VAR) {
1221 ZVAL_DEREF(value);
1222 }
1223
1224 Z_OBJ_HT_P(object)->write_property(object, property_name, value, cache_slot);
1225
1226 if (retval && EXPECTED(!EG(exception))) {
1227 ZVAL_COPY(retval, value);
1228 }
1229 if (value_type == IS_CONST) {
1230 zval_ptr_dtor_nogc(value);
1231 } else {
1232 FREE_OP(free_value);
1233 }
1234 }
1235
1236 static zend_never_inline void zend_assign_to_object_dim(zval *retval, zval *object, zval *property_name, int value_type, znode_op value_op, const zend_execute_data *execute_data)
1237 {
1238 zend_free_op free_value;
1239 zval *value = get_zval_ptr_deref(value_type, value_op, execute_data, &free_value, BP_VAR_R);
1240 zval tmp;
1241
1242
1243 if (!Z_OBJ_HT_P(object)->write_dimension) {
1244 zend_throw_error(NULL, "Cannot use object as array");
1245 FREE_OP(free_value);
1246 return;
1247 }
1248
1249
1250 if (value_type == IS_CONST) {
1251 if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
1252 ZVAL_COPY_VALUE(&tmp, value);
1253 zval_copy_ctor_func(&tmp);
1254 value = &tmp;
1255 }
1256 }
1257
1258 Z_OBJ_HT_P(object)->write_dimension(object, property_name, value);
1259
1260 if (retval && EXPECTED(!EG(exception))) {
1261 ZVAL_COPY(retval, value);
1262 }
1263 if (value_type == IS_CONST) {
1264 zval_ptr_dtor_nogc(value);
1265 } else {
1266 FREE_OP(free_value);
1267 }
1268 }
1269
1270 static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval *property, zval *value, zval *retval, binary_op_type binary_op)
1271 {
1272 zval *z;
1273 zval rv, res;
1274
1275 if (Z_OBJ_HT_P(object)->read_dimension &&
1276 (z = Z_OBJ_HT_P(object)->read_dimension(object, property, BP_VAR_R, &rv)) != NULL) {
1277
1278 if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1279 zval rv2;
1280 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1281
1282 if (z == &rv) {
1283 zval_ptr_dtor(&rv);
1284 }
1285 ZVAL_COPY_VALUE(z, value);
1286 }
1287 binary_op(&res, Z_ISREF_P(z) ? Z_REFVAL_P(z) : z, value);
1288 Z_OBJ_HT_P(object)->write_dimension(object, property, &res);
1289 if (z == &rv) {
1290 zval_ptr_dtor(&rv);
1291 }
1292 if (retval) {
1293 ZVAL_COPY(retval, &res);
1294 }
1295 zval_ptr_dtor(&res);
1296 } else {
1297 zend_error(E_WARNING, "Attempt to assign property of non-object");
1298 if (retval) {
1299 ZVAL_NULL(retval);
1300 }
1301 }
1302 }
1303
1304 static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result)
1305 {
1306 zend_string *old_str;
1307
1308 if (offset < 0) {
1309 zend_error(E_WARNING, "Illegal string offset: " ZEND_LONG_FMT, offset);
1310 zend_string_release(Z_STR_P(str));
1311 if (result) {
1312 ZVAL_NULL(result);
1313 }
1314 return;
1315 }
1316
1317 old_str = Z_STR_P(str);
1318 if ((size_t)offset >= Z_STRLEN_P(str)) {
1319 zend_long old_len = Z_STRLEN_P(str);
1320 Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0);
1321 Z_TYPE_INFO_P(str) = IS_STRING_EX;
1322 memset(Z_STRVAL_P(str) + old_len, ' ', offset - old_len);
1323 Z_STRVAL_P(str)[offset+1] = 0;
1324 } else if (!Z_REFCOUNTED_P(str)) {
1325 Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0);
1326 Z_TYPE_INFO_P(str) = IS_STRING_EX;
1327 }
1328
1329 if (Z_TYPE_P(value) != IS_STRING) {
1330 zend_string *tmp = zval_get_string(value);
1331
1332 Z_STRVAL_P(str)[offset] = ZSTR_VAL(tmp)[0];
1333 zend_string_release(tmp);
1334 } else {
1335 Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0];
1336 }
1337
1338
1339
1340
1341
1342 zend_string_release(old_str);
1343 if (result) {
1344 zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset];
1345
1346 if (CG(one_char_string)[c]) {
1347 ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
1348 } else {
1349 ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(str) + offset, 1, 0));
1350 }
1351 }
1352 }
1353
1354 static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
1355 {
1356 if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1357 zval rv, obj;
1358 zval *z;
1359 zval z_copy;
1360
1361 ZVAL_OBJ(&obj, Z_OBJ_P(object));
1362 Z_ADDREF(obj);
1363 z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1364 if (UNEXPECTED(EG(exception))) {
1365 OBJ_RELEASE(Z_OBJ(obj));
1366 return;
1367 }
1368
1369 if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1370 zval rv2;
1371 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1372 if (z == &rv) {
1373 zval_ptr_dtor(&rv);
1374 }
1375 ZVAL_COPY_VALUE(z, value);
1376 }
1377
1378 if (UNEXPECTED(Z_TYPE_P(z) == IS_REFERENCE)) {
1379 ZVAL_COPY(result, Z_REFVAL_P(z));
1380 } else {
1381 ZVAL_COPY(result, z);
1382 }
1383 ZVAL_DUP(&z_copy, result);
1384 if (inc) {
1385 increment_function(&z_copy);
1386 } else {
1387 decrement_function(&z_copy);
1388 }
1389 Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
1390 OBJ_RELEASE(Z_OBJ(obj));
1391 zval_ptr_dtor(&z_copy);
1392 zval_ptr_dtor(z);
1393 } else {
1394 zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1395 ZVAL_NULL(result);
1396 }
1397 }
1398
1399 static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
1400 {
1401 zval rv;
1402
1403 if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
1404 zval *z, obj;
1405
1406 ZVAL_OBJ(&obj, Z_OBJ_P(object));
1407 Z_ADDREF(obj);
1408 z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1409 if (UNEXPECTED(EG(exception))) {
1410 OBJ_RELEASE(Z_OBJ(obj));
1411 return;
1412 }
1413
1414 if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
1415 zval rv2;
1416 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1417
1418 if (z == &rv) {
1419 zval_ptr_dtor(&rv);
1420 }
1421 ZVAL_COPY_VALUE(z, value);
1422 }
1423 ZVAL_DEREF(z);
1424 SEPARATE_ZVAL_NOREF(z);
1425 if (inc) {
1426 increment_function(z);
1427 } else {
1428 decrement_function(z);
1429 }
1430 if (UNEXPECTED(result)) {
1431 ZVAL_COPY(result, z);
1432 }
1433 Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
1434 OBJ_RELEASE(Z_OBJ(obj));
1435 zval_ptr_dtor(z);
1436 } else {
1437 zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
1438 if (UNEXPECTED(result)) {
1439 ZVAL_NULL(result);
1440 }
1441 }
1442 }
1443
1444 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)
1445 {
1446 zval *z;
1447 zval rv, obj;
1448 zval *zptr;
1449
1450 ZVAL_OBJ(&obj, Z_OBJ_P(object));
1451 Z_ADDREF(obj);
1452 if (EXPECTED(Z_OBJ_HT(obj)->read_property)) {
1453 z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
1454 if (UNEXPECTED(EG(exception))) {
1455 OBJ_RELEASE(Z_OBJ(obj));
1456 return;
1457 }
1458 if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
1459 zval rv2;
1460 zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
1461
1462 if (z == &rv) {
1463 zval_ptr_dtor(&rv);
1464 }
1465 ZVAL_COPY_VALUE(z, value);
1466 }
1467 zptr = z;
1468 ZVAL_DEREF(z);
1469 SEPARATE_ZVAL_NOREF(z);
1470 binary_op(z, z, value);
1471 Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
1472 if (UNEXPECTED(result)) {
1473 ZVAL_COPY(result, z);
1474 }
1475 zval_ptr_dtor(zptr);
1476 } else {
1477 zend_error(E_WARNING, "Attempt to assign property of non-object");
1478 if (UNEXPECTED(result)) {
1479 ZVAL_NULL(result);
1480 }
1481 }
1482 OBJ_RELEASE(Z_OBJ(obj));
1483 }
1484
1485
1486 static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array)
1487 {
1488 if (extension->statement_handler) {
1489 extension->statement_handler(op_array);
1490 }
1491 }
1492
1493
1494 static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array)
1495 {
1496 if (extension->fcall_begin_handler) {
1497 extension->fcall_begin_handler(op_array);
1498 }
1499 }
1500
1501
1502 static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array)
1503 {
1504 if (extension->fcall_end_handler) {
1505 extension->fcall_end_handler(op_array);
1506 }
1507 }
1508
1509
1510 static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_data *execute_data, int fetch_type)
1511 {
1512 HashTable *ht;
1513
1514 if (EXPECTED(fetch_type == ZEND_FETCH_GLOBAL_LOCK) ||
1515 EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) {
1516 ht = &EG(symbol_table);
1517 } else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) {
1518 ZEND_ASSERT(EX(func)->op_array.static_variables != NULL);
1519 ht = EX(func)->op_array.static_variables;
1520 if (GC_REFCOUNT(ht) > 1) {
1521 if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
1522 GC_REFCOUNT(ht)--;
1523 }
1524 EX(func)->op_array.static_variables = ht = zend_array_dup(ht);
1525 }
1526 } else {
1527 ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL);
1528 if (!EX(symbol_table)) {
1529 zend_rebuild_symbol_table();
1530 }
1531 ht = EX(symbol_table);
1532 }
1533 return ht;
1534 }
1535
1536 static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type)
1537 {
1538 zval *retval;
1539 zend_string *offset_key;
1540 zend_ulong hval;
1541
1542 try_again:
1543 if (EXPECTED(Z_TYPE_P(dim) == IS_LONG)) {
1544 hval = Z_LVAL_P(dim);
1545 num_index:
1546 retval = zend_hash_index_find(ht, hval);
1547 if (retval == NULL) {
1548 switch (type) {
1549 case BP_VAR_R:
1550 zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
1551
1552 case BP_VAR_UNSET:
1553 case BP_VAR_IS:
1554 retval = &EG(uninitialized_zval);
1555 break;
1556 case BP_VAR_RW:
1557 zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
1558 retval = zend_hash_index_update(ht, hval, &EG(uninitialized_zval));
1559 break;
1560 case BP_VAR_W:
1561 retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
1562 break;
1563 }
1564 }
1565 } else if (EXPECTED(Z_TYPE_P(dim) == IS_STRING)) {
1566 offset_key = Z_STR_P(dim);
1567 if (dim_type != IS_CONST) {
1568 if (ZEND_HANDLE_NUMERIC(offset_key, hval)) {
1569 goto num_index;
1570 }
1571 }
1572 str_index:
1573 retval = zend_hash_find(ht, offset_key);
1574 if (retval) {
1575
1576 if (UNEXPECTED(Z_TYPE_P(retval) == IS_INDIRECT)) {
1577 retval = Z_INDIRECT_P(retval);
1578 if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) {
1579 switch (type) {
1580 case BP_VAR_R:
1581 zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
1582
1583 case BP_VAR_UNSET:
1584 case BP_VAR_IS:
1585 retval = &EG(uninitialized_zval);
1586 break;
1587 case BP_VAR_RW:
1588 zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key));
1589
1590 case BP_VAR_W:
1591 ZVAL_NULL(retval);
1592 break;
1593 }
1594 }
1595 }
1596 } else {
1597 switch (type) {
1598 case BP_VAR_R:
1599 zend_error(E_NOTICE, "Undefined index: %s", ZSTR_VAL(offset_key));
1600
1601 case BP_VAR_UNSET:
1602 case BP_VAR_IS:
1603 retval = &EG(uninitialized_zval);
1604 break;
1605 case BP_VAR_RW:
1606 zend_error(E_NOTICE,"Undefined index: %s", ZSTR_VAL(offset_key));
1607 retval = zend_hash_update(ht, offset_key, &EG(uninitialized_zval));
1608 break;
1609 case BP_VAR_W:
1610 retval = zend_hash_add_new(ht, offset_key, &EG(uninitialized_zval));
1611 break;
1612 }
1613 }
1614 } else {
1615 switch (Z_TYPE_P(dim)) {
1616 case IS_NULL:
1617 offset_key = ZSTR_EMPTY_ALLOC();
1618 goto str_index;
1619 case IS_DOUBLE:
1620 hval = zend_dval_to_lval(Z_DVAL_P(dim));
1621 goto num_index;
1622 case IS_RESOURCE:
1623 zend_error(E_NOTICE, "Resource ID#%pd used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(dim), Z_RES_HANDLE_P(dim));
1624 hval = Z_RES_HANDLE_P(dim);
1625 goto num_index;
1626 case IS_FALSE:
1627 hval = 0;
1628 goto num_index;
1629 case IS_TRUE:
1630 hval = 1;
1631 goto num_index;
1632 case IS_REFERENCE:
1633 dim = Z_REFVAL_P(dim);
1634 goto try_again;
1635 default:
1636 zend_error(E_WARNING, "Illegal offset type");
1637 retval = (type == BP_VAR_W || type == BP_VAR_RW) ?
1638 &EG(error_zval) : &EG(uninitialized_zval);
1639 }
1640 }
1641 return retval;
1642 }
1643
1644 static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type)
1645 {
1646 zend_long offset;
1647
1648 try_again:
1649 if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1650 switch(Z_TYPE_P(dim)) {
1651 case IS_STRING:
1652 if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1653 break;
1654 }
1655 if (type != BP_VAR_UNSET) {
1656 zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1657 }
1658 break;
1659 case IS_DOUBLE:
1660 case IS_NULL:
1661 case IS_FALSE:
1662 case IS_TRUE:
1663 zend_error(E_NOTICE, "String offset cast occurred");
1664 break;
1665 case IS_REFERENCE:
1666 dim = Z_REFVAL_P(dim);
1667 goto try_again;
1668 default:
1669 zend_error(E_WARNING, "Illegal offset type");
1670 break;
1671 }
1672
1673 offset = zval_get_long(dim);
1674 } else {
1675 offset = Z_LVAL_P(dim);
1676 }
1677
1678 return offset;
1679 }
1680
1681 static zend_always_inline zend_long zend_fetch_string_offset(zval *container, zval *dim, int type)
1682 {
1683 zend_long offset = zend_check_string_offset(dim, type);
1684
1685 if (Z_REFCOUNTED_P(container)) {
1686 if (Z_REFCOUNT_P(container) > 1) {
1687 Z_DELREF_P(container);
1688 zval_copy_ctor_func(container);
1689 }
1690 Z_ADDREF_P(container);
1691 }
1692 return offset;
1693 }
1694
1695 static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type)
1696 {
1697 zval *retval;
1698
1699 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1700 try_array:
1701 SEPARATE_ARRAY(container);
1702 fetch_from_array:
1703 if (dim == NULL) {
1704 retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
1705 if (UNEXPECTED(retval == NULL)) {
1706 zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1707 retval = &EG(error_zval);
1708 }
1709 } else {
1710 retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
1711 }
1712 ZVAL_INDIRECT(result, retval);
1713 return;
1714 } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1715 container = Z_REFVAL_P(container);
1716 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1717 goto try_array;
1718 }
1719 }
1720 if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1721 if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
1722 zval_ptr_dtor_nogc(container);
1723 convert_to_array:
1724 ZVAL_NEW_ARR(container);
1725 zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
1726 goto fetch_from_array;
1727 }
1728
1729 if (dim == NULL) {
1730 zend_throw_error(NULL, "[] operator not supported for strings");
1731 ZVAL_INDIRECT(result, &EG(error_zval));
1732 } else {
1733 zend_check_string_offset(dim, type);
1734 ZVAL_INDIRECT(result, NULL);
1735 }
1736 } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1737 if (!Z_OBJ_HT_P(container)->read_dimension) {
1738 zend_throw_error(NULL, "Cannot use object as array");
1739 retval = &EG(error_zval);
1740 } else {
1741 retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
1742
1743 if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1744 zend_class_entry *ce = Z_OBJCE_P(container);
1745
1746 ZVAL_NULL(result);
1747 zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1748 } else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1749 if (!Z_ISREF_P(retval)) {
1750 if (Z_REFCOUNTED_P(retval) &&
1751 Z_REFCOUNT_P(retval) > 1) {
1752 if (Z_TYPE_P(retval) != IS_OBJECT) {
1753 Z_DELREF_P(retval);
1754 ZVAL_DUP(result, retval);
1755 retval = result;
1756 } else {
1757 ZVAL_COPY_VALUE(result, retval);
1758 retval = result;
1759 }
1760 }
1761 if (Z_TYPE_P(retval) != IS_OBJECT) {
1762 zend_class_entry *ce = Z_OBJCE_P(container);
1763 zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1764 }
1765 } else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
1766 ZVAL_UNREF(retval);
1767 }
1768 if (result != retval) {
1769 ZVAL_INDIRECT(result, retval);
1770 }
1771 } else {
1772 ZVAL_INDIRECT(result, &EG(error_zval));
1773 }
1774 }
1775 } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
1776 if (UNEXPECTED(container == &EG(error_zval))) {
1777 ZVAL_INDIRECT(result, &EG(error_zval));
1778 } else if (type != BP_VAR_UNSET) {
1779 goto convert_to_array;
1780 } else {
1781
1782 ZVAL_NULL(result);
1783 }
1784 } else {
1785 if (type == BP_VAR_UNSET) {
1786 zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
1787 ZVAL_NULL(result);
1788 } else {
1789 zend_error(E_WARNING, "Cannot use a scalar value as an array");
1790 ZVAL_INDIRECT(result, &EG(error_zval));
1791 }
1792 }
1793 }
1794
1795 static zend_never_inline void zend_fetch_dimension_address_W(zval *result, zval *container_ptr, zval *dim, int dim_type)
1796 {
1797 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_W);
1798 }
1799
1800 static zend_never_inline void zend_fetch_dimension_address_RW(zval *result, zval *container_ptr, zval *dim, int dim_type)
1801 {
1802 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_RW);
1803 }
1804
1805 static zend_never_inline void zend_fetch_dimension_address_UNSET(zval *result, zval *container_ptr, zval *dim, int dim_type)
1806 {
1807 zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET);
1808 }
1809
1810 static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type)
1811 {
1812 zval *retval;
1813
1814 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1815 try_array:
1816 retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
1817 ZVAL_COPY(result, retval);
1818 return;
1819 } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
1820 container = Z_REFVAL_P(container);
1821 if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
1822 goto try_array;
1823 }
1824 }
1825 if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
1826 zend_long offset;
1827
1828 try_string_offset:
1829 if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1830 switch (Z_TYPE_P(dim)) {
1831
1832 case IS_STRING:
1833 if (IS_LONG == is_numeric_string(Z_STRVAL_P(dim), Z_STRLEN_P(dim), NULL, NULL, -1)) {
1834 break;
1835 }
1836 if (type == BP_VAR_IS) {
1837 ZVAL_NULL(result);
1838 return;
1839 }
1840 zend_error(E_WARNING, "Illegal string offset '%s'", Z_STRVAL_P(dim));
1841 break;
1842 case IS_DOUBLE:
1843 case IS_NULL:
1844 case IS_FALSE:
1845 case IS_TRUE:
1846 if (type != BP_VAR_IS) {
1847 zend_error(E_NOTICE, "String offset cast occurred");
1848 }
1849 break;
1850 case IS_REFERENCE:
1851 dim = Z_REFVAL_P(dim);
1852 goto try_string_offset;
1853 default:
1854 zend_error(E_WARNING, "Illegal offset type");
1855 break;
1856 }
1857
1858 offset = zval_get_long(dim);
1859 } else {
1860 offset = Z_LVAL_P(dim);
1861 }
1862
1863 if (UNEXPECTED(offset < 0) || UNEXPECTED(Z_STRLEN_P(container) <= (size_t)offset)) {
1864 if (type != BP_VAR_IS) {
1865 zend_error(E_NOTICE, "Uninitialized string offset: %pd", offset);
1866 ZVAL_EMPTY_STRING(result);
1867 } else {
1868 ZVAL_NULL(result);
1869 }
1870 } else {
1871 zend_uchar c = (zend_uchar)Z_STRVAL_P(container)[offset];
1872
1873 if (CG(one_char_string)[c]) {
1874 ZVAL_INTERNED_STR(result, CG(one_char_string)[c]);
1875 } else {
1876 ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(container) + offset, 1, 0));
1877 }
1878 }
1879 } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1880 if (!Z_OBJ_HT_P(container)->read_dimension) {
1881 zend_throw_error(NULL, "Cannot use object as array");
1882 ZVAL_NULL(result);
1883 } else {
1884 retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result);
1885
1886 ZEND_ASSERT(result != NULL);
1887 if (retval) {
1888 if (result != retval) {
1889 ZVAL_COPY(result, retval);
1890 }
1891 } else {
1892 ZVAL_NULL(result);
1893 }
1894 }
1895 } else {
1896 ZVAL_NULL(result);
1897 }
1898 }
1899
1900 static zend_never_inline void zend_fetch_dimension_address_read_R(zval *result, zval *container, zval *dim, int dim_type)
1901 {
1902 zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_R);
1903 }
1904
1905 static zend_never_inline void zend_fetch_dimension_address_read_IS(zval *result, zval *container, zval *dim, int dim_type)
1906 {
1907 zend_fetch_dimension_address_read(result, container, dim, dim_type, BP_VAR_IS);
1908 }
1909
1910 ZEND_API void zend_fetch_dimension_by_zval(zval *result, zval *container, zval *dim)
1911 {
1912 zend_fetch_dimension_address_read_R(result, container, dim, IS_TMP_VAR);
1913 }
1914
1915 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)
1916 {
1917 if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
1918 do {
1919 if (container_op_type == IS_VAR && UNEXPECTED(container == &EG(error_zval))) {
1920 ZVAL_INDIRECT(result, &EG(error_zval));
1921 return;
1922 }
1923
1924 if (Z_ISREF_P(container)) {
1925 container = Z_REFVAL_P(container);
1926 if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
1927 break;
1928 }
1929 }
1930
1931
1932 if (type != BP_VAR_UNSET &&
1933 EXPECTED(Z_TYPE_P(container) <= IS_FALSE ||
1934 (Z_TYPE_P(container) == IS_STRING && Z_STRLEN_P(container)==0))) {
1935 zval_ptr_dtor_nogc(container);
1936 object_init(container);
1937 } else {
1938 zend_error(E_WARNING, "Attempt to modify property of non-object");
1939 ZVAL_INDIRECT(result, &EG(error_zval));
1940 return;
1941 }
1942 } while (0);
1943 }
1944 if (prop_op_type == IS_CONST &&
1945 EXPECTED(Z_OBJCE_P(container) == CACHED_PTR_EX(cache_slot))) {
1946 uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1);
1947 zend_object *zobj = Z_OBJ_P(container);
1948 zval *retval;
1949
1950 if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) {
1951 retval = OBJ_PROP(zobj, prop_offset);
1952 if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
1953 ZVAL_INDIRECT(result, retval);
1954 return;
1955 }
1956 } else if (EXPECTED(zobj->properties != NULL)) {
1957 if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) {
1958 if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) {
1959 GC_REFCOUNT(zobj->properties)--;
1960 }
1961 zobj->properties = zend_array_dup(zobj->properties);
1962 }
1963 retval = zend_hash_find(zobj->properties, Z_STR_P(prop_ptr));
1964 if (EXPECTED(retval)) {
1965 ZVAL_INDIRECT(result, retval);
1966 return;
1967 }
1968 }
1969 }
1970 if (EXPECTED(Z_OBJ_HT_P(container)->get_property_ptr_ptr)) {
1971 zval *ptr = Z_OBJ_HT_P(container)->get_property_ptr_ptr(container, prop_ptr, type, cache_slot);
1972 if (NULL == ptr) {
1973 if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1974 ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
1975 if (ptr != result) {
1976 ZVAL_INDIRECT(result, ptr);
1977 } else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
1978 ZVAL_UNREF(ptr);
1979 }
1980 } else {
1981 zend_throw_error(NULL, "Cannot access undefined property for object with overloaded property access");
1982 ZVAL_INDIRECT(result, &EG(error_zval));
1983 }
1984 } else {
1985 ZVAL_INDIRECT(result, ptr);
1986 }
1987 } else if (EXPECTED(Z_OBJ_HT_P(container)->read_property)) {
1988 zval *ptr = Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type, cache_slot, result);
1989 if (ptr != result) {
1990 ZVAL_INDIRECT(result, ptr);
1991 } else if (UNEXPECTED(Z_ISREF_P(ptr) && Z_REFCOUNT_P(ptr) == 1)) {
1992 ZVAL_UNREF(ptr);
1993 }
1994 } else {
1995 zend_error(E_WARNING, "This object doesn't support property references");
1996 ZVAL_INDIRECT(result, &EG(error_zval));
1997 }
1998 }
1999
2000 #if ZEND_INTENSIVE_DEBUGGING
2001
2002 #define CHECK_SYMBOL_TABLES() \
2003 zend_hash_apply(&EG(symbol_table), zend_check_symbol); \
2004 if (&EG(symbol_table)!=EX(symbol_table)) { \
2005 zend_hash_apply(EX(symbol_table), zend_check_symbol); \
2006 }
2007
2008 static int zend_check_symbol(zval *pz)
2009 {
2010 if (Z_TYPE_P(pz) == IS_INDIRECT) {
2011 pz = Z_INDIRECT_P(pz);
2012 }
2013 if (Z_TYPE_P(pz) > 10) {
2014 fprintf(stderr, "Warning! %x has invalid type!\n", *pz);
2015
2016 #ifdef ZEND_WIN32
2017 fflush(stderr);
2018 #endif
2019 } else if (Z_TYPE_P(pz) == IS_ARRAY) {
2020 zend_hash_apply(Z_ARRVAL_P(pz), zend_check_symbol);
2021 } else if (Z_TYPE_P(pz) == IS_OBJECT) {
2022
2023 zend_hash_apply(Z_OBJPROP_P(pz), zend_check_symbol);
2024 }
2025
2026 return 0;
2027 }
2028
2029
2030 #else
2031 #define CHECK_SYMBOL_TABLES()
2032 #endif
2033
2034 ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value)
2035 {
2036 execute_data->func->internal_function.handler(execute_data, return_value);
2037 }
2038
2039 ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table)
2040 {
2041 if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
2042 zend_array_destroy(symbol_table);
2043 } else {
2044
2045
2046 zend_symtable_clean(symbol_table);
2047 *(++EG(symtable_cache_ptr)) = symbol_table;
2048 }
2049 }
2050
2051
2052 static zend_always_inline void i_free_compiled_variables(zend_execute_data *execute_data)
2053 {
2054 zval *cv = EX_VAR_NUM(0);
2055 zval *end = cv + EX(func)->op_array.last_var;
2056 while (EXPECTED(cv != end)) {
2057 if (Z_REFCOUNTED_P(cv)) {
2058 if (!Z_DELREF_P(cv)) {
2059 zend_refcounted *r = Z_COUNTED_P(cv);
2060 ZVAL_NULL(cv);
2061 zval_dtor_func_for_ptr(r);
2062 } else {
2063 GC_ZVAL_CHECK_POSSIBLE_ROOT(cv);
2064 }
2065 }
2066 cv++;
2067 }
2068 }
2069
2070
2071 void zend_free_compiled_variables(zend_execute_data *execute_data)
2072 {
2073 i_free_compiled_variables(execute_data);
2074 }
2075
2076
2077 #ifdef ZEND_WIN32
2078 # define ZEND_VM_INTERRUPT_CHECK() do { \
2079 if (EG(timed_out)) { \
2080 zend_timeout(0); \
2081 } \
2082 } while (0)
2083 #else
2084 # define ZEND_VM_INTERRUPT_CHECK() do { \
2085 } while (0)
2086 #endif
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108 static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, int check_this)
2109 {
2110 uint32_t first_extra_arg, num_args;
2111 ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2112
2113 EX(opline) = op_array->opcodes;
2114 EX(call) = NULL;
2115 EX(return_value) = return_value;
2116
2117
2118 first_extra_arg = op_array->num_args;
2119 num_args = EX_NUM_ARGS();
2120 if (UNEXPECTED(num_args > first_extra_arg)) {
2121 if (EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
2122 zval *end, *src, *dst;
2123 uint32_t type_flags = 0;
2124
2125 if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2126
2127 EX(opline) += first_extra_arg;
2128 }
2129
2130
2131 end = EX_VAR_NUM(first_extra_arg - 1);
2132 src = end + (num_args - first_extra_arg);
2133 dst = src + (op_array->last_var + op_array->T - first_extra_arg);
2134 if (EXPECTED(src != dst)) {
2135 do {
2136 type_flags |= Z_TYPE_INFO_P(src);
2137 ZVAL_COPY_VALUE(dst, src);
2138 ZVAL_UNDEF(src);
2139 src--;
2140 dst--;
2141 } while (src != end);
2142 } else {
2143 do {
2144 type_flags |= Z_TYPE_INFO_P(src);
2145 src--;
2146 } while (src != end);
2147 }
2148 ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
2149 }
2150 } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2151
2152 EX(opline) += num_args;
2153 }
2154
2155
2156 if (EXPECTED((int)num_args < op_array->last_var)) {
2157 zval *var = EX_VAR_NUM(num_args);
2158 zval *end = EX_VAR_NUM(op_array->last_var);
2159
2160 do {
2161 ZVAL_UNDEF(var);
2162 var++;
2163 } while (var != end);
2164 }
2165
2166 if (check_this && op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
2167 ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
2168 GC_REFCOUNT(Z_OBJ(EX(This)))++;
2169 }
2170
2171 if (UNEXPECTED(!op_array->run_time_cache)) {
2172 op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2173 memset(op_array->run_time_cache, 0, op_array->cache_size);
2174 }
2175 EX_LOAD_RUN_TIME_CACHE(op_array);
2176 EX_LOAD_LITERALS(op_array);
2177
2178 EG(current_execute_data) = execute_data;
2179 ZEND_VM_INTERRUPT_CHECK();
2180 }
2181
2182
2183 static zend_always_inline void i_init_code_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value)
2184 {
2185 ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2186
2187 EX(opline) = op_array->opcodes;
2188 EX(call) = NULL;
2189 EX(return_value) = return_value;
2190
2191 if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_OBJ(EX(This)))) {
2192 GC_REFCOUNT(Z_OBJ(EX(This)))++;
2193 if (!zend_hash_str_add(EX(symbol_table), "this", sizeof("this")-1, &EX(This))) {
2194 GC_REFCOUNT(Z_OBJ(EX(This)))--;
2195 }
2196 }
2197
2198 zend_attach_symbol_table(execute_data);
2199
2200 if (!op_array->run_time_cache) {
2201 op_array->run_time_cache = emalloc(op_array->cache_size);
2202 memset(op_array->run_time_cache, 0, op_array->cache_size);
2203 }
2204 EX_LOAD_RUN_TIME_CACHE(op_array);
2205 EX_LOAD_LITERALS(op_array);
2206
2207 EG(current_execute_data) = execute_data;
2208 ZEND_VM_INTERRUPT_CHECK();
2209 }
2210
2211
2212 static zend_always_inline void i_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value)
2213 {
2214 ZEND_ASSERT(EX(func) == (zend_function*)op_array);
2215
2216 EX(opline) = op_array->opcodes;
2217 EX(call) = NULL;
2218 EX(return_value) = return_value;
2219
2220 if (UNEXPECTED(EX(symbol_table) != NULL)) {
2221 if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_OBJ(EX(This)))) {
2222 GC_REFCOUNT(Z_OBJ(EX(This)))++;
2223 if (!zend_hash_str_add(EX(symbol_table), "this", sizeof("this")-1, &EX(This))) {
2224 GC_REFCOUNT(Z_OBJ(EX(This)))--;
2225 }
2226 }
2227
2228 zend_attach_symbol_table(execute_data);
2229 } else {
2230 uint32_t first_extra_arg, num_args;
2231
2232
2233 first_extra_arg = op_array->num_args;
2234 num_args = EX_NUM_ARGS();
2235 if (UNEXPECTED(num_args > first_extra_arg)) {
2236 if (EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) {
2237 zval *end, *src, *dst;
2238 uint32_t type_flags = 0;
2239
2240 if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2241
2242 EX(opline) += first_extra_arg;
2243 }
2244
2245
2246 end = EX_VAR_NUM(first_extra_arg - 1);
2247 src = end + (num_args - first_extra_arg);
2248 dst = src + (op_array->last_var + op_array->T - first_extra_arg);
2249 if (EXPECTED(src != dst)) {
2250 do {
2251 type_flags |= Z_TYPE_INFO_P(src);
2252 ZVAL_COPY_VALUE(dst, src);
2253 ZVAL_UNDEF(src);
2254 src--;
2255 dst--;
2256 } while (src != end);
2257 } else {
2258 do {
2259 type_flags |= Z_TYPE_INFO_P(src);
2260 src--;
2261 } while (src != end);
2262 }
2263 ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
2264 }
2265 } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
2266
2267 EX(opline) += num_args;
2268 }
2269
2270
2271 if (EXPECTED((int)num_args < op_array->last_var)) {
2272 zval *var = EX_VAR_NUM(num_args);
2273 zval *end = EX_VAR_NUM(op_array->last_var);
2274
2275 do {
2276 ZVAL_UNDEF(var);
2277 var++;
2278 } while (var != end);
2279 }
2280
2281 if (op_array->this_var != (uint32_t)-1 && EXPECTED(Z_OBJ(EX(This)))) {
2282 ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
2283 GC_REFCOUNT(Z_OBJ(EX(This)))++;
2284 }
2285 }
2286
2287 if (!op_array->run_time_cache) {
2288 if (op_array->function_name) {
2289 op_array->run_time_cache = zend_arena_alloc(&CG(arena), op_array->cache_size);
2290 } else {
2291 op_array->run_time_cache = emalloc(op_array->cache_size);
2292 }
2293 memset(op_array->run_time_cache, 0, op_array->cache_size);
2294 }
2295 EX_LOAD_RUN_TIME_CACHE(op_array);
2296 EX_LOAD_LITERALS(op_array);
2297
2298 EG(current_execute_data) = execute_data;
2299 ZEND_VM_INTERRUPT_CHECK();
2300 }
2301
2302
2303 ZEND_API zend_execute_data *zend_create_generator_execute_data(zend_execute_data *call, zend_op_array *op_array, zval *return_value)
2304 {
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314 zend_execute_data *execute_data;
2315 uint32_t num_args = ZEND_CALL_NUM_ARGS(call);
2316 size_t stack_size = (ZEND_CALL_FRAME_SLOT + MAX(op_array->last_var + op_array->T, num_args)) * sizeof(zval);
2317 uint32_t call_info;
2318
2319 EG(vm_stack) = zend_vm_stack_new_page(
2320 EXPECTED(stack_size < ZEND_VM_STACK_FREE_PAGE_SIZE(1)) ?
2321 ZEND_VM_STACK_PAGE_SIZE(1) :
2322 ZEND_VM_STACK_PAGE_ALIGNED_SIZE(1, stack_size),
2323 NULL);
2324 EG(vm_stack_top) = EG(vm_stack)->top;
2325 EG(vm_stack_end) = EG(vm_stack)->end;
2326
2327 call_info = ZEND_CALL_TOP_FUNCTION | ZEND_CALL_ALLOCATED | (ZEND_CALL_INFO(call) & (ZEND_CALL_CLOSURE|ZEND_CALL_RELEASE_THIS));
2328 if (Z_OBJ(call->This)) {
2329 call_info |= ZEND_CALL_RELEASE_THIS;
2330 }
2331 execute_data = zend_vm_stack_push_call_frame(
2332 call_info,
2333 (zend_function*)op_array,
2334 num_args,
2335 call->called_scope,
2336 Z_OBJ(call->This));
2337 EX(prev_execute_data) = NULL;
2338 EX_NUM_ARGS() = num_args;
2339
2340
2341 if (num_args > 0) {
2342 zval *arg_src = ZEND_CALL_ARG(call, 1);
2343 zval *arg_dst = ZEND_CALL_ARG(execute_data, 1);
2344 zval *end = arg_src + num_args;
2345
2346 do {
2347 ZVAL_COPY_VALUE(arg_dst, arg_src);
2348 arg_src++;
2349 arg_dst++;
2350 } while (arg_src != end);
2351 }
2352
2353 EX(symbol_table) = NULL;
2354
2355 i_init_func_execute_data(execute_data, op_array, return_value, 1);
2356
2357 return execute_data;
2358 }
2359
2360
2361 ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value)
2362 {
2363 EX(prev_execute_data) = EG(current_execute_data);
2364 i_init_execute_data(execute_data, op_array, return_value);
2365 }
2366
2367
2368 static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call)
2369 {
2370 uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK;
2371 return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num);
2372 }
2373
2374
2375 static zend_execute_data *zend_vm_stack_copy_call_frame(zend_execute_data *call, uint32_t passed_args, uint32_t additional_args)
2376 {
2377 zend_execute_data *new_call;
2378 int used_stack = (EG(vm_stack_top) - (zval*)call) + additional_args;
2379
2380
2381 new_call = zend_vm_stack_extend(used_stack * sizeof(zval));
2382 *new_call = *call;
2383 ZEND_SET_CALL_INFO(new_call, ZEND_CALL_INFO(new_call) | ZEND_CALL_ALLOCATED);
2384
2385 if (passed_args) {
2386 zval *src = ZEND_CALL_ARG(call, 1);
2387 zval *dst = ZEND_CALL_ARG(new_call, 1);
2388 do {
2389 ZVAL_COPY_VALUE(dst, src);
2390 passed_args--;
2391 src++;
2392 dst++;
2393 } while (passed_args);
2394 }
2395
2396
2397 EG(vm_stack)->prev->top = (zval*)call;
2398
2399
2400 if (UNEXPECTED(EG(vm_stack)->prev->top == ZEND_VM_STACK_ELEMETS(EG(vm_stack)->prev))) {
2401 zend_vm_stack r = EG(vm_stack)->prev;
2402
2403 EG(vm_stack)->prev = r->prev;
2404 efree(r);
2405 }
2406
2407 return new_call;
2408 }
2409
2410
2411 static zend_always_inline void zend_vm_stack_extend_call_frame(zend_execute_data **call, uint32_t passed_args, uint32_t additional_args)
2412 {
2413 if (EXPECTED((uint32_t)(EG(vm_stack_end) - EG(vm_stack_top)) > additional_args)) {
2414 EG(vm_stack_top) += additional_args;
2415 } else {
2416 *call = zend_vm_stack_copy_call_frame(*call, passed_args, additional_args);
2417 }
2418 }
2419
2420
2421 static zend_always_inline zend_generator *zend_get_running_generator(zend_execute_data *execute_data)
2422 {
2423
2424 zend_generator *generator = (zend_generator *) EX(return_value);
2425
2426
2427 return generator;
2428 }
2429
2430
2431 static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t op_num)
2432 {
2433 if (UNEXPECTED(EX(call))) {
2434 zend_execute_data *call = EX(call);
2435 zend_op *opline = EX(func)->op_array.opcodes + op_num;
2436 int level;
2437 int do_exit;
2438
2439 if (UNEXPECTED(opline->opcode == ZEND_INIT_FCALL ||
2440 opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
2441 opline->opcode == ZEND_INIT_DYNAMIC_CALL ||
2442 opline->opcode == ZEND_INIT_METHOD_CALL ||
2443 opline->opcode == ZEND_INIT_STATIC_METHOD_CALL)) {
2444 ZEND_ASSERT(op_num);
2445 opline--;
2446 }
2447
2448 do {
2449
2450
2451
2452
2453 level = 0;
2454 do_exit = 0;
2455 do {
2456 switch (opline->opcode) {
2457 case ZEND_DO_FCALL:
2458 case ZEND_DO_ICALL:
2459 case ZEND_DO_UCALL:
2460 case ZEND_DO_FCALL_BY_NAME:
2461 level++;
2462 break;
2463 case ZEND_INIT_FCALL:
2464 case ZEND_INIT_FCALL_BY_NAME:
2465 case ZEND_INIT_NS_FCALL_BY_NAME:
2466 case ZEND_INIT_DYNAMIC_CALL:
2467 case ZEND_INIT_USER_CALL:
2468 case ZEND_INIT_METHOD_CALL:
2469 case ZEND_INIT_STATIC_METHOD_CALL:
2470 case ZEND_NEW:
2471 if (level == 0) {
2472 ZEND_CALL_NUM_ARGS(call) = 0;
2473 do_exit = 1;
2474 }
2475 level--;
2476 break;
2477 case ZEND_SEND_VAL:
2478 case ZEND_SEND_VAL_EX:
2479 case ZEND_SEND_VAR:
2480 case ZEND_SEND_VAR_EX:
2481 case ZEND_SEND_REF:
2482 case ZEND_SEND_VAR_NO_REF:
2483 case ZEND_SEND_USER:
2484 if (level == 0) {
2485 ZEND_CALL_NUM_ARGS(call) = opline->op2.num;
2486 do_exit = 1;
2487 }
2488 break;
2489 case ZEND_SEND_ARRAY:
2490 case ZEND_SEND_UNPACK:
2491 if (level == 0) {
2492 do_exit = 1;
2493 }
2494 break;
2495 }
2496 if (!do_exit) {
2497 opline--;
2498 }
2499 } while (!do_exit);
2500 if (call->prev_execute_data) {
2501
2502 level = 0;
2503 do_exit = 0;
2504 do {
2505 switch (opline->opcode) {
2506 case ZEND_DO_FCALL:
2507 case ZEND_DO_ICALL:
2508 case ZEND_DO_UCALL:
2509 case ZEND_DO_FCALL_BY_NAME:
2510 level++;
2511 break;
2512 case ZEND_INIT_FCALL:
2513 case ZEND_INIT_FCALL_BY_NAME:
2514 case ZEND_INIT_NS_FCALL_BY_NAME:
2515 case ZEND_INIT_DYNAMIC_CALL:
2516 case ZEND_INIT_USER_CALL:
2517 case ZEND_INIT_METHOD_CALL:
2518 case ZEND_INIT_STATIC_METHOD_CALL:
2519 case ZEND_NEW:
2520 if (level == 0) {
2521 do_exit = 1;
2522 }
2523 level--;
2524 break;
2525 }
2526 opline--;
2527 } while (!do_exit);
2528 }
2529
2530 zend_vm_stack_free_args(EX(call));
2531
2532 if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) {
2533 if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
2534 if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) {
2535 GC_REFCOUNT(Z_OBJ(call->This))--;
2536 }
2537 if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
2538 zend_object_store_ctor_failed(Z_OBJ(call->This));
2539 }
2540 }
2541 OBJ_RELEASE(Z_OBJ(call->This));
2542 }
2543 if (call->func->common.fn_flags & ZEND_ACC_CLOSURE) {
2544 zend_object_release((zend_object *) call->func->common.prototype);
2545 } else if (call->func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2546 zend_string_release(call->func->common.function_name);
2547 zend_free_trampoline(call->func);
2548 }
2549
2550 EX(call) = call->prev_execute_data;
2551 zend_vm_stack_free_call_frame(call);
2552 call = EX(call);
2553 } while (call);
2554 }
2555 }
2556
2557
2558 static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num)
2559 {
2560 int i;
2561
2562 for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
2563 const zend_brk_cont_element *brk_cont = &EX(func)->op_array.brk_cont_array[i];
2564 if (brk_cont->start < 0) {
2565 continue;
2566 } else if (brk_cont->start > op_num) {
2567
2568 break;
2569 } else if (op_num < brk_cont->brk) {
2570 if (!catch_op_num || catch_op_num >= brk_cont->brk) {
2571 zend_op *brk_opline = &EX(func)->op_array.opcodes[brk_cont->brk];
2572
2573 if (brk_opline->opcode == ZEND_FREE) {
2574 zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
2575 } else if (brk_opline->opcode == ZEND_FE_FREE) {
2576 zval *var = EX_VAR(brk_opline->op1.var);
2577 if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
2578 zend_hash_iterator_del(Z_FE_ITER_P(var));
2579 }
2580 zval_ptr_dtor_nogc(var);
2581 } else if (brk_opline->opcode == ZEND_ROPE_END) {
2582 zend_string **rope = (zend_string **) EX_VAR(brk_opline->op1.var);
2583 zend_op *last = EX(func)->op_array.opcodes + op_num;
2584 while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
2585 || last->result.var != brk_opline->op1.var) {
2586 ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
2587 last--;
2588 }
2589 if (last->opcode == ZEND_ROPE_INIT) {
2590 zend_string_release(*rope);
2591 } else {
2592 int j = last->extended_value;
2593 do {
2594 zend_string_release(rope[j]);
2595 } while (j--);
2596 }
2597 } else if (brk_opline->opcode == ZEND_END_SILENCE) {
2598
2599 if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
2600 EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
2601 }
2602 }
2603 }
2604 }
2605 }
2606 }
2607
2608
2609 void zend_cleanup_unfinished_execution(zend_execute_data *execute_data, uint32_t op_num, uint32_t catch_op_num) {
2610 cleanup_unfinished_calls(execute_data, op_num);
2611 cleanup_live_vars(execute_data, op_num, catch_op_num);
2612 }
2613
2614 #ifdef HAVE_GCC_GLOBAL_REGS
2615 # if defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(i386)
2616 # define ZEND_VM_FP_GLOBAL_REG "%esi"
2617 # define ZEND_VM_IP_GLOBAL_REG "%edi"
2618 # elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__x86_64__)
2619 # define ZEND_VM_FP_GLOBAL_REG "%r14"
2620 # define ZEND_VM_IP_GLOBAL_REG "%r15"
2621 # elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
2622 # define ZEND_VM_FP_GLOBAL_REG "r28"
2623 # define ZEND_VM_IP_GLOBAL_REG "r29"
2624 # elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
2625 # define ZEND_VM_FP_GLOBAL_REG "r28"
2626 # define ZEND_VM_IP_GLOBAL_REG "r29"
2627 # endif
2628 #endif
2629
2630 #define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \
2631 CHECK_SYMBOL_TABLES() \
2632 if (check_exception) { \
2633 OPLINE = EX(opline) + (skip); \
2634 } else { \
2635 OPLINE = opline + (skip); \
2636 } \
2637 ZEND_VM_CONTINUE()
2638
2639 #define ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() \
2640 ZEND_VM_NEXT_OPCODE_EX(1, 1)
2641
2642 #define ZEND_VM_NEXT_OPCODE() \
2643 ZEND_VM_NEXT_OPCODE_EX(0, 1)
2644
2645 #define ZEND_VM_SET_NEXT_OPCODE(new_op) \
2646 CHECK_SYMBOL_TABLES() \
2647 OPLINE = new_op
2648
2649 #define ZEND_VM_SET_OPCODE(new_op) \
2650 CHECK_SYMBOL_TABLES() \
2651 OPLINE = new_op; \
2652 ZEND_VM_INTERRUPT_CHECK()
2653
2654 #define ZEND_VM_SET_RELATIVE_OPCODE(opline, offset) \
2655 ZEND_VM_SET_OPCODE(ZEND_OFFSET_TO_OPLINE(opline, offset))
2656
2657 #define ZEND_VM_JMP(new_op) \
2658 if (EXPECTED(!EG(exception))) { \
2659 ZEND_VM_SET_OPCODE(new_op); \
2660 } else { \
2661 LOAD_OPLINE(); \
2662 } \
2663 ZEND_VM_CONTINUE()
2664
2665 #define ZEND_VM_INC_OPCODE() \
2666 OPLINE++
2667
2668
2669 #ifndef VM_SMART_OPCODES
2670 # define VM_SMART_OPCODES 1
2671 #endif
2672
2673 #if VM_SMART_OPCODES
2674 # define ZEND_VM_REPEATABLE_OPCODE \
2675 do {
2676 # define ZEND_VM_REPEAT_OPCODE(_opcode) \
2677 } while (UNEXPECTED((++opline)->opcode == _opcode)); \
2678 OPLINE = opline; \
2679 ZEND_VM_CONTINUE()
2680 # define ZEND_VM_SMART_BRANCH(_result, _check) do { \
2681 int __result; \
2682 if (EXPECTED((opline+1)->opcode == ZEND_JMPZ)) { \
2683 __result = (_result); \
2684 } else if (EXPECTED((opline+1)->opcode == ZEND_JMPNZ)) { \
2685 __result = !(_result); \
2686 } else { \
2687 break; \
2688 } \
2689 if ((_check) && UNEXPECTED(EG(exception))) { \
2690 HANDLE_EXCEPTION(); \
2691 } \
2692 if (__result) { \
2693 ZEND_VM_SET_NEXT_OPCODE(opline + 2); \
2694 } else { \
2695 ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline + 1, (opline+1)->op2)); \
2696 } \
2697 ZEND_VM_CONTINUE(); \
2698 } while (0)
2699 #else
2700 # define ZEND_VM_REPEATABLE_OPCODE
2701 # define ZEND_VM_REPEAT_OPCODE(_opcode)
2702 # define ZEND_VM_SMART_BRANCH(_result, _check)
2703 #endif
2704
2705 #ifdef __GNUC__
2706 # define ZEND_VM_GUARD(name) __asm__("#" #name)
2707 #else
2708 # define ZEND_VM_GUARD(name)
2709 #endif
2710
2711 #define GET_OP1_UNDEF_CV(ptr, type) \
2712 _get_zval_cv_lookup_ ## type(ptr, opline->op1.var, execute_data)
2713 #define GET_OP2_UNDEF_CV(ptr, type) \
2714 _get_zval_cv_lookup_ ## type(ptr, opline->op2.var, execute_data)
2715
2716 #include "zend_vm_execute.h"
2717
2718 ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
2719 {
2720 if (opcode != ZEND_USER_OPCODE) {
2721 if (handler == NULL) {
2722
2723 zend_user_opcodes[opcode] = opcode;
2724 } else {
2725 zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
2726 }
2727 zend_user_opcode_handlers[opcode] = handler;
2728 return SUCCESS;
2729 }
2730 return FAILURE;
2731 }
2732
2733 ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode)
2734 {
2735 return zend_user_opcode_handlers[opcode];
2736 }
2737
2738 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)
2739 {
2740 return get_zval_ptr(op_type, *node, execute_data, should_free, type);
2741 }
2742
2743 ZEND_API void ZEND_FASTCALL zend_check_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
2744 {
2745 zend_verify_internal_arg_type(zf, arg_num, arg);
2746 }
2747
2748 ZEND_API int ZEND_FASTCALL zend_check_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, void **cache_slot)
2749 {
2750 return zend_verify_arg_type(zf, arg_num, arg, default_value, cache_slot);
2751 }
2752
2753 ZEND_API void ZEND_FASTCALL zend_check_missing_arg(zend_execute_data *execute_data, uint32_t arg_num, void **cache_slot)
2754 {
2755 zend_verify_missing_arg(execute_data, arg_num, cache_slot);
2756 }
2757
2758
2759
2760
2761
2762
2763
2764