mirror of
https://github.com/php/php-src.git
synced 2024-09-25 03:47:26 +00:00
f62ad3bc57
* origin/master: made the apache ini holders to be zend_bool Removed useless local variable Use simpler functions Fixed test small fixes to UPGRADING Reorder to save alignment size (of course, only for common used structs)
40029 lines
1.2 MiB
40029 lines
1.2 MiB
/*
|
|
+----------------------------------------------------------------------+
|
|
| Zend Engine |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 1998-2014 Zend Technologies Ltd. (http://www.zend.com) |
|
|
+----------------------------------------------------------------------+
|
|
| This source file is subject to version 2.00 of the Zend license, |
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
| available through the world-wide-web at the following url: |
|
|
| http://www.zend.com/license/2_00.txt. |
|
|
| If you did not receive a copy of the Zend license and are unable to |
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
| license@zend.com so we can mail you a copy immediately. |
|
|
+----------------------------------------------------------------------+
|
|
| Authors: Andi Gutmans <andi@zend.com> |
|
|
| Zeev Suraski <zeev@zend.com> |
|
|
| Dmitry Stogov <dmitry@zend.com> |
|
|
+----------------------------------------------------------------------+
|
|
*/
|
|
|
|
#ifdef ZEND_WIN32
|
|
# pragma warning(once : 4101)
|
|
# pragma warning(once : 6235)
|
|
# pragma warning(once : 6237)
|
|
# pragma warning(once : 6239)
|
|
# pragma warning(once : 6240)
|
|
# pragma warning(once : 6285)
|
|
# pragma warning(once : 6286)
|
|
# pragma warning(once : 6326)
|
|
#endif
|
|
static user_opcode_handler_t zend_user_opcode_handlers[256] = {
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL,
|
|
(user_opcode_handler_t)NULL
|
|
};
|
|
|
|
static zend_uchar zend_user_opcodes[256] = {0,
|
|
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
|
|
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,
|
|
33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,
|
|
49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
|
|
65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
|
|
81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,
|
|
97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,
|
|
113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
|
|
129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,
|
|
145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,
|
|
161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
|
|
177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
|
|
193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,
|
|
209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
|
|
225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,
|
|
241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
|
|
};
|
|
|
|
static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);
|
|
|
|
|
|
#undef OPLINE
|
|
#undef DCL_OPLINE
|
|
#undef USE_OPLINE
|
|
#undef LOAD_OPLINE
|
|
#undef SAVE_OPLINE
|
|
#define OPLINE EX(opline)
|
|
#define DCL_OPLINE
|
|
#define USE_OPLINE const zend_op *opline = EX(opline);
|
|
#define LOAD_OPLINE()
|
|
#define SAVE_OPLINE()
|
|
#undef CHECK_EXCEPTION
|
|
#undef HANDLE_EXCEPTION
|
|
#undef HANDLE_EXCEPTION_LEAVE
|
|
#define CHECK_EXCEPTION() LOAD_OPLINE()
|
|
#define HANDLE_EXCEPTION() LOAD_OPLINE(); ZEND_VM_CONTINUE()
|
|
#define HANDLE_EXCEPTION_LEAVE() LOAD_OPLINE(); ZEND_VM_LEAVE()
|
|
#define ZEND_VM_CONTINUE() return 0
|
|
#define ZEND_VM_RETURN() return -1
|
|
#define ZEND_VM_ENTER() return 1
|
|
#define ZEND_VM_LEAVE() return 2
|
|
#define ZEND_VM_DISPATCH(opcode, opline) return zend_vm_get_opcode_handler(opcode, opline)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
|
|
#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL execute_data
|
|
|
|
ZEND_API void execute_ex(zend_execute_data *execute_data)
|
|
{
|
|
DCL_OPLINE
|
|
|
|
|
|
|
|
LOAD_OPLINE();
|
|
|
|
while (1) {
|
|
int ret;
|
|
#ifdef ZEND_WIN32
|
|
if (EG(timed_out)) {
|
|
zend_timeout(0);
|
|
}
|
|
#endif
|
|
|
|
if (UNEXPECTED((ret = OPLINE->handler(execute_data)) != 0)) {
|
|
if (EXPECTED(ret > 0)) {
|
|
execute_data = EG(current_execute_data);
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");
|
|
}
|
|
|
|
ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)
|
|
{
|
|
zend_execute_data *execute_data;
|
|
|
|
if (EG(exception) != NULL) {
|
|
return;
|
|
}
|
|
|
|
execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE,
|
|
(zend_function*)op_array, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, EG(current_execute_data) ? Z_OBJ(EG(current_execute_data)->This) : NULL, NULL);
|
|
if (EG(current_execute_data)) {
|
|
execute_data->symbol_table = zend_rebuild_symbol_table();
|
|
} else {
|
|
execute_data->symbol_table = &EG(symbol_table);
|
|
}
|
|
EX(prev_execute_data) = EG(current_execute_data);
|
|
i_init_execute_data(execute_data, op_array, return_value);
|
|
zend_execute_ex(execute_data);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zend_call_kind call_kind = EX_CALL_KIND();
|
|
|
|
if (call_kind == ZEND_CALL_NESTED_FUNCTION) {
|
|
zend_object *object;
|
|
|
|
i_free_compiled_variables(execute_data);
|
|
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
|
zend_clean_and_cache_symbol_table(EX(symbol_table));
|
|
}
|
|
zend_vm_stack_free_extra_args(execute_data);
|
|
EG(current_execute_data) = EX(prev_execute_data);
|
|
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(func)->op_array.prototype) {
|
|
OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
|
|
}
|
|
object = Z_OBJ(EX(This));
|
|
zend_vm_stack_free_call_frame(execute_data);
|
|
|
|
execute_data = EG(current_execute_data);
|
|
|
|
if (object) {
|
|
if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) {
|
|
if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
|
|
GC_REFCOUNT(object)--;
|
|
}
|
|
if (GC_REFCOUNT(object) == 1) {
|
|
zend_object_store_ctor_failed(object);
|
|
}
|
|
}
|
|
OBJ_RELEASE(object);
|
|
}
|
|
EG(scope) = EX(func)->op_array.scope;
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
const zend_op *opline = EX(opline);
|
|
zend_throw_exception_internal(NULL);
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
zval_ptr_dtor(EX_VAR(opline->result.var));
|
|
}
|
|
HANDLE_EXCEPTION_LEAVE();
|
|
}
|
|
|
|
LOAD_OPLINE();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_LEAVE();
|
|
} else if (call_kind == ZEND_CALL_NESTED_CODE) {
|
|
zend_detach_symbol_table(execute_data);
|
|
destroy_op_array(&EX(func)->op_array);
|
|
efree_size(EX(func), sizeof(zend_op_array));
|
|
EG(current_execute_data) = EX(prev_execute_data);
|
|
zend_vm_stack_free_call_frame(execute_data);
|
|
|
|
execute_data = EG(current_execute_data);
|
|
zend_attach_symbol_table(execute_data);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION_LEAVE();
|
|
}
|
|
|
|
LOAD_OPLINE();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_LEAVE();
|
|
} else {
|
|
if (call_kind == ZEND_CALL_TOP_FUNCTION) {
|
|
i_free_compiled_variables(execute_data);
|
|
if (UNEXPECTED(EX(symbol_table) != NULL)) {
|
|
zend_clean_and_cache_symbol_table(EX(symbol_table));
|
|
}
|
|
zend_vm_stack_free_extra_args(execute_data);
|
|
EG(current_execute_data) = EX(prev_execute_data);
|
|
if ((EX(func)->op_array.fn_flags & ZEND_ACC_CLOSURE) && EX(func)->op_array.prototype) {
|
|
OBJ_RELEASE((zend_object*)EX(func)->op_array.prototype);
|
|
}
|
|
} else /* if (call_kind == ZEND_CALL_TOP_CODE) */ {
|
|
zend_array *symbol_table = EX(symbol_table);
|
|
zend_execute_data *old_execute_data;
|
|
|
|
zend_detach_symbol_table(execute_data);
|
|
old_execute_data = EX(prev_execute_data);
|
|
while (old_execute_data) {
|
|
if (old_execute_data->func && ZEND_USER_CODE(old_execute_data->func->op_array.type)) {
|
|
if (old_execute_data->symbol_table == symbol_table) {
|
|
zend_attach_symbol_table(old_execute_data);
|
|
}
|
|
break;
|
|
}
|
|
old_execute_data = old_execute_data->prev_execute_data;
|
|
}
|
|
EG(current_execute_data) = EX(prev_execute_data);
|
|
}
|
|
zend_vm_stack_free_call_frame(execute_data);
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_execute_data *call = EX(call);
|
|
zend_function *fbc = call->func;
|
|
zend_object *object = Z_OBJ(call->This);
|
|
|
|
SAVE_OPLINE();
|
|
EX(call) = call->prev_execute_data;
|
|
if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
|
|
}
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) {
|
|
zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated",
|
|
fbc->common.scope ? fbc->common.scope->name->val : "",
|
|
fbc->common.scope ? "::" : "",
|
|
fbc->common.function_name->val);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
}
|
|
|
|
LOAD_OPLINE();
|
|
|
|
if (UNEXPECTED(fbc->type == ZEND_INTERNAL_FUNCTION)) {
|
|
zval *ret;
|
|
|
|
if (fbc->common.scope) {
|
|
/* TODO: we don't set scope if we call an object method ??? */
|
|
/* See: ext/pdo_sqlite/tests/pdo_fetch_func_001.phpt */
|
|
#if 1
|
|
EG(scope) = object ? NULL : fbc->common.scope;
|
|
#else
|
|
EG(scope) = fbc->common.scope;
|
|
#endif
|
|
} else {
|
|
call->called_scope = EX(called_scope);
|
|
Z_OBJ(call->This) = Z_OBJ(EX(This));
|
|
}
|
|
|
|
call->prev_execute_data = execute_data;
|
|
EG(current_execute_data) = call;
|
|
|
|
if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
|
|
uint32_t i;
|
|
zval *p = ZEND_CALL_ARG(call, 1);
|
|
|
|
for (i = 0; i < ZEND_CALL_NUM_ARGS(call); ++i) {
|
|
zend_verify_internal_arg_type(fbc, i + 1, p);
|
|
p++;
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
EG(current_execute_data) = call->prev_execute_data;
|
|
zend_vm_stack_free_args(call);
|
|
zend_vm_stack_free_call_frame(call);
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
|
}
|
|
if (UNEXPECTED(fbc->common.scope)) {
|
|
goto fcall_end_change_scope;
|
|
} else {
|
|
goto fcall_end;
|
|
}
|
|
}
|
|
}
|
|
|
|
ret = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(ret);
|
|
Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
|
|
|
|
if (!zend_execute_internal) {
|
|
/* saves one function call if zend_execute_internal is not used */
|
|
fbc->internal_function.handler(call, ret);
|
|
} else {
|
|
zend_execute_internal(call, ret);
|
|
}
|
|
EG(current_execute_data) = call->prev_execute_data;
|
|
zend_vm_stack_free_args(call);
|
|
zend_vm_stack_free_call_frame(call);
|
|
|
|
if (!RETURN_VALUE_USED(opline)) {
|
|
zval_ptr_dtor(ret);
|
|
}
|
|
|
|
if (UNEXPECTED(fbc->common.scope)) {
|
|
goto fcall_end_change_scope;
|
|
} else {
|
|
goto fcall_end;
|
|
}
|
|
} else if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) {
|
|
EG(scope) = fbc->common.scope;
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
zend_generator_create_zval(call, &fbc->op_array, EX_VAR(opline->result.var));
|
|
} else {
|
|
zend_vm_stack_free_args(call);
|
|
}
|
|
|
|
zend_vm_stack_free_call_frame(call);
|
|
} else {
|
|
zval *return_value = NULL;
|
|
|
|
call->symbol_table = NULL;
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
return_value = EX_VAR(opline->result.var);
|
|
|
|
ZVAL_NULL(return_value);
|
|
Z_VAR_FLAGS_P(return_value) = 0;
|
|
}
|
|
|
|
call->prev_execute_data = execute_data;
|
|
i_init_func_execute_data(call, &fbc->op_array, return_value);
|
|
|
|
if (EXPECTED(zend_execute_ex == execute_ex)) {
|
|
ZEND_VM_ENTER();
|
|
} else {
|
|
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
|
zend_execute_ex(call);
|
|
}
|
|
}
|
|
} else { /* ZEND_OVERLOADED_FUNCTION */
|
|
EG(scope) = fbc->common.scope;
|
|
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
|
|
/* Not sure what should be done here if it's a static method */
|
|
if (EXPECTED(object != NULL)) {
|
|
call->prev_execute_data = execute_data;
|
|
EG(current_execute_data) = call;
|
|
object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var));
|
|
EG(current_execute_data) = call->prev_execute_data;
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
|
|
}
|
|
|
|
zend_vm_stack_free_args(call);
|
|
|
|
zend_vm_stack_free_call_frame(call);
|
|
|
|
if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) {
|
|
zend_string_release(fbc->common.function_name);
|
|
}
|
|
efree(fbc);
|
|
|
|
if (!RETURN_VALUE_USED(opline)) {
|
|
zval_ptr_dtor(EX_VAR(opline->result.var));
|
|
} else {
|
|
//??? Z_UNSET_ISREF_P(EX_T(opline->result.var).var.ptr);
|
|
//??? Z_SET_REFCOUNT_P(EX_T(opline->result.var).var.ptr, 1);
|
|
Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0;
|
|
}
|
|
}
|
|
|
|
fcall_end_change_scope:
|
|
if (object) {
|
|
if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) {
|
|
if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) {
|
|
GC_REFCOUNT(object)--;
|
|
}
|
|
if (GC_REFCOUNT(object) == 1) {
|
|
zend_object_store_ctor_failed(object);
|
|
}
|
|
}
|
|
OBJ_RELEASE(object);
|
|
}
|
|
EG(scope) = EX(func)->op_array.scope;
|
|
|
|
fcall_end:
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zend_throw_exception_internal(NULL);
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
zval_ptr_dtor(EX_VAR(opline->result.var));
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
/* Close the generator to free up resources */
|
|
zend_generator_close(generator, 1);
|
|
|
|
/* Pass execution back to handling code */
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *args;
|
|
int arg_num;
|
|
SAVE_OPLINE();
|
|
|
|
args = get_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R);
|
|
arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1;
|
|
|
|
send_again:
|
|
switch (Z_TYPE_P(args)) {
|
|
case IS_ARRAY: {
|
|
HashTable *ht = Z_ARRVAL_P(args);
|
|
zval *arg, *top;
|
|
zend_string *name;
|
|
|
|
zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
|
|
|
|
if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
|
|
uint32_t i;
|
|
int separate = 0;
|
|
|
|
/* check if any of arguments are going to be passed by reference */
|
|
for (i = 0; i < zend_hash_num_elements(ht); i++) {
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
|
|
separate = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (separate) {
|
|
zval_copy_ctor(args);
|
|
ht = Z_ARRVAL_P(args);
|
|
}
|
|
}
|
|
|
|
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
|
|
if (name) {
|
|
zend_error(E_RECOVERABLE_ERROR, "Cannot unpack array with string keys");
|
|
FREE_OP(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
top = ZEND_CALL_ARG(EX(call), arg_num);
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
|
|
if (!Z_IMMUTABLE_P(args)) {
|
|
ZVAL_MAKE_REF(arg);
|
|
Z_ADDREF_P(arg);
|
|
ZVAL_REF(top, Z_REF_P(arg));
|
|
} else {
|
|
ZVAL_DUP(top, arg);
|
|
}
|
|
} else if (Z_ISREF_P(arg)) {
|
|
ZVAL_COPY(top, Z_REFVAL_P(arg));
|
|
} else {
|
|
ZVAL_COPY(top, arg);
|
|
}
|
|
|
|
ZEND_CALL_NUM_ARGS(EX(call))++;
|
|
arg_num++;
|
|
} ZEND_HASH_FOREACH_END();
|
|
|
|
break;
|
|
}
|
|
case IS_OBJECT: {
|
|
zend_class_entry *ce = Z_OBJCE_P(args);
|
|
zend_object_iterator *iter;
|
|
|
|
if (!ce || !ce->get_iterator) {
|
|
zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
|
|
break;
|
|
}
|
|
|
|
iter = ce->get_iterator(ce, args, 0);
|
|
if (UNEXPECTED(!iter)) {
|
|
FREE_OP(free_op1);
|
|
if (!EG(exception)) {
|
|
zend_throw_exception_ex(
|
|
NULL, 0, "Object of type %s did not create an Iterator", ce->name->val
|
|
);
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
if (iter->funcs->rewind) {
|
|
iter->funcs->rewind(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
goto unpack_iter_dtor;
|
|
}
|
|
}
|
|
|
|
for (; iter->funcs->valid(iter) == SUCCESS; ++arg_num) {
|
|
zval *arg, *top;
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
goto unpack_iter_dtor;
|
|
}
|
|
|
|
arg = iter->funcs->get_current_data(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
goto unpack_iter_dtor;
|
|
}
|
|
|
|
if (iter->funcs->get_current_key) {
|
|
zval key;
|
|
iter->funcs->get_current_key(iter, &key);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
goto unpack_iter_dtor;
|
|
}
|
|
|
|
if (Z_TYPE(key) == IS_STRING) {
|
|
zend_error(E_RECOVERABLE_ERROR,
|
|
"Cannot unpack Traversable with string keys");
|
|
zend_string_release(Z_STR(key));
|
|
goto unpack_iter_dtor;
|
|
}
|
|
|
|
zval_dtor(&key);
|
|
}
|
|
|
|
if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
|
|
zend_error(
|
|
E_WARNING, "Cannot pass by-reference argument %d of %s%s%s()"
|
|
" by unpacking a Traversable, passing by-value instead", arg_num,
|
|
EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
|
|
EX(call)->func->common.scope ? "::" : "",
|
|
EX(call)->func->common.function_name->val
|
|
);
|
|
}
|
|
|
|
if (Z_ISREF_P(arg)) {
|
|
ZVAL_DUP(arg, Z_REFVAL_P(arg));
|
|
} else {
|
|
if (Z_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
|
}
|
|
|
|
zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, 1);
|
|
top = ZEND_CALL_ARG(EX(call), arg_num);
|
|
ZVAL_COPY_VALUE(top, arg);
|
|
ZEND_CALL_NUM_ARGS(EX(call))++;
|
|
|
|
iter->funcs->move_forward(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
goto unpack_iter_dtor;
|
|
}
|
|
}
|
|
|
|
unpack_iter_dtor:
|
|
zend_iterator_dtor(iter);
|
|
break;
|
|
}
|
|
case IS_REFERENCE:
|
|
args = Z_REFVAL_P(args);
|
|
goto send_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
|
|
}
|
|
|
|
FREE_OP(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_ARRAY_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *args;
|
|
SAVE_OPLINE();
|
|
|
|
args = get_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(args) != IS_ARRAY)) {
|
|
if ((opline->op1_type & (IS_VAR|IS_CV)) && Z_ISREF_P(args)) {
|
|
args = Z_REFVAL_P(args);
|
|
if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
|
|
goto send_array;
|
|
}
|
|
}
|
|
zend_error(E_WARNING, "call_user_func_array() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(args)));
|
|
if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
|
|
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
|
|
}
|
|
if (Z_OBJ(EX(call)->This)) {
|
|
OBJ_RELEASE(Z_OBJ(EX(call)->This));
|
|
}
|
|
EX(call)->func = (zend_function*)&zend_pass_function;
|
|
EX(call)->called_scope = NULL;
|
|
Z_OBJ(EX(call)->This) = NULL;
|
|
} else {
|
|
uint32_t arg_num;
|
|
HashTable *ht;
|
|
zval *arg, *param, tmp;
|
|
|
|
send_array:
|
|
arg_num = 1;
|
|
ht = Z_ARRVAL_P(args);
|
|
zend_vm_stack_extend_call_frame(&EX(call), 0, zend_hash_num_elements(ht));
|
|
|
|
if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
|
|
uint32_t i;
|
|
int separate = 0;
|
|
|
|
/* check if any of arguments are going to be passed by reference */
|
|
for (i = 0; i < zend_hash_num_elements(ht); i++) {
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
|
|
separate = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (separate) {
|
|
zval_copy_ctor(args);
|
|
ht = Z_ARRVAL_P(args);
|
|
}
|
|
}
|
|
|
|
param = ZEND_CALL_ARG(EX(call), arg_num);
|
|
ZEND_HASH_FOREACH_VAL(ht, arg) {
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
|
|
// TODO: Scalar values don't have reference counters anymore.
|
|
// They are assumed to be 1, and they may be easily passed by
|
|
// reference now. However, previously scalars with refcount==1
|
|
// might be passed and with refcount>1 might not. We can support
|
|
// only single behavior ???
|
|
#if 0
|
|
if (Z_REFCOUNTED_P(arg) &&
|
|
// This solution breaks the following test (omit warning message) ???
|
|
// Zend/tests/bug61273.phpt
|
|
// ext/reflection/tests/bug42976.phpt
|
|
// ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
|
|
#else
|
|
if (!Z_REFCOUNTED_P(arg) ||
|
|
// This solution breaks the following test (emit warning message) ???
|
|
// ext/pdo_sqlite/tests/pdo_005.phpt
|
|
#endif
|
|
(!Z_ISREF_P(arg) && Z_REFCOUNT_P(arg) > 1)) {
|
|
|
|
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
|
|
|
|
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
|
|
arg_num,
|
|
EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
|
|
EX(call)->func->common.scope ? "::" : "",
|
|
EX(call)->func->common.function_name->val);
|
|
|
|
if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
|
|
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
|
|
}
|
|
if (Z_OBJ(EX(call)->This)) {
|
|
OBJ_RELEASE(Z_OBJ(EX(call)->This));
|
|
}
|
|
EX(call)->func = (zend_function*)&zend_pass_function;
|
|
EX(call)->called_scope = NULL;
|
|
Z_OBJ(EX(call)->This) = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
if (Z_REFCOUNTED_P(arg)) {
|
|
Z_DELREF_P(arg);
|
|
}
|
|
ZVAL_DUP(&tmp, arg);
|
|
ZVAL_NEW_REF(arg, &tmp);
|
|
Z_ADDREF_P(arg);
|
|
} else if (!Z_ISREF_P(arg)) {
|
|
ZVAL_NEW_REF(arg, arg);
|
|
Z_ADDREF_P(arg);
|
|
} else if (Z_REFCOUNTED_P(arg)) {
|
|
Z_ADDREF_P(arg);
|
|
}
|
|
ZVAL_COPY_VALUE(param, arg);
|
|
} else if (Z_ISREF_P(arg) &&
|
|
/* don't separate references for __call */
|
|
(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
|
|
ZVAL_DUP(param, Z_REFVAL_P(arg));
|
|
} else {
|
|
ZVAL_COPY(param, arg);
|
|
}
|
|
ZEND_CALL_NUM_ARGS(EX(call))++;
|
|
arg_num++;
|
|
param++;
|
|
} ZEND_HASH_FOREACH_END();
|
|
}
|
|
FREE_OP(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
uint32_t arg_num = opline->op1.num;
|
|
|
|
SAVE_OPLINE();
|
|
if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
|
|
zend_verify_missing_arg(execute_data, arg_num);
|
|
CHECK_EXCEPTION();
|
|
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
|
|
zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
|
|
|
|
zend_verify_arg_type(EX(func), arg_num, param, NULL);
|
|
CHECK_EXCEPTION();
|
|
}
|
|
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
uint32_t arg_num = opline->op1.num;
|
|
uint32_t arg_count = EX_NUM_ARGS();
|
|
zval *params;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
|
|
|
|
if (arg_num <= arg_count) {
|
|
zval *param;
|
|
|
|
array_init_size(params, arg_count - arg_num + 1);
|
|
param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
|
|
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
|
|
do {
|
|
zend_verify_arg_type(EX(func), arg_num, param, NULL);
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
|
|
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
|
|
param++;
|
|
} while (++arg_num <= arg_count);
|
|
} else {
|
|
do {
|
|
zend_hash_next_index_insert_new(Z_ARRVAL_P(params), param);
|
|
if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
|
|
param++;
|
|
} while (++arg_num <= arg_count);
|
|
}
|
|
} else {
|
|
array_init(params);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
ZVAL_LONG(EX_VAR(opline->result.var), EG(error_reporting));
|
|
|
|
if (EG(error_reporting)) {
|
|
do {
|
|
EG(error_reporting) = 0;
|
|
if (!EG(error_reporting_ini_entry)) {
|
|
zend_ini_entry *p = zend_hash_str_find_ptr(EG(ini_directives), "error_reporting", sizeof("error_reporting")-1);
|
|
if (p) {
|
|
EG(error_reporting_ini_entry) = p;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (!EG(error_reporting_ini_entry)->modified) {
|
|
if (!EG(modified_ini_directives)) {
|
|
ALLOC_HASHTABLE(EG(modified_ini_directives));
|
|
zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
|
|
}
|
|
if (EXPECTED(zend_hash_str_add_ptr(EG(modified_ini_directives), "error_reporting", sizeof("error_reporting")-1, EG(error_reporting_ini_entry)) != NULL)) {
|
|
EG(error_reporting_ini_entry)->orig_value = EG(error_reporting_ini_entry)->value;
|
|
EG(error_reporting_ini_entry)->orig_modifiable = EG(error_reporting_ini_entry)->modifiable;
|
|
EG(error_reporting_ini_entry)->modified = 1;
|
|
}
|
|
}
|
|
} while (0);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXT_STMT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
SAVE_OPLINE();
|
|
if (!EG(no_extensions)) {
|
|
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, EX(func));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
SAVE_OPLINE();
|
|
if (!EG(no_extensions)) {
|
|
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, EX(func));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXT_FCALL_END_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
SAVE_OPLINE();
|
|
if (!EG(no_extensions)) {
|
|
zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, EX(func));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DECLARE_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_class(&EX(func)->op_array, opline, EG(class_table), 0);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
Z_CE_P(EX_VAR(opline->result.var)) = do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *zce, *orig_zce;
|
|
|
|
SAVE_OPLINE();
|
|
if ((zce = zend_hash_find(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op2)))) == NULL ||
|
|
((orig_zce = zend_hash_find(EG(class_table), Z_STR_P(EX_CONSTANT(opline->op1)))) != NULL &&
|
|
Z_CE_P(zce) != Z_CE_P(orig_zce))) {
|
|
do_bind_inherited_class(&EX(func)->op_array, opline, EG(class_table), Z_CE_P(EX_VAR(opline->extended_value)), 0);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DECLARE_FUNCTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
do_bind_function(&EX(func)->op_array, opline, EG(function_table), 0);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_TICKS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if ((uint32_t)++EG(ticks_count) >= opline->extended_value) {
|
|
EG(ticks_count) = 0;
|
|
if (zend_ticks_function) {
|
|
zend_ticks_function(opline->extended_value);
|
|
}
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXT_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_NOP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_TRAIT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_class_entry *ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
zend_class_entry *trait;
|
|
|
|
SAVE_OPLINE();
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
trait = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
trait = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)),
|
|
EX_CONSTANT(opline->op2) + 1,
|
|
ZEND_FETCH_CLASS_TRAIT);
|
|
if (UNEXPECTED(trait == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
if (!((trait->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT)) {
|
|
zend_error_noreturn(E_ERROR, "%s cannot use %s - it is not a trait", ce->name->val, trait->name->val);
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), trait);
|
|
}
|
|
|
|
zend_do_implement_trait(ce, trait);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BIND_TRAITS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_class_entry *ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
|
|
SAVE_OPLINE();
|
|
zend_do_bind_traits(ce);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes;
|
|
int i;
|
|
uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0;
|
|
int in_finally = 0;
|
|
|
|
for (i = 0; i < EX(func)->op_array.last_try_catch; i++) {
|
|
if (EX(func)->op_array.try_catch_array[i].try_op > op_num) {
|
|
/* further blocks will not be relevant... */
|
|
break;
|
|
}
|
|
in_finally = 0;
|
|
if (op_num < EX(func)->op_array.try_catch_array[i].catch_op) {
|
|
catch_op_num = EX(func)->op_array.try_catch_array[i].catch_op;
|
|
}
|
|
if (op_num < EX(func)->op_array.try_catch_array[i].finally_op) {
|
|
finally_op_num = EX(func)->op_array.try_catch_array[i].finally_op;
|
|
finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
|
|
}
|
|
if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op &&
|
|
op_num < EX(func)->op_array.try_catch_array[i].finally_end) {
|
|
finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end;
|
|
in_finally = 1;
|
|
}
|
|
}
|
|
|
|
if (EX(call)) {
|
|
zend_execute_data *call = EX(call);
|
|
do {
|
|
/* If the exception was thrown during a function call there might be
|
|
* arguments pushed to the stack that have to be dtor'ed. */
|
|
zend_vm_stack_free_args(EX(call));
|
|
|
|
if (Z_OBJ(call->This)) {
|
|
if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) {
|
|
if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) {
|
|
GC_REFCOUNT(Z_OBJ(call->This))--;
|
|
}
|
|
if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) {
|
|
zend_object_store_ctor_failed(Z_OBJ(call->This));
|
|
}
|
|
}
|
|
OBJ_RELEASE(Z_OBJ(call->This));
|
|
}
|
|
EX(call) = call->prev_execute_data;
|
|
zend_vm_stack_free_call_frame(call);
|
|
call = EX(call);
|
|
} while (call);
|
|
}
|
|
|
|
for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
|
|
if (EX(func)->op_array.brk_cont_array[i].start < 0) {
|
|
continue;
|
|
} else if (EX(func)->op_array.brk_cont_array[i].start > op_num) {
|
|
/* further blocks will not be relevant... */
|
|
break;
|
|
} else if (op_num < EX(func)->op_array.brk_cont_array[i].brk) {
|
|
if (!catch_op_num ||
|
|
catch_op_num >= EX(func)->op_array.brk_cont_array[i].brk) {
|
|
zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
|
|
|
|
if (brk_opline->opcode == ZEND_FREE) {
|
|
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
|
|
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
|
|
}
|
|
} else if (brk_opline->opcode == ZEND_END_SILENCE) {
|
|
/* restore previous error_reporting value */
|
|
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
|
|
EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
|
|
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
|
|
|
|
if (in_finally && Z_OBJ_P(fast_call)) {
|
|
zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call));
|
|
}
|
|
Z_OBJ_P(fast_call) = EG(exception);
|
|
EG(exception) = NULL;
|
|
fast_call->u2.lineno = (uint32_t)-1;
|
|
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op_num]);
|
|
ZEND_VM_CONTINUE();
|
|
} else {
|
|
if (in_finally) {
|
|
/* we are going out of current finally scope */
|
|
zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var);
|
|
|
|
if (Z_OBJ_P(fast_call)) {
|
|
zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call));
|
|
Z_OBJ_P(fast_call) = NULL;
|
|
}
|
|
}
|
|
if (catch_op_num) {
|
|
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
|
|
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
zend_verify_abstract_class(Z_CE_P(EX_VAR(opline->op1.var)));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
int ret;
|
|
|
|
SAVE_OPLINE();
|
|
ret = zend_user_opcode_handlers[opline->opcode](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_INTERNAL);
|
|
LOAD_OPLINE();
|
|
|
|
switch (ret) {
|
|
case ZEND_USER_OPCODE_CONTINUE:
|
|
ZEND_VM_CONTINUE();
|
|
case ZEND_USER_OPCODE_RETURN:
|
|
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
|
|
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
case ZEND_USER_OPCODE_ENTER:
|
|
ZEND_VM_ENTER();
|
|
case ZEND_USER_OPCODE_LEAVE:
|
|
ZEND_VM_LEAVE();
|
|
case ZEND_USER_OPCODE_DISPATCH:
|
|
ZEND_VM_DISPATCH(opline->opcode, opline);
|
|
default:
|
|
ZEND_VM_DISPATCH((zend_uchar)(ret & 0xff), opline);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *fast_call = EX_VAR(opline->op1.var);
|
|
|
|
/* check for delayed exception */
|
|
if (Z_OBJ_P(fast_call) != NULL) {
|
|
/* discard the previously thrown exception */
|
|
OBJ_RELEASE(Z_OBJ_P(fast_call));
|
|
Z_OBJ_P(fast_call) = NULL;
|
|
}
|
|
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *fast_call = EX_VAR(opline->result.var);
|
|
|
|
if ((opline->extended_value & ZEND_FAST_CALL_FROM_CATCH) &&
|
|
UNEXPECTED(EG(prev_exception) != NULL)) {
|
|
/* in case of unhandled exception jump to catch block instead of finally */
|
|
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
/* set no delayed exception */
|
|
Z_OBJ_P(fast_call) = NULL;
|
|
/* set return address */
|
|
fast_call->u2.lineno = opline - EX(func)->op_array.opcodes;
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *fast_call = EX_VAR(opline->op1.var);
|
|
|
|
if (fast_call->u2.lineno != (uint32_t)-1) {
|
|
const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno;
|
|
ZEND_VM_SET_OPCODE(fast_ret + 1);
|
|
if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) {
|
|
fast_call->u2.lineno = fast_ret->op2.opline_num;
|
|
}
|
|
ZEND_VM_CONTINUE();
|
|
} else {
|
|
/* special case for unhandled exceptions */
|
|
USE_OPLINE
|
|
|
|
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
|
|
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
|
|
ZEND_VM_CONTINUE();
|
|
} else {
|
|
EG(exception) = Z_OBJ_P(fast_call);
|
|
Z_OBJ_P(fast_call) = NULL;
|
|
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
|
|
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) {
|
|
return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (EG(exception)) {
|
|
zend_exception_save();
|
|
}
|
|
if (IS_CONST == IS_UNUSED) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->extended_value);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval *class_name = EX_CONSTANT(opline->op2);
|
|
|
|
try_class_name:
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
|
|
} else {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var)));
|
|
}
|
|
} else if (Z_TYPE_P(class_name) == IS_OBJECT) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name);
|
|
} else if (Z_TYPE_P(class_name) == IS_STRING) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->extended_value);
|
|
} else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) {
|
|
class_name = Z_REFVAL_P(class_name);
|
|
goto try_class_name;
|
|
} else {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_function *fbc;
|
|
zval *function_name, *func;
|
|
|
|
if (IS_CONST == IS_CONST && Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_STRING) {
|
|
function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
|
|
SAVE_OPLINE();
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
fbc = Z_FUNC_P(func);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, NULL, NULL, EX(call));
|
|
|
|
/*CHECK_EXCEPTION();*/
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_string *lcname;
|
|
zend_free_op free_op2;
|
|
zend_class_entry *called_scope;
|
|
zend_object *object;
|
|
|
|
SAVE_OPLINE();
|
|
function_name = EX_CONSTANT(opline->op2);
|
|
|
|
try_function_name:
|
|
if (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
|
|
if (Z_STRVAL_P(function_name)[0] == '\\') {
|
|
lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
|
|
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
|
|
} else {
|
|
lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
|
|
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
|
|
}
|
|
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
|
|
}
|
|
zend_string_free(lcname);
|
|
|
|
fbc = Z_FUNC_P(func);
|
|
called_scope = NULL;
|
|
object = NULL;
|
|
} else if (IS_CONST != IS_CONST &&
|
|
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
|
|
Z_OBJ_HANDLER_P(function_name, get_closure) &&
|
|
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) {
|
|
if (object) {
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (IS_CONST == IS_VAR && (fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
|
|
/* Delay closure destruction until its invocation */
|
|
fbc->common.prototype = (zend_function*)Z_OBJ_P(free_op2);
|
|
} else if (IS_CONST == IS_CV) {
|
|
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
|
|
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
|
|
zval *obj;
|
|
zval *method;
|
|
|
|
obj = zend_hash_index_find(Z_ARRVAL_P(function_name), 0);
|
|
method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1);
|
|
|
|
if (!obj || !method) {
|
|
zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
|
|
}
|
|
|
|
ZVAL_DEREF(obj);
|
|
if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
|
|
zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
|
|
}
|
|
|
|
ZVAL_DEREF(method);
|
|
if (Z_TYPE_P(method) != IS_STRING) {
|
|
zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
|
|
}
|
|
|
|
if (Z_TYPE_P(obj) == IS_STRING) {
|
|
object = NULL;
|
|
called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0);
|
|
if (UNEXPECTED(called_scope == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (called_scope->get_static_method) {
|
|
fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
|
|
} else {
|
|
fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
|
|
}
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val);
|
|
} else {
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val);
|
|
}
|
|
}
|
|
} else {
|
|
called_scope = Z_OBJCE_P(obj);
|
|
object = Z_OBJ_P(obj);
|
|
|
|
fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method));
|
|
}
|
|
|
|
if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
|
|
object = NULL;
|
|
} else {
|
|
GC_REFCOUNT(object)++; /* For $this pointer */
|
|
}
|
|
}
|
|
|
|
} else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
|
|
function_name = Z_REFVAL_P(function_name);
|
|
goto try_function_name;
|
|
} else {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
ZEND_VM_CONTINUE(); /* Never reached */
|
|
}
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, object, EX(call));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *func_name;
|
|
zval *func;
|
|
zend_function *fbc;
|
|
|
|
func_name = EX_CONSTANT(opline->op2) + 1;
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if ((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL) {
|
|
func_name++;
|
|
if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(func_name))) == NULL)) {
|
|
SAVE_OPLINE();
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
fbc = Z_FUNC_P(func);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
|
|
}
|
|
} else {
|
|
fbc = Z_FUNC_P(func);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, NULL, NULL, EX(call));
|
|
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *fname = EX_CONSTANT(opline->op2);
|
|
zval *func;
|
|
zend_function *fbc;
|
|
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(fname))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(fname));
|
|
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(fname))) == NULL)) {
|
|
SAVE_OPLINE();
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(fname));
|
|
} else {
|
|
fbc = Z_FUNC_P(func);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(fname), fbc);
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame_ex(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->op1.num, NULL, NULL, EX(call));
|
|
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
uint32_t arg_num = opline->op1.num;
|
|
zval *param;
|
|
|
|
SAVE_OPLINE();
|
|
param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
|
|
if (arg_num > EX_NUM_ARGS()) {
|
|
ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2));
|
|
if (Z_OPT_CONSTANT_P(param)) {
|
|
zval_update_constant(param, 0);
|
|
} else {
|
|
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(param))) {
|
|
zval_copy_ctor_func(param);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
|
|
zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_brk_cont_element *el;
|
|
|
|
SAVE_OPLINE();
|
|
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
|
|
&EX(func)->op_array, execute_data);
|
|
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_brk_cont_element *el;
|
|
|
|
SAVE_OPLINE();
|
|
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
|
|
&EX(func)->op_array, execute_data);
|
|
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zend_op *brk_opline;
|
|
USE_OPLINE
|
|
zend_brk_cont_element *el;
|
|
|
|
SAVE_OPLINE();
|
|
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->extended_value,
|
|
&EX(func)->op_array, execute_data);
|
|
|
|
brk_opline = EX(func)->op_array.opcodes + el->brk;
|
|
|
|
if (brk_opline->opcode == ZEND_FREE) {
|
|
if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
|
|
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
|
|
}
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op1));
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_class_entry *ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
zend_class_entry *iface;
|
|
|
|
SAVE_OPLINE();
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
iface = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
iface = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_INTERFACE);
|
|
if (UNEXPECTED(iface == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), iface);
|
|
}
|
|
|
|
if (UNEXPECTED((iface->ce_flags & ZEND_ACC_INTERFACE) == 0)) {
|
|
zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name->val, iface->name->val);
|
|
}
|
|
zend_do_implement_interface(ce, iface);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (EG(exception)) {
|
|
zend_exception_save();
|
|
}
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->extended_value);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval *class_name = NULL;
|
|
|
|
try_class_name:
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
|
|
} else {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var)));
|
|
}
|
|
} else if (Z_TYPE_P(class_name) == IS_OBJECT) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name);
|
|
} else if (Z_TYPE_P(class_name) == IS_STRING) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->extended_value);
|
|
} else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) {
|
|
class_name = Z_REFVAL_P(class_name);
|
|
goto try_class_name;
|
|
} else {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (EG(exception)) {
|
|
zend_exception_save();
|
|
}
|
|
if (IS_CV == IS_UNUSED) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->extended_value);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval *class_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
try_class_name:
|
|
if (IS_CV == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
|
|
} else {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var)));
|
|
}
|
|
} else if (Z_TYPE_P(class_name) == IS_OBJECT) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name);
|
|
} else if (Z_TYPE_P(class_name) == IS_STRING) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->extended_value);
|
|
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) {
|
|
class_name = Z_REFVAL_P(class_name);
|
|
goto try_class_name;
|
|
} else {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_function *fbc;
|
|
zval *function_name, *func;
|
|
|
|
if (IS_CV == IS_CONST && Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_STRING) {
|
|
function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
|
|
SAVE_OPLINE();
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
fbc = Z_FUNC_P(func);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, NULL, NULL, EX(call));
|
|
|
|
/*CHECK_EXCEPTION();*/
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_string *lcname;
|
|
zend_free_op free_op2;
|
|
zend_class_entry *called_scope;
|
|
zend_object *object;
|
|
|
|
SAVE_OPLINE();
|
|
function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
try_function_name:
|
|
if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
|
|
if (Z_STRVAL_P(function_name)[0] == '\\') {
|
|
lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
|
|
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
|
|
} else {
|
|
lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
|
|
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
|
|
}
|
|
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
|
|
}
|
|
zend_string_free(lcname);
|
|
|
|
fbc = Z_FUNC_P(func);
|
|
called_scope = NULL;
|
|
object = NULL;
|
|
} else if (IS_CV != IS_CONST &&
|
|
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
|
|
Z_OBJ_HANDLER_P(function_name, get_closure) &&
|
|
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) {
|
|
if (object) {
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (IS_CV == IS_VAR && (fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
|
|
/* Delay closure destruction until its invocation */
|
|
fbc->common.prototype = (zend_function*)Z_OBJ_P(free_op2);
|
|
} else if (IS_CV == IS_CV) {
|
|
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
|
|
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
|
|
zval *obj;
|
|
zval *method;
|
|
|
|
obj = zend_hash_index_find(Z_ARRVAL_P(function_name), 0);
|
|
method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1);
|
|
|
|
if (!obj || !method) {
|
|
zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
|
|
}
|
|
|
|
ZVAL_DEREF(obj);
|
|
if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
|
|
zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
|
|
}
|
|
|
|
ZVAL_DEREF(method);
|
|
if (Z_TYPE_P(method) != IS_STRING) {
|
|
zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
|
|
}
|
|
|
|
if (Z_TYPE_P(obj) == IS_STRING) {
|
|
object = NULL;
|
|
called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0);
|
|
if (UNEXPECTED(called_scope == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (called_scope->get_static_method) {
|
|
fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
|
|
} else {
|
|
fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
|
|
}
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val);
|
|
} else {
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val);
|
|
}
|
|
}
|
|
} else {
|
|
called_scope = Z_OBJCE_P(obj);
|
|
object = Z_OBJ_P(obj);
|
|
|
|
fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method));
|
|
}
|
|
|
|
if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
|
|
object = NULL;
|
|
} else {
|
|
GC_REFCOUNT(object)++; /* For $this pointer */
|
|
}
|
|
}
|
|
|
|
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
|
|
function_name = Z_REFVAL_P(function_name);
|
|
goto try_function_name;
|
|
} else {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
ZEND_VM_CONTINUE(); /* Never reached */
|
|
}
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, object, EX(call));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (EG(exception)) {
|
|
zend_exception_save();
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(NULL, opline->extended_value);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_free_op free_op2;
|
|
zval *class_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
try_class_name:
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(class_name))) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = CACHED_PTR(Z_CACHE_SLOT_P(class_name));
|
|
} else {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class_by_name(Z_STR_P(class_name), EX_CONSTANT(opline->op2) + 1, opline->extended_value);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(class_name), Z_CE_P(EX_VAR(opline->result.var)));
|
|
}
|
|
} else if (Z_TYPE_P(class_name) == IS_OBJECT) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = Z_OBJCE_P(class_name);
|
|
} else if (Z_TYPE_P(class_name) == IS_STRING) {
|
|
Z_CE_P(EX_VAR(opline->result.var)) = zend_fetch_class(Z_STR_P(class_name), opline->extended_value);
|
|
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(class_name) == IS_REFERENCE) {
|
|
class_name = Z_REFVAL_P(class_name);
|
|
goto try_class_name;
|
|
} else {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_function *fbc;
|
|
zval *function_name, *func;
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST && Z_TYPE_P(EX_CONSTANT(opline->op2)) == IS_STRING) {
|
|
function_name = (zval*)(EX_CONSTANT(opline->op2)+1);
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (UNEXPECTED((func = zend_hash_find(EG(function_table), Z_STR_P(function_name))) == NULL)) {
|
|
SAVE_OPLINE();
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
fbc = Z_FUNC_P(func);
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), fbc);
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, NULL, NULL, EX(call));
|
|
|
|
/*CHECK_EXCEPTION();*/
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_string *lcname;
|
|
zend_free_op free_op2;
|
|
zend_class_entry *called_scope;
|
|
zend_object *object;
|
|
|
|
SAVE_OPLINE();
|
|
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
try_function_name:
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
|
|
if (Z_STRVAL_P(function_name)[0] == '\\') {
|
|
lcname = zend_string_alloc(Z_STRLEN_P(function_name) - 1, 0);
|
|
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name) + 1, Z_STRLEN_P(function_name) - 1);
|
|
} else {
|
|
lcname = zend_string_alloc(Z_STRLEN_P(function_name), 0);
|
|
zend_str_tolower_copy(lcname->val, Z_STRVAL_P(function_name), Z_STRLEN_P(function_name));
|
|
}
|
|
if (UNEXPECTED((func = zend_hash_find(EG(function_table), lcname)) == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined function %s()", Z_STRVAL_P(function_name));
|
|
}
|
|
zend_string_free(lcname);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
fbc = Z_FUNC_P(func);
|
|
called_scope = NULL;
|
|
object = NULL;
|
|
} else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
|
|
EXPECTED(Z_TYPE_P(function_name) == IS_OBJECT) &&
|
|
Z_OBJ_HANDLER_P(function_name, get_closure) &&
|
|
Z_OBJ_HANDLER_P(function_name, get_closure)(function_name, &called_scope, &fbc, &object) == SUCCESS) {
|
|
if (object) {
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_VAR && (fbc->common.fn_flags & ZEND_ACC_CLOSURE)) {
|
|
/* Delay closure destruction until its invocation */
|
|
fbc->common.prototype = (zend_function*)Z_OBJ_P(free_op2);
|
|
} else if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) &&
|
|
zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) {
|
|
zval *obj;
|
|
zval *method;
|
|
|
|
obj = zend_hash_index_find(Z_ARRVAL_P(function_name), 0);
|
|
method = zend_hash_index_find(Z_ARRVAL_P(function_name), 1);
|
|
|
|
if (!obj || !method) {
|
|
zend_error_noreturn(E_ERROR, "Array callback has to contain indices 0 and 1");
|
|
}
|
|
|
|
ZVAL_DEREF(obj);
|
|
if (Z_TYPE_P(obj) != IS_STRING && Z_TYPE_P(obj) != IS_OBJECT) {
|
|
zend_error_noreturn(E_ERROR, "First array member is not a valid class name or object");
|
|
}
|
|
|
|
ZVAL_DEREF(method);
|
|
if (Z_TYPE_P(method) != IS_STRING) {
|
|
zend_error_noreturn(E_ERROR, "Second array member is not a valid method");
|
|
}
|
|
|
|
if (Z_TYPE_P(obj) == IS_STRING) {
|
|
object = NULL;
|
|
called_scope = zend_fetch_class_by_name(Z_STR_P(obj), NULL, 0);
|
|
if (UNEXPECTED(called_scope == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (called_scope->get_static_method) {
|
|
fbc = called_scope->get_static_method(called_scope, Z_STR_P(method));
|
|
} else {
|
|
fbc = zend_std_get_static_method(called_scope, Z_STR_P(method), NULL);
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", called_scope->name->val, Z_STRVAL_P(method));
|
|
}
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val);
|
|
} else {
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val);
|
|
}
|
|
}
|
|
} else {
|
|
called_scope = Z_OBJCE_P(obj);
|
|
object = Z_OBJ_P(obj);
|
|
|
|
fbc = Z_OBJ_HT_P(obj)->get_method(&object, Z_STR_P(method), NULL);
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", object->ce->name->val, Z_STRVAL_P(method));
|
|
}
|
|
|
|
if ((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0) {
|
|
object = NULL;
|
|
} else {
|
|
GC_REFCOUNT(object)++; /* For $this pointer */
|
|
}
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(function_name) == IS_REFERENCE) {
|
|
function_name = Z_REFVAL_P(function_name);
|
|
goto try_function_name;
|
|
} else {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
ZEND_VM_CONTINUE(); /* Never reached */
|
|
}
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, object, EX(call));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_not_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *val;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
val = EX_CONSTANT(opline->op1);
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val));
|
|
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *z;
|
|
|
|
SAVE_OPLINE();
|
|
z = EX_CONSTANT(opline->op1);
|
|
|
|
if (Z_TYPE_P(z) == IS_STRING) {
|
|
zend_string *str = Z_STR_P(z);
|
|
|
|
if (str->len != 0) {
|
|
zend_write(str->val, str->len);
|
|
}
|
|
} else {
|
|
zend_string *str = _zval_get_string_func(z);
|
|
|
|
if (str->len != 0) {
|
|
zend_write(str->val, str->len);
|
|
}
|
|
zend_string_release(str);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRINT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
|
return ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = EX_CONSTANT(opline->op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if (IS_CONST == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline++;
|
|
} else {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = EX_CONSTANT(opline->op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if (IS_CONST == IS_CV) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
} else {
|
|
opline++;
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = EX_CONSTANT(opline->op1);
|
|
|
|
if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) {
|
|
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if (IS_CONST == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
|
|
} else {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = EX_CONSTANT(opline->op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
if (IS_CONST == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
opline++;
|
|
} else {
|
|
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = EX_CONSTANT(opline->op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
if (IS_CONST == IS_CV) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
if (i_zend_is_true(val)) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
opline++;
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
retval_ptr = EX_CONSTANT(opline->op1);
|
|
|
|
if (!EX(return_value)) {
|
|
|
|
} else {
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
|
|
zval_copy_ctor_func(EX(return_value));
|
|
}
|
|
}
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(retval_ptr)) {
|
|
ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
}
|
|
}
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
|
|
do {
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR ||
|
|
(IS_CONST == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) {
|
|
/* Not supposed to happen, but we'll allow it */
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
|
|
retval_ptr = EX_CONSTANT(opline->op1);
|
|
if (!EX(return_value)) {
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (IS_CONST != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor_no_imm(EX(return_value));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
retval_ptr = NULL;
|
|
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
|
|
}
|
|
|
|
if (IS_CONST == IS_VAR) {
|
|
if (retval_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) {
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
if (EX(return_value)) {
|
|
ZVAL_NEW_REF(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (EX(return_value)) {
|
|
ZVAL_MAKE_REF(retval_ptr);
|
|
Z_ADDREF_P(retval_ptr);
|
|
ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
}
|
|
} while (0);
|
|
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op1);
|
|
|
|
do {
|
|
if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
|
|
value = Z_REFVAL_P(value);
|
|
if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Can only throw objects");
|
|
}
|
|
} while (0);
|
|
|
|
zend_exception_save();
|
|
if (IS_CONST != IS_TMP_VAR) {
|
|
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
|
|
zend_throw_exception_object(value);
|
|
zend_exception_restore();
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value, *arg;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op1);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
ZVAL_COPY_VALUE(arg, value);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
|
|
zval_copy_ctor_func(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value, *arg;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
|
|
}
|
|
value = EX_CONSTANT(opline->op1);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
ZVAL_COPY_VALUE(arg, value);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
|
|
zval_copy_ctor_func(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *val;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
val = EX_CONSTANT(opline->op1);
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val));
|
|
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval object_zval;
|
|
zend_function *constructor;
|
|
zend_class_entry *ce;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
|
|
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
|
|
} else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
|
|
zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
|
|
}
|
|
}
|
|
object_init_ex(&object_zval, ce);
|
|
constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval));
|
|
|
|
if (constructor == NULL) {
|
|
if (EXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
|
|
} else {
|
|
OBJ_RELEASE(Z_OBJ(object_zval));
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
/* We are not handling overloaded classes right now */
|
|
EX(call) = zend_vm_stack_push_call_frame(
|
|
ZEND_CALL_FUNCTION | ZEND_CALL_CTOR |
|
|
(EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED),
|
|
constructor,
|
|
opline->extended_value,
|
|
ce,
|
|
Z_OBJ(object_zval),
|
|
EX(call));
|
|
|
|
if (EXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
|
|
EX(call)->return_value = EX_VAR(opline->result.var);
|
|
} else {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *obj;
|
|
zend_class_entry *ce;
|
|
zend_function *clone;
|
|
zend_object_clone_obj_t clone_call;
|
|
|
|
SAVE_OPLINE();
|
|
obj = EX_CONSTANT(opline->op1);
|
|
|
|
do {
|
|
if (IS_CONST == IS_CONST ||
|
|
(IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
|
|
obj = Z_REFVAL_P(obj);
|
|
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
|
|
}
|
|
} while (0);
|
|
|
|
ce = Z_OBJCE_P(obj);
|
|
clone = ce ? ce->clone : NULL;
|
|
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
|
if (UNEXPECTED(clone_call == NULL)) {
|
|
if (ce) {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object");
|
|
}
|
|
}
|
|
|
|
if (ce && clone) {
|
|
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
|
/* Ensure that if we're calling a private function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(ce != EG(scope))) {
|
|
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
|
/* Ensure that if we're calling a protected function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
|
|
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
|
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
|
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
|
}
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
expr = EX_CONSTANT(opline->op1);
|
|
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
/* This code is taken from convert_to_null. However, it does not seems very useful,
|
|
* because a conversion to null always results in the same value. This could only
|
|
* be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */
|
|
#if 0
|
|
if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) {
|
|
if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL) == SUCCESS) {
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ZVAL_NULL(result);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(result, zend_is_true(expr));
|
|
break;
|
|
case IS_LONG:
|
|
ZVAL_LONG(result, zval_get_long(expr));
|
|
break;
|
|
case IS_DOUBLE:
|
|
ZVAL_DOUBLE(result, zval_get_double(expr));
|
|
break;
|
|
case IS_STRING:
|
|
ZVAL_STR(result, zval_get_string(expr));
|
|
break;
|
|
default:
|
|
if (IS_CONST & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
/* If value is already of correct type, return it directly */
|
|
if (Z_TYPE_P(expr) == opline->extended_value) {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
|
|
zval_copy_ctor_func(result);
|
|
}
|
|
} else if (IS_CONST != IS_TMP_VAR) {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (opline->extended_value == IS_ARRAY) {
|
|
if (Z_TYPE_P(expr) != IS_OBJECT) {
|
|
ZVAL_NEW_ARR(result);
|
|
zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
Z_ADDREF_P(result);
|
|
convert_to_array(result);
|
|
}
|
|
} else {
|
|
if (Z_TYPE_P(expr) != IS_ARRAY) {
|
|
object_init(result);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
zval_opt_copy_ctor(result);
|
|
convert_to_object(result);
|
|
}
|
|
}
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_op_array *new_op_array=NULL;
|
|
|
|
zval *inc_filename;
|
|
zval tmp_inc_filename;
|
|
zend_bool failure_retval=0;
|
|
|
|
SAVE_OPLINE();
|
|
inc_filename = EX_CONSTANT(opline->op1);
|
|
|
|
ZVAL_UNDEF(&tmp_inc_filename);
|
|
if (Z_TYPE_P(inc_filename) != IS_STRING) {
|
|
ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
|
|
inc_filename = &tmp_inc_filename;
|
|
}
|
|
|
|
if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
|
|
if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
|
|
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
} else {
|
|
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
}
|
|
} else {
|
|
switch (opline->extended_value) {
|
|
case ZEND_INCLUDE_ONCE:
|
|
case ZEND_REQUIRE_ONCE: {
|
|
zend_file_handle file_handle;
|
|
char *resolved_path;
|
|
|
|
resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename));
|
|
if (resolved_path) {
|
|
failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
|
|
} else {
|
|
resolved_path = Z_STRVAL_P(inc_filename);
|
|
}
|
|
|
|
if (failure_retval) {
|
|
/* do nothing, file already included */
|
|
} else if (SUCCESS == zend_stream_open(resolved_path, &file_handle)) {
|
|
|
|
if (!file_handle.opened_path) {
|
|
file_handle.opened_path = estrdup(resolved_path);
|
|
}
|
|
|
|
if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
|
|
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE));
|
|
zend_destroy_file_handle(&file_handle);
|
|
} else {
|
|
zend_file_handle_dtor(&file_handle);
|
|
failure_retval=1;
|
|
}
|
|
} else {
|
|
if (opline->extended_value == ZEND_INCLUDE_ONCE) {
|
|
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
} else {
|
|
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
}
|
|
}
|
|
if (resolved_path != Z_STRVAL_P(inc_filename)) {
|
|
efree(resolved_path);
|
|
}
|
|
}
|
|
break;
|
|
case ZEND_INCLUDE:
|
|
case ZEND_REQUIRE:
|
|
new_op_array = compile_filename(opline->extended_value, inc_filename);
|
|
break;
|
|
case ZEND_EVAL: {
|
|
char *eval_desc = zend_make_compiled_string_description("eval()'d code");
|
|
|
|
new_op_array = zend_compile_string(inc_filename, eval_desc);
|
|
efree(eval_desc);
|
|
}
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp_inc_filename));
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
} else if (EXPECTED(new_op_array != NULL)) {
|
|
zval *return_value = NULL;
|
|
zend_execute_data *call;
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
return_value = EX_VAR(opline->result.var);
|
|
}
|
|
|
|
new_op_array->scope = EG(scope); /* ??? */
|
|
|
|
call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE,
|
|
(zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL);
|
|
|
|
if (EX(symbol_table)) {
|
|
call->symbol_table = EX(symbol_table);
|
|
} else {
|
|
call->symbol_table = zend_rebuild_symbol_table();
|
|
}
|
|
|
|
call->prev_execute_data = execute_data;
|
|
i_init_code_execute_data(call, new_op_array, return_value);
|
|
if (EXPECTED(zend_execute_ex == execute_ex)) {
|
|
ZEND_VM_ENTER();
|
|
} else {
|
|
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
|
zend_execute_ex(call);
|
|
}
|
|
|
|
destroy_op_array(new_op_array);
|
|
efree_size(new_op_array, sizeof(zend_op_array));
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
} else if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *array_ptr, *array_ref, iterator, tmp;
|
|
HashTable *fe_ht;
|
|
zend_object_iterator *iter = NULL;
|
|
zend_class_entry *ce = NULL;
|
|
zend_bool is_empty = 0;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) &&
|
|
(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
array_ptr = array_ref = NULL;
|
|
ZVAL_DEREF(array_ptr);
|
|
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
|
|
SEPARATE_ARRAY(array_ptr);
|
|
if (!Z_ISREF_P(array_ref)) {
|
|
ZVAL_NEW_REF(array_ref, array_ref);
|
|
array_ptr = Z_REFVAL_P(array_ref);
|
|
}
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce->get_iterator == NULL) {
|
|
Z_ADDREF_P(array_ptr);
|
|
}
|
|
array_ref = array_ptr;
|
|
} else {
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
}
|
|
} else {
|
|
array_ptr = array_ref = EX_CONSTANT(opline->op1);
|
|
if (IS_CONST & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(array_ptr);
|
|
}
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&tmp, array_ptr);
|
|
if (Z_OPT_IMMUTABLE_P(&tmp)) {
|
|
zval_copy_ctor_func(&tmp);
|
|
}
|
|
array_ref = array_ptr = &tmp;
|
|
if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce && ce->get_iterator) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (!ce->get_iterator) {
|
|
if (IS_CONST == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_IMMUTABLE_P(array_ref)) {
|
|
if (IS_CONST == IS_CV) {
|
|
zval_copy_ctor_func(array_ref);
|
|
Z_ADDREF_P(array_ref);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&tmp, array_ref);
|
|
zval_copy_ctor_func(&tmp);
|
|
array_ptr = array_ref = &tmp;
|
|
}
|
|
} else if (Z_REFCOUNTED_P(array_ref)) {
|
|
if (IS_CONST == IS_CONST ||
|
|
(IS_CONST == IS_CV &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 1) ||
|
|
(IS_CONST == IS_VAR &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 2)) {
|
|
if (IS_CONST == IS_VAR) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
ZVAL_DUP(&tmp, array_ref);
|
|
array_ptr = array_ref = &tmp;
|
|
} else if (IS_CONST == IS_CV || IS_CONST == IS_VAR) {
|
|
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
|
|
ZVAL_UNREF(array_ref);
|
|
array_ptr = array_ref;
|
|
}
|
|
if (Z_IMMUTABLE_P(array_ptr)) {
|
|
zval_copy_ctor_func(array_ptr);
|
|
} else if (Z_ISREF_P(array_ref) &&
|
|
Z_COPYABLE_P(array_ptr) &&
|
|
Z_REFCOUNT_P(array_ptr) > 1) {
|
|
Z_DELREF_P(array_ptr);
|
|
zval_copy_ctor_func(array_ptr);
|
|
}
|
|
if (IS_CONST == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ce && ce->get_iterator) {
|
|
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF);
|
|
|
|
if (IS_CONST == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
|
|
}
|
|
if (iter && EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(&iterator, &iter->std);
|
|
array_ptr = array_ref = &iterator;
|
|
} else {
|
|
if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
if (!EG(exception)) {
|
|
zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val);
|
|
}
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
|
|
|
|
if (iter) {
|
|
iter->index = 0;
|
|
if (iter->funcs->rewind) {
|
|
iter->funcs->rewind(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
is_empty = iter->funcs->valid(iter) != SUCCESS;
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
iter->index = -1; /* will be set to 0 before using next handler */
|
|
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
|
|
HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
|
|
HashPosition pos = 0;
|
|
Bucket *p;
|
|
|
|
while (1) {
|
|
if (pos >= fe_ht->nNumUsed) {
|
|
is_empty = 1;
|
|
if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
p = fe_ht->arData + pos;
|
|
if (Z_TYPE(p->val) == IS_UNDEF ||
|
|
(Z_TYPE(p->val) == IS_INDIRECT &&
|
|
Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
}
|
|
if (!ce ||
|
|
!p->key ||
|
|
zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
fe_ht->nInternalPointer = pos;
|
|
ptr->pos = pos;
|
|
ptr->ht = fe_ht;
|
|
ptr->h = fe_ht->arData[pos].h;
|
|
ptr->key = fe_ht->arData[pos].key;
|
|
is_empty = 0;
|
|
} else {
|
|
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
|
|
is_empty = 1;
|
|
}
|
|
|
|
if (IS_CONST == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
if (is_empty) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *ptr = EX_CONSTANT(opline->op1);
|
|
|
|
do {
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
} else {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(ptr)) {
|
|
ptr = Z_REFVAL_P(ptr);
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
break;
|
|
}
|
|
}
|
|
zend_print_variable(ptr);
|
|
}
|
|
} while (0);
|
|
|
|
}
|
|
#endif
|
|
zend_bailout();
|
|
ZEND_VM_NEXT_OPCODE(); /* Never reached */
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op1);
|
|
|
|
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
if (i_zend_is_true(value)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_CONST == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_COALESCE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op1);
|
|
|
|
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
|
|
if (Z_TYPE_P(value) > IS_NULL) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_CONST == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op1);
|
|
|
|
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(value)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_CONST == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op1);
|
|
try_strlen:
|
|
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
|
} else {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
|
|
value = Z_REFVAL_P(value);
|
|
goto try_strlen;
|
|
} else if (Z_TYPE_P(value) < IS_TRUE) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
|
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
|
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
|
zend_string *str = zval_get_string(value);
|
|
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
|
zend_string_release(str);
|
|
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
|
zend_string *str;
|
|
zval tmp;
|
|
|
|
ZVAL_COPY(&tmp, value);
|
|
if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) {
|
|
goto strlen_error;
|
|
}
|
|
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
|
zval_dtor(&tmp);
|
|
} else {
|
|
strlen_error:
|
|
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op1);
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
case IS_LONG:
|
|
case IS_DOUBLE:
|
|
case IS_STRING:
|
|
case IS_ARRAY:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE);
|
|
break;
|
|
case IS_OBJECT:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
zend_class_entry *ce = Z_OBJCE_P(value);
|
|
if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1
|
|
&& !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
case IS_RESOURCE:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value));
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL);
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DEFINED_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_constant *c;
|
|
|
|
SAVE_OPLINE();
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op1), 0)) == NULL) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), c);
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = EX_CONSTANT(opline->op1);
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if (IS_CONST != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_CONST == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = NULL;
|
|
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
|
|
try_fetch_list:
|
|
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
|
|
zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), EX_CONSTANT(opline->op2), IS_CONST, BP_VAR_R);
|
|
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
|
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
|
zval *result = EX_VAR(opline->result.var);
|
|
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
|
|
|
|
if (retval) {
|
|
if (result != retval) {
|
|
ZVAL_COPY(result, retval);
|
|
}
|
|
} else {
|
|
ZVAL_NULL(result);
|
|
}
|
|
} else if (Z_TYPE_P(container) == IS_REFERENCE) {
|
|
container = Z_REFVAL_P(container);
|
|
goto try_fetch_list;
|
|
} else {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_CONST == IS_CONST &&
|
|
IS_CONST == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_CONST != IS_CONST &&
|
|
IS_CONST == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if (IS_CONST != IS_UNUSED) {
|
|
|
|
|
|
function_name = EX_CONSTANT(opline->op2);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_CONST == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if (IS_CONST != IS_CONST) {
|
|
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if (IS_CONST == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *function_name = EX_CONSTANT(opline->op2);
|
|
zend_fcall_info_cache fcc;
|
|
char *error = NULL;
|
|
zend_function *func;
|
|
zend_class_entry *called_scope;
|
|
zend_object *object;
|
|
|
|
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
|
|
if (error) {
|
|
efree(error);
|
|
}
|
|
func = fcc.function_handler;
|
|
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
|
|
/* Delay closure destruction until its invocation */
|
|
func->common.prototype = (zend_function*)Z_OBJ_P(function_name);
|
|
Z_ADDREF_P(function_name);
|
|
}
|
|
called_scope = fcc.called_scope;
|
|
object = fcc.object;
|
|
if (object) {
|
|
GC_REFCOUNT(object)++; /* For $this pointer */
|
|
} else if (func->common.scope &&
|
|
!(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically",
|
|
func->common.scope->name->val, func->common.function_name->val);
|
|
} else {
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically",
|
|
func->common.scope->name->val, func->common.function_name->val);
|
|
}
|
|
}
|
|
} else {
|
|
zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
|
|
efree(error);
|
|
func = (zend_function*)&zend_pass_function;
|
|
called_scope = NULL;
|
|
object = NULL;
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
func, opline->extended_value, called_scope, object, EX(call));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_UNUSED) {
|
|
zend_constant *c;
|
|
zval *retval;
|
|
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
|
|
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
|
|
char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
|
|
if (!actual) {
|
|
ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2))));
|
|
} else {
|
|
actual++;
|
|
ZVAL_STRINGL(EX_VAR(opline->result.var),
|
|
actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
|
|
}
|
|
/* non-qualified constant - allow text substitution */
|
|
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
|
Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
} else {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
|
|
}
|
|
retval = EX_VAR(opline->result.var);
|
|
ZVAL_COPY_VALUE(retval, &c->value);
|
|
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
|
|
if (Z_OPT_COPYABLE_P(retval)) {
|
|
zval_copy_ctor_func(retval);
|
|
} else {
|
|
Z_ADDREF_P(retval);
|
|
}
|
|
}
|
|
} else {
|
|
/* class constant */
|
|
zend_class_entry *ce;
|
|
zval *value;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
ZVAL_DEREF(value);
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
goto constant_fetch_end;
|
|
} else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
|
ZVAL_DEREF(value);
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
goto constant_fetch_end;
|
|
}
|
|
}
|
|
|
|
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
|
ZVAL_DEREF(value);
|
|
if (Z_CONSTANT_P(value)) {
|
|
EG(scope) = ce;
|
|
zval_update_constant(value, 1);
|
|
EG(scope) = EX(func)->op_array.scope;
|
|
}
|
|
if (IS_CONST == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
|
|
}
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
} else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
|
|
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
}
|
|
constant_fetch_end:
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = EX_CONSTANT(opline->op1);
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CONST == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *offset = EX_CONSTANT(opline->op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CONST != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CONST != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_CV &&
|
|
IS_CONST == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = EX_CONSTANT(opline->op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_CV &&
|
|
IS_CONST == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval tmp, *varname = EX_CONSTANT(opline->op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CONST & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *name;
|
|
zval *val;
|
|
zend_constant c;
|
|
|
|
SAVE_OPLINE();
|
|
name = EX_CONSTANT(opline->op1);
|
|
val = EX_CONSTANT(opline->op2);
|
|
|
|
ZVAL_COPY_VALUE(&c.value, val);
|
|
if (Z_OPT_CONSTANT(c.value)) {
|
|
zval_update_constant(&c.value, 0);
|
|
} else {
|
|
/* IS_CONST can't be IS_OBJECT, IS_RESOURCE or IS_REFERENCE */
|
|
if (UNEXPECTED(Z_OPT_COPYABLE(c.value))) {
|
|
zval_copy_ctor_func(&c.value);
|
|
}
|
|
}
|
|
c.flags = CONST_CS; /* non persistent, case sensetive */
|
|
c.name = zend_string_dup(Z_STR_P(name), 0);
|
|
c.module_number = PHP_USER_CONSTANT;
|
|
|
|
if (zend_register_constant(&c) == FAILURE) {
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = EX_CONSTANT(opline->op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CONST != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CONST == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = EX_CONSTANT(opline->op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *key = EX_CONSTANT(opline->op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = EX_CONSTANT(opline->op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CONST != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CONST == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = EX_CONSTANT(opline->op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = EX_CONSTANT(opline->op1);
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if (IS_CONST != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_CV &&
|
|
IS_VAR == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = EX_CONSTANT(opline->op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_CV &&
|
|
IS_VAR == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval tmp, *varname = EX_CONSTANT(opline->op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = EX_CONSTANT(opline->op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CONST != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CONST == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = EX_CONSTANT(opline->op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = EX_CONSTANT(opline->op1);
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if (IS_CONST != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_CONST == IS_CONST &&
|
|
IS_UNUSED == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_CONST != IS_CONST &&
|
|
IS_UNUSED == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
|
|
function_name = NULL;
|
|
if (IS_UNUSED != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_UNUSED == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_CONST == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if (IS_UNUSED != IS_CONST) {
|
|
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = EX_CONSTANT(opline->op1);
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CONST == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *offset = NULL;
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_UNUSED != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CONST != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CONST != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_CV &&
|
|
IS_UNUSED == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = EX_CONSTANT(opline->op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CONST == IS_CV &&
|
|
IS_UNUSED == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval tmp, *varname = EX_CONSTANT(opline->op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *zfunc;
|
|
int closure_is_static, closure_is_being_defined_inside_static_context;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (UNEXPECTED((zfunc = zend_hash_find(EG(function_table), Z_STR_P(EX_CONSTANT(opline->op1)))) == NULL) ||
|
|
UNEXPECTED(Z_FUNC_P(zfunc)->type != ZEND_USER_FUNCTION)) {
|
|
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
|
|
}
|
|
|
|
closure_is_static = Z_FUNC_P(zfunc)->common.fn_flags & ZEND_ACC_STATIC;
|
|
closure_is_being_defined_inside_static_context = EX(func)->common.fn_flags & ZEND_ACC_STATIC;
|
|
if (closure_is_static || closure_is_being_defined_inside_static_context) {
|
|
zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EX(called_scope), NULL);
|
|
} else {
|
|
zend_create_closure(EX_VAR(opline->result.var), Z_FUNC_P(zfunc), EG(scope), Z_OBJ(EX(This)) ? &EX(This) : NULL);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = EX_CONSTANT(opline->op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CONST != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CONST == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = EX_CONSTANT(opline->op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *key = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_CV == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = NULL;
|
|
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_CONST == IS_CONST &&
|
|
IS_CV == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_CONST != IS_CONST &&
|
|
IS_CV == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if (IS_CV != IS_UNUSED) {
|
|
|
|
|
|
function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
if (IS_CV != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_CONST == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if (IS_CV != IS_CONST) {
|
|
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if (IS_CV == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zend_fcall_info_cache fcc;
|
|
char *error = NULL;
|
|
zend_function *func;
|
|
zend_class_entry *called_scope;
|
|
zend_object *object;
|
|
|
|
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
|
|
if (error) {
|
|
efree(error);
|
|
}
|
|
func = fcc.function_handler;
|
|
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
|
|
/* Delay closure destruction until its invocation */
|
|
func->common.prototype = (zend_function*)Z_OBJ_P(function_name);
|
|
Z_ADDREF_P(function_name);
|
|
}
|
|
called_scope = fcc.called_scope;
|
|
object = fcc.object;
|
|
if (object) {
|
|
GC_REFCOUNT(object)++; /* For $this pointer */
|
|
} else if (func->common.scope &&
|
|
!(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically",
|
|
func->common.scope->name->val, func->common.function_name->val);
|
|
} else {
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically",
|
|
func->common.scope->name->val, func->common.function_name->val);
|
|
}
|
|
}
|
|
} else {
|
|
zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
|
|
efree(error);
|
|
func = (zend_function*)&zend_pass_function;
|
|
called_scope = NULL;
|
|
object = NULL;
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
func, opline->extended_value, called_scope, object, EX(call));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_class_entry *ce, *catch_ce;
|
|
zend_object *exception;
|
|
|
|
SAVE_OPLINE();
|
|
/* Check whether an exception has been thrown, if not, jump over code */
|
|
zend_exception_restore();
|
|
if (EG(exception) == NULL) {
|
|
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
|
|
ZEND_VM_CONTINUE(); /* CHECK_ME */
|
|
}
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
catch_ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
|
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), catch_ce);
|
|
}
|
|
ce = EG(exception)->ce;
|
|
|
|
#ifdef HAVE_DTRACE
|
|
if (DTRACE_EXCEPTION_CAUGHT_ENABLED()) {
|
|
DTRACE_EXCEPTION_CAUGHT((char *)ce->name);
|
|
}
|
|
#endif /* HAVE_DTRACE */
|
|
|
|
if (ce != catch_ce) {
|
|
if (!instanceof_function(ce, catch_ce)) {
|
|
if (opline->result.num) {
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
|
|
ZEND_VM_CONTINUE(); /* CHECK_ME */
|
|
}
|
|
}
|
|
|
|
exception = EG(exception);
|
|
zval_ptr_dtor(EX_VAR(opline->op2.var));
|
|
ZVAL_OBJ(EX_VAR(opline->op2.var), EG(exception));
|
|
if (UNEXPECTED(EG(exception) != exception)) {
|
|
GC_REFCOUNT(EG(exception))++;
|
|
HANDLE_EXCEPTION();
|
|
} else {
|
|
EG(exception) = NULL;
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = EX_CONSTANT(opline->op1);
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CONST == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CONST != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CONST != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CV & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = EX_CONSTANT(opline->op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CONST != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CONST == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = EX_CONSTANT(opline->op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
} else {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = EX_CONSTANT(opline->op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = NULL;
|
|
|
|
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CONST == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_CONST == IS_CONST &&
|
|
(IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_CONST != IS_CONST &&
|
|
(IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
|
|
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_CONST == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zend_fcall_info_cache fcc;
|
|
char *error = NULL;
|
|
zend_function *func;
|
|
zend_class_entry *called_scope;
|
|
zend_object *object;
|
|
|
|
if (zend_is_callable_ex(function_name, NULL, 0, NULL, &fcc, &error)) {
|
|
if (error) {
|
|
efree(error);
|
|
}
|
|
func = fcc.function_handler;
|
|
if (func->common.fn_flags & ZEND_ACC_CLOSURE) {
|
|
/* Delay closure destruction until its invocation */
|
|
func->common.prototype = (zend_function*)Z_OBJ_P(function_name);
|
|
Z_ADDREF_P(function_name);
|
|
}
|
|
called_scope = fcc.called_scope;
|
|
object = fcc.object;
|
|
if (object) {
|
|
GC_REFCOUNT(object)++; /* For $this pointer */
|
|
} else if (func->common.scope &&
|
|
!(func->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (func->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically",
|
|
func->common.scope->name->val, func->common.function_name->val);
|
|
} else {
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically",
|
|
func->common.scope->name->val, func->common.function_name->val);
|
|
}
|
|
}
|
|
} else {
|
|
zend_error(E_WARNING, "%s() expects parameter 1 to be a valid callback, %s", Z_STRVAL_P(EX_CONSTANT(opline->op1)), error);
|
|
efree(error);
|
|
func = (zend_function*)&zend_pass_function;
|
|
called_scope = NULL;
|
|
object = NULL;
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
func, opline->extended_value, called_scope, object, EX(call));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = EX_CONSTANT(opline->op1);
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CONST == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CONST != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CONST != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = EX_CONSTANT(opline->op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
EX_CONSTANT(opline->op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (!EX(return_value)) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
|
|
zval_copy_ctor_func(EX(return_value));
|
|
}
|
|
}
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(retval_ptr)) {
|
|
ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
}
|
|
}
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
do {
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR ||
|
|
(IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) {
|
|
/* Not supposed to happen, but we'll allow it */
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
|
|
retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
if (!EX(return_value)) {
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor_no_imm(EX(return_value));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
retval_ptr = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
|
|
}
|
|
|
|
if (IS_TMP_VAR == IS_VAR) {
|
|
if (retval_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) {
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
if (EX(return_value)) {
|
|
ZVAL_NEW_REF(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (EX(return_value)) {
|
|
ZVAL_MAKE_REF(retval_ptr);
|
|
Z_ADDREF_P(retval_ptr);
|
|
ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
}
|
|
} while (0);
|
|
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
do {
|
|
if (IS_TMP_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
|
|
if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
|
|
value = Z_REFVAL_P(value);
|
|
if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Can only throw objects");
|
|
}
|
|
} while (0);
|
|
|
|
zend_exception_save();
|
|
if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
|
|
zend_throw_exception_object(value);
|
|
zend_exception_restore();
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value, *arg;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
ZVAL_COPY_VALUE(arg, value);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
|
|
zval_copy_ctor_func(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value, *arg;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.num);
|
|
}
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
ZVAL_COPY_VALUE(arg, value);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) {
|
|
zval_copy_ctor_func(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
expr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
/* This code is taken from convert_to_null. However, it does not seems very useful,
|
|
* because a conversion to null always results in the same value. This could only
|
|
* be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */
|
|
#if 0
|
|
if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) {
|
|
if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL) == SUCCESS) {
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ZVAL_NULL(result);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(result, zend_is_true(expr));
|
|
break;
|
|
case IS_LONG:
|
|
ZVAL_LONG(result, zval_get_long(expr));
|
|
break;
|
|
case IS_DOUBLE:
|
|
ZVAL_DOUBLE(result, zval_get_double(expr));
|
|
break;
|
|
case IS_STRING:
|
|
ZVAL_STR(result, zval_get_string(expr));
|
|
break;
|
|
default:
|
|
if (IS_TMP_VAR & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
/* If value is already of correct type, return it directly */
|
|
if (Z_TYPE_P(expr) == opline->extended_value) {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
|
|
zval_copy_ctor_func(result);
|
|
}
|
|
} else if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (opline->extended_value == IS_ARRAY) {
|
|
if (Z_TYPE_P(expr) != IS_OBJECT) {
|
|
ZVAL_NEW_ARR(result);
|
|
zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
Z_ADDREF_P(result);
|
|
convert_to_array(result);
|
|
}
|
|
} else {
|
|
if (Z_TYPE_P(expr) != IS_ARRAY) {
|
|
object_init(result);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
zval_opt_copy_ctor(result);
|
|
convert_to_object(result);
|
|
}
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *array_ptr, *array_ref, iterator, tmp;
|
|
HashTable *fe_ht;
|
|
zend_object_iterator *iter = NULL;
|
|
zend_class_entry *ce = NULL;
|
|
zend_bool is_empty = 0;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) &&
|
|
(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
array_ptr = array_ref = NULL;
|
|
ZVAL_DEREF(array_ptr);
|
|
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
|
|
SEPARATE_ARRAY(array_ptr);
|
|
if (!Z_ISREF_P(array_ref)) {
|
|
ZVAL_NEW_REF(array_ref, array_ref);
|
|
array_ptr = Z_REFVAL_P(array_ref);
|
|
}
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce->get_iterator == NULL) {
|
|
Z_ADDREF_P(array_ptr);
|
|
}
|
|
array_ref = array_ptr;
|
|
} else {
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
}
|
|
} else {
|
|
array_ptr = array_ref = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_TMP_VAR & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(array_ptr);
|
|
}
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&tmp, array_ptr);
|
|
if (Z_OPT_IMMUTABLE_P(&tmp)) {
|
|
zval_copy_ctor_func(&tmp);
|
|
}
|
|
array_ref = array_ptr = &tmp;
|
|
if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce && ce->get_iterator) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (!ce->get_iterator) {
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_IMMUTABLE_P(array_ref)) {
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
zval_copy_ctor_func(array_ref);
|
|
Z_ADDREF_P(array_ref);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&tmp, array_ref);
|
|
zval_copy_ctor_func(&tmp);
|
|
array_ptr = array_ref = &tmp;
|
|
}
|
|
} else if (Z_REFCOUNTED_P(array_ref)) {
|
|
if (IS_TMP_VAR == IS_CONST ||
|
|
(IS_TMP_VAR == IS_CV &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 1) ||
|
|
(IS_TMP_VAR == IS_VAR &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 2)) {
|
|
if (IS_TMP_VAR == IS_VAR) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
ZVAL_DUP(&tmp, array_ref);
|
|
array_ptr = array_ref = &tmp;
|
|
} else if (IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) {
|
|
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
|
|
ZVAL_UNREF(array_ref);
|
|
array_ptr = array_ref;
|
|
}
|
|
if (Z_IMMUTABLE_P(array_ptr)) {
|
|
zval_copy_ctor_func(array_ptr);
|
|
} else if (Z_ISREF_P(array_ref) &&
|
|
Z_COPYABLE_P(array_ptr) &&
|
|
Z_REFCOUNT_P(array_ptr) > 1) {
|
|
Z_DELREF_P(array_ptr);
|
|
zval_copy_ctor_func(array_ptr);
|
|
}
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ce && ce->get_iterator) {
|
|
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF);
|
|
|
|
if (IS_TMP_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
|
|
}
|
|
if (iter && EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(&iterator, &iter->std);
|
|
array_ptr = array_ref = &iterator;
|
|
} else {
|
|
if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
if (!EG(exception)) {
|
|
zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val);
|
|
}
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
|
|
|
|
if (iter) {
|
|
iter->index = 0;
|
|
if (iter->funcs->rewind) {
|
|
iter->funcs->rewind(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
is_empty = iter->funcs->valid(iter) != SUCCESS;
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
iter->index = -1; /* will be set to 0 before using next handler */
|
|
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
|
|
HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
|
|
HashPosition pos = 0;
|
|
Bucket *p;
|
|
|
|
while (1) {
|
|
if (pos >= fe_ht->nNumUsed) {
|
|
is_empty = 1;
|
|
if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
p = fe_ht->arData + pos;
|
|
if (Z_TYPE(p->val) == IS_UNDEF ||
|
|
(Z_TYPE(p->val) == IS_INDIRECT &&
|
|
Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
}
|
|
if (!ce ||
|
|
!p->key ||
|
|
zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
fe_ht->nInternalPointer = pos;
|
|
ptr->pos = pos;
|
|
ptr->ht = fe_ht;
|
|
ptr->h = fe_ht->arData[pos].h;
|
|
ptr->key = fe_ht->arData[pos].key;
|
|
is_empty = 0;
|
|
} else {
|
|
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
|
|
is_empty = 1;
|
|
}
|
|
|
|
if (IS_TMP_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
if (is_empty) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(opline->op1.var)) != 0) {
|
|
EG(error_reporting) = Z_LVAL_P(EX_VAR(opline->op1.var));
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
if (i_zend_is_true(value)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_TMP_VAR == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_COALESCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
|
|
if (Z_TYPE_P(value) > IS_NULL) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_TMP_VAR == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(value)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
case IS_LONG:
|
|
case IS_DOUBLE:
|
|
case IS_STRING:
|
|
case IS_ARRAY:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE);
|
|
break;
|
|
case IS_OBJECT:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
zend_class_entry *ce = Z_OBJCE_P(value);
|
|
if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1
|
|
&& !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
case IS_RESOURCE:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value));
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL);
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_CONST == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *str = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_char_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
add_char_to_string(str, str, EX_CONSTANT(opline->op2));
|
|
|
|
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
|
/*CHECK_EXCEPTION();*/
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *str = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_string_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
add_string_to_string(str, str, EX_CONSTANT(opline->op2));
|
|
|
|
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
|
/*CHECK_EXCEPTION();*/
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_TMP_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *offset = EX_CONSTANT(opline->op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_TMP_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_TMP_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *key = EX_CONSTANT(opline->op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_TMP_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_TMP_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_TMP_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *offset = NULL;
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_UNUSED != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_TMP_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_TMP_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *key = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_CV == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *str = EX_VAR(opline->result.var);
|
|
zval *var;
|
|
zval var_copy;
|
|
int use_copy = 0;
|
|
|
|
SAVE_OPLINE();
|
|
var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_string_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
if (Z_TYPE_P(var) != IS_STRING) {
|
|
use_copy = zend_make_printable_zval(var, &var_copy);
|
|
|
|
if (use_copy) {
|
|
var = &var_copy;
|
|
}
|
|
}
|
|
add_string_to_string(str, str, var);
|
|
|
|
if (use_copy) {
|
|
zend_string_release(Z_STR_P(var));
|
|
}
|
|
/* original comment, possibly problematic:
|
|
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
|
|
* (Zeev): I don't think it's problematic, we only use variables
|
|
* which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
|
|
* string offsets or overloaded objects
|
|
*/
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_TMP_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_TMP_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_TMP_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_TMP_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
} else {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = NULL;
|
|
|
|
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_TMP_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *str = EX_VAR(opline->result.var);
|
|
zval *var;
|
|
zval var_copy;
|
|
int use_copy = 0;
|
|
|
|
SAVE_OPLINE();
|
|
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_string_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
if (Z_TYPE_P(var) != IS_STRING) {
|
|
use_copy = zend_make_printable_zval(var, &var_copy);
|
|
|
|
if (use_copy) {
|
|
var = &var_copy;
|
|
}
|
|
}
|
|
add_string_to_string(str, str, var);
|
|
|
|
if (use_copy) {
|
|
zend_string_release(Z_STR_P(var));
|
|
}
|
|
/* original comment, possibly problematic:
|
|
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
|
|
* (Zeev): I don't think it's problematic, we only use variables
|
|
* which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
|
|
* string offsets or overloaded objects
|
|
*/
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = NULL;
|
|
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_TMP_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_TMP_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_TMP_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
fast_increment_function(var_ptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
increment_function(var_ptr);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
fast_decrement_function(var_ptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
decrement_function(var_ptr);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
fast_increment_function(var_ptr);
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
zval_opt_copy_ctor(var_ptr);
|
|
|
|
increment_function(var_ptr);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
fast_decrement_function(var_ptr);
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
zval_opt_copy_ctor(var_ptr);
|
|
|
|
decrement_function(var_ptr);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (!EX(return_value)) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
|
|
zval_copy_ctor_func(EX(return_value));
|
|
}
|
|
}
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(retval_ptr)) {
|
|
ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
}
|
|
}
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
do {
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR ||
|
|
(IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) {
|
|
/* Not supposed to happen, but we'll allow it */
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
|
|
retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (!EX(return_value)) {
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (IS_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor_no_imm(EX(return_value));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
retval_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR) {
|
|
if (retval_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) {
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
if (EX(return_value)) {
|
|
ZVAL_NEW_REF(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (EX(return_value)) {
|
|
ZVAL_MAKE_REF(retval_ptr);
|
|
Z_ADDREF_P(retval_ptr);
|
|
ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
do {
|
|
if (IS_VAR == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
|
|
if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
|
|
value = Z_REFVAL_P(value);
|
|
if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Can only throw objects");
|
|
}
|
|
} while (0);
|
|
|
|
zend_exception_save();
|
|
if (IS_VAR != IS_TMP_VAR) {
|
|
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
|
|
zend_throw_exception_object(value);
|
|
zend_exception_restore();
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *varptr, *arg;
|
|
zend_free_op free_op1;
|
|
|
|
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
if (Z_ISREF_P(varptr)) {
|
|
ZVAL_COPY(arg, Z_REFVAL_P(varptr));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *varptr, *arg;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) {
|
|
if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
return ZEND_SEND_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
|
|
(Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) &&
|
|
(Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) {
|
|
|
|
ZVAL_MAKE_REF(varptr);
|
|
if (IS_VAR == IS_CV) {
|
|
Z_ADDREF_P(varptr);
|
|
}
|
|
} else {
|
|
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
|
|
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
|
|
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
zend_error(E_STRICT, "Only variables should be passed by reference");
|
|
}
|
|
}
|
|
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *varptr, *arg;
|
|
|
|
SAVE_OPLINE();
|
|
varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(varptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
|
|
}
|
|
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
|
|
ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (Z_ISREF_P(varptr)) {
|
|
Z_ADDREF_P(varptr);
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
} else if (IS_VAR == IS_VAR &&
|
|
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
|
|
ZVAL_NEW_REF(arg, varptr);
|
|
} else {
|
|
ZVAL_NEW_REF(arg, varptr);
|
|
Z_ADDREF_P(arg);
|
|
ZVAL_REF(varptr, Z_REF_P(arg));
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *varptr, *arg;
|
|
zend_free_op free_op1;
|
|
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
return ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
if (Z_ISREF_P(varptr)) {
|
|
ZVAL_COPY(arg, Z_REFVAL_P(varptr));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *arg, *param, tmp;
|
|
zend_free_op free_op1;
|
|
|
|
arg = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
param = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
// TODO: Scalar values don't have reference counters anymore.
|
|
// They are assumed to be 1, and they may be easily passed by
|
|
// reference now. However, previously scalars with refcount==1
|
|
// might be passed and with refcount>1 might not. We can support
|
|
// only single behavior ???
|
|
#if 0
|
|
if (Z_REFCOUNTED_P(arg) &&
|
|
// This solution breaks the following test (omit warning message) ???
|
|
// Zend/tests/bug61273.phpt
|
|
// ext/reflection/tests/bug42976.phpt
|
|
// ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
|
|
#else
|
|
if (!Z_REFCOUNTED_P(arg) ||
|
|
// This solution breaks the following test (emit warning message) ???
|
|
// ext/pdo_sqlite/tests/pdo_005.phpt
|
|
#endif
|
|
(!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
|
|
|
|
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
|
|
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
|
|
opline->op2.num,
|
|
EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
|
|
EX(call)->func->common.scope ? "::" : "",
|
|
EX(call)->func->common.function_name->val);
|
|
|
|
if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
|
|
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
|
|
}
|
|
if (Z_OBJ(EX(call)->This)) {
|
|
OBJ_RELEASE(Z_OBJ(EX(call)->This));
|
|
}
|
|
EX(call)->func = (zend_function*)&zend_pass_function;
|
|
EX(call)->called_scope = NULL;
|
|
Z_OBJ(EX(call)->This) = NULL;
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (Z_REFCOUNTED_P(arg)) {
|
|
Z_DELREF_P(arg);
|
|
}
|
|
ZVAL_DUP(&tmp, arg);
|
|
ZVAL_NEW_REF(arg, &tmp);
|
|
Z_ADDREF_P(arg);
|
|
} else if (!Z_ISREF_P(arg)) {
|
|
ZVAL_NEW_REF(arg, arg);
|
|
Z_ADDREF_P(arg);
|
|
} else if (Z_REFCOUNTED_P(arg)) {
|
|
Z_ADDREF_P(arg);
|
|
}
|
|
ZVAL_COPY_VALUE(param, arg);
|
|
} else if (Z_ISREF_P(arg) &&
|
|
/* don't separate references for __call */
|
|
(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
|
|
ZVAL_DUP(param, Z_REFVAL_P(arg));
|
|
} else {
|
|
ZVAL_COPY(param, arg);
|
|
}
|
|
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval object_zval;
|
|
zend_function *constructor;
|
|
zend_class_entry *ce;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
if (UNEXPECTED((ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) != 0)) {
|
|
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot instantiate interface %s", ce->name->val);
|
|
} else if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
|
|
zend_error_noreturn(E_ERROR, "Cannot instantiate trait %s", ce->name->val);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Cannot instantiate abstract class %s", ce->name->val);
|
|
}
|
|
}
|
|
object_init_ex(&object_zval, ce);
|
|
constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval));
|
|
|
|
if (constructor == NULL) {
|
|
if (EXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval);
|
|
} else {
|
|
OBJ_RELEASE(Z_OBJ(object_zval));
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
/* We are not handling overloaded classes right now */
|
|
EX(call) = zend_vm_stack_push_call_frame(
|
|
ZEND_CALL_FUNCTION | ZEND_CALL_CTOR |
|
|
(EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED),
|
|
constructor,
|
|
opline->extended_value,
|
|
ce,
|
|
Z_OBJ(object_zval),
|
|
EX(call));
|
|
|
|
if (EXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
|
|
EX(call)->return_value = EX_VAR(opline->result.var);
|
|
} else {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
/* This code is taken from convert_to_null. However, it does not seems very useful,
|
|
* because a conversion to null always results in the same value. This could only
|
|
* be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */
|
|
#if 0
|
|
if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) {
|
|
if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL) == SUCCESS) {
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ZVAL_NULL(result);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(result, zend_is_true(expr));
|
|
break;
|
|
case IS_LONG:
|
|
ZVAL_LONG(result, zval_get_long(expr));
|
|
break;
|
|
case IS_DOUBLE:
|
|
ZVAL_DOUBLE(result, zval_get_double(expr));
|
|
break;
|
|
case IS_STRING:
|
|
ZVAL_STR(result, zval_get_string(expr));
|
|
break;
|
|
default:
|
|
if (IS_VAR & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
/* If value is already of correct type, return it directly */
|
|
if (Z_TYPE_P(expr) == opline->extended_value) {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
if (IS_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
|
|
zval_copy_ctor_func(result);
|
|
}
|
|
} else if (IS_VAR != IS_TMP_VAR) {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (opline->extended_value == IS_ARRAY) {
|
|
if (Z_TYPE_P(expr) != IS_OBJECT) {
|
|
ZVAL_NEW_ARR(result);
|
|
zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
|
if (IS_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
Z_ADDREF_P(result);
|
|
convert_to_array(result);
|
|
}
|
|
} else {
|
|
if (Z_TYPE_P(expr) != IS_ARRAY) {
|
|
object_init(result);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
|
|
if (IS_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
zval_opt_copy_ctor(result);
|
|
convert_to_object(result);
|
|
}
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *array_ptr, *array_ref, iterator, tmp;
|
|
HashTable *fe_ht;
|
|
zend_object_iterator *iter = NULL;
|
|
zend_class_entry *ce = NULL;
|
|
zend_bool is_empty = 0;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) &&
|
|
(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
array_ptr = array_ref = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_DEREF(array_ptr);
|
|
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
|
|
SEPARATE_ARRAY(array_ptr);
|
|
if (!Z_ISREF_P(array_ref)) {
|
|
ZVAL_NEW_REF(array_ref, array_ref);
|
|
array_ptr = Z_REFVAL_P(array_ref);
|
|
}
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce->get_iterator == NULL) {
|
|
Z_ADDREF_P(array_ptr);
|
|
}
|
|
array_ref = array_ptr;
|
|
} else {
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
}
|
|
} else {
|
|
array_ptr = array_ref = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(array_ptr);
|
|
}
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&tmp, array_ptr);
|
|
if (Z_OPT_IMMUTABLE_P(&tmp)) {
|
|
zval_copy_ctor_func(&tmp);
|
|
}
|
|
array_ref = array_ptr = &tmp;
|
|
if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce && ce->get_iterator) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (!ce->get_iterator) {
|
|
if (IS_VAR == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_IMMUTABLE_P(array_ref)) {
|
|
if (IS_VAR == IS_CV) {
|
|
zval_copy_ctor_func(array_ref);
|
|
Z_ADDREF_P(array_ref);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&tmp, array_ref);
|
|
zval_copy_ctor_func(&tmp);
|
|
array_ptr = array_ref = &tmp;
|
|
}
|
|
} else if (Z_REFCOUNTED_P(array_ref)) {
|
|
if (IS_VAR == IS_CONST ||
|
|
(IS_VAR == IS_CV &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 1) ||
|
|
(IS_VAR == IS_VAR &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 2)) {
|
|
if (IS_VAR == IS_VAR) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
ZVAL_DUP(&tmp, array_ref);
|
|
array_ptr = array_ref = &tmp;
|
|
} else if (IS_VAR == IS_CV || IS_VAR == IS_VAR) {
|
|
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
|
|
ZVAL_UNREF(array_ref);
|
|
array_ptr = array_ref;
|
|
}
|
|
if (Z_IMMUTABLE_P(array_ptr)) {
|
|
zval_copy_ctor_func(array_ptr);
|
|
} else if (Z_ISREF_P(array_ref) &&
|
|
Z_COPYABLE_P(array_ptr) &&
|
|
Z_REFCOUNT_P(array_ptr) > 1) {
|
|
Z_DELREF_P(array_ptr);
|
|
zval_copy_ctor_func(array_ptr);
|
|
}
|
|
if (IS_VAR == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ce && ce->get_iterator) {
|
|
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF);
|
|
|
|
if (IS_VAR == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
if (iter && EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(&iterator, &iter->std);
|
|
array_ptr = array_ref = &iterator;
|
|
} else {
|
|
if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
if (!EG(exception)) {
|
|
zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val);
|
|
}
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
|
|
|
|
if (iter) {
|
|
iter->index = 0;
|
|
if (iter->funcs->rewind) {
|
|
iter->funcs->rewind(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
is_empty = iter->funcs->valid(iter) != SUCCESS;
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
iter->index = -1; /* will be set to 0 before using next handler */
|
|
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
|
|
HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
|
|
HashPosition pos = 0;
|
|
Bucket *p;
|
|
|
|
while (1) {
|
|
if (pos >= fe_ht->nNumUsed) {
|
|
is_empty = 1;
|
|
if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
p = fe_ht->arData + pos;
|
|
if (Z_TYPE(p->val) == IS_UNDEF ||
|
|
(Z_TYPE(p->val) == IS_INDIRECT &&
|
|
Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
}
|
|
if (!ce ||
|
|
!p->key ||
|
|
zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
fe_ht->nInternalPointer = pos;
|
|
ptr->pos = pos;
|
|
ptr->ht = fe_ht;
|
|
ptr->h = fe_ht->arData[pos].h;
|
|
ptr->key = fe_ht->arData[pos].key;
|
|
is_empty = 0;
|
|
} else {
|
|
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
|
|
is_empty = 1;
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
if (is_empty) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *array, *array_ref;
|
|
zval *value;
|
|
HashTable *fe_ht;
|
|
HashPointer *ptr;
|
|
HashPosition pos;
|
|
Bucket *p;
|
|
|
|
array = array_ref = EX_VAR(opline->op1.var);
|
|
if (Z_ISREF_P(array)) {
|
|
array = Z_REFVAL_P(array);
|
|
// TODO: referenced value might be changed to different array ???
|
|
if (Z_IMMUTABLE_P(array)) {
|
|
zval_copy_ctor_func(array);
|
|
}
|
|
}
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
|
|
fe_ht = Z_ARRVAL_P(array);
|
|
ptr = (HashPointer*)EX_VAR((opline+1)->op1.var);
|
|
pos = ptr->pos;
|
|
if (UNEXPECTED(pos == INVALID_IDX)) {
|
|
/* reached end of iteration */
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else if (UNEXPECTED(ptr->ht != fe_ht)) {
|
|
ptr->ht = fe_ht;
|
|
pos = 0;
|
|
} else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) {
|
|
if (fe_ht->u.flags & HASH_FLAG_PACKED) {
|
|
pos = ptr->h;
|
|
} else {
|
|
pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask];
|
|
while (1) {
|
|
if (pos == INVALID_IDX) {
|
|
pos = fe_ht->nInternalPointer;
|
|
break;
|
|
} else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) {
|
|
break;
|
|
}
|
|
pos = Z_NEXT(fe_ht->arData[pos].val);
|
|
}
|
|
}
|
|
}
|
|
while (1) {
|
|
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
|
|
/* reached end of iteration */
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
p = fe_ht->arData + pos;
|
|
value = &p->val;
|
|
if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
} else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
|
|
value = Z_INDIRECT_P(value);
|
|
if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
}
|
|
}
|
|
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
ZVAL_MAKE_REF(value);
|
|
Z_ADDREF_P(value);
|
|
ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
|
|
} else {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
|
|
if (!p->key) {
|
|
ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h);
|
|
} else {
|
|
ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
do {
|
|
pos++;
|
|
if (pos >= fe_ht->nNumUsed) {
|
|
fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
p = fe_ht->arData + pos;
|
|
} while (Z_TYPE(p->val) == IS_UNDEF ||
|
|
(Z_TYPE(p->val) == IS_INDIRECT &&
|
|
Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF));
|
|
fe_ht->nInternalPointer = ptr->pos = pos;
|
|
ptr->h = fe_ht->arData[pos].h;
|
|
ptr->key = fe_ht->arData[pos].key;
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else if (EXPECTED(Z_TYPE_P(array) == IS_OBJECT)) {
|
|
zend_object_iterator *iter;
|
|
|
|
if ((iter = zend_iterator_unwrap(array)) == NULL) {
|
|
/* plain object */
|
|
zend_object *zobj = Z_OBJ_P(array);
|
|
|
|
fe_ht = Z_OBJPROP_P(array);
|
|
ptr = (HashPointer*)EX_VAR((opline+1)->op1.var);
|
|
pos = ptr->pos;
|
|
if (pos == INVALID_IDX) {
|
|
/* reached end of iteration */
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else if (UNEXPECTED(ptr->ht != fe_ht)) {
|
|
ptr->ht = fe_ht;
|
|
pos = 0;
|
|
} else if (UNEXPECTED(fe_ht->nInternalPointer != ptr->pos)) {
|
|
if (fe_ht->u.flags & HASH_FLAG_PACKED) {
|
|
pos = ptr->h;
|
|
} else {
|
|
pos = fe_ht->arHash[ptr->h & fe_ht->nTableMask];
|
|
while (1) {
|
|
if (pos == INVALID_IDX) {
|
|
pos = fe_ht->nInternalPointer;
|
|
break;
|
|
} else if (fe_ht->arData[pos].h == ptr->h && fe_ht->arData[pos].key == ptr->key) {
|
|
break;
|
|
}
|
|
pos = Z_NEXT(fe_ht->arData[pos].val);
|
|
}
|
|
}
|
|
}
|
|
while (1) {
|
|
if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
|
|
/* reached end of iteration */
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
p = fe_ht->arData + pos;
|
|
value = &p->val;
|
|
if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
} else if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
|
|
value = Z_INDIRECT_P(value);
|
|
if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(!p->key)) {
|
|
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
|
|
ZVAL_LONG(EX_VAR((opline+1)->result.var), p->h);
|
|
}
|
|
break;
|
|
} else if (zend_check_property_access(zobj, p->key) == SUCCESS) {
|
|
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
|
|
if (p->key->val[0]) {
|
|
ZVAL_STR_COPY(EX_VAR((opline+1)->result.var), p->key);
|
|
} else {
|
|
const char *class_name, *prop_name;
|
|
size_t prop_name_len;
|
|
zend_unmangle_property_name_ex(
|
|
p->key, &class_name, &prop_name, &prop_name_len);
|
|
ZVAL_STRINGL(EX_VAR((opline+1)->result.var), prop_name, prop_name_len);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
ZVAL_MAKE_REF(value);
|
|
Z_ADDREF_P(value);
|
|
ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
|
|
} else {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
do {
|
|
pos++;
|
|
if (pos >= fe_ht->nNumUsed) {
|
|
fe_ht->nInternalPointer = ptr->pos = INVALID_IDX;
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
p = fe_ht->arData + pos;
|
|
} while (Z_TYPE(p->val) == IS_UNDEF ||
|
|
(Z_TYPE(p->val) == IS_INDIRECT &&
|
|
Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF) ||
|
|
(EXPECTED(p->key != NULL) &&
|
|
zend_check_property_access(zobj, p->key) == FAILURE));
|
|
fe_ht->nInternalPointer = ptr->pos = pos;
|
|
ptr->h = fe_ht->arData[pos].h;
|
|
ptr->key = fe_ht->arData[pos].key;
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
/* !iter happens from exception */
|
|
if (iter && ++iter->index > 0) {
|
|
/* This could cause an endless loop if index becomes zero again.
|
|
* In case that ever happens we need an additional flag. */
|
|
iter->funcs->move_forward(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
/* If index is zero we come from FE_RESET and checked valid() already. */
|
|
if (!iter || (iter->index > 0 && iter->funcs->valid(iter) == FAILURE)) {
|
|
/* reached end of iteration */
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
value = iter->funcs->get_current_data(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (!value) {
|
|
/* failure in get_current_data */
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
if (opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
ZVAL_MAKE_REF(value);
|
|
Z_ADDREF_P(value);
|
|
ZVAL_REF(EX_VAR(opline->result.var), Z_REF_P(value));
|
|
} else {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
if (opline->extended_value & ZEND_FE_FETCH_WITH_KEY) {
|
|
if (iter->funcs->get_current_key) {
|
|
iter->funcs->get_current_key(iter, EX_VAR((opline+1)->result.var));
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
} else {
|
|
ZVAL_LONG(EX_VAR((opline+1)->result.var), iter->index);
|
|
}
|
|
}
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
} else {
|
|
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
if (i_zend_is_true(value)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_VAR == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_COALESCE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
|
|
if (Z_TYPE_P(value) > IS_NULL) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_VAR == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(value)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_VAR == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
case IS_LONG:
|
|
case IS_DOUBLE:
|
|
case IS_STRING:
|
|
case IS_ARRAY:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE);
|
|
break;
|
|
case IS_OBJECT:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
zend_class_entry *ce = Z_OBJCE_P(value);
|
|
if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1
|
|
&& !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
case IS_RESOURCE:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value));
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL);
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op_data1;
|
|
zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zval *property = EX_CONSTANT(opline->op2);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = EX_CONSTANT(opline->op2);
|
|
|
|
do {
|
|
if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_VAR != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *var_ptr;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op2);
|
|
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = EX_CONSTANT(opline->op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_VAR_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_VAR_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = EX_CONSTANT(opline->op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_VAR_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_VAR_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
if (IS_CONST == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property_name = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object_ptr;
|
|
zend_free_op free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = EX_CONSTANT(opline->op2);
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
|
|
zval *property_name = EX_CONSTANT(opline->op2);
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = EX_CONSTANT(opline->op2);
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op2);
|
|
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_CONST);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_VAR == IS_CONST &&
|
|
IS_CONST == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_VAR != IS_CONST &&
|
|
IS_CONST == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if (IS_CONST != IS_UNUSED) {
|
|
|
|
|
|
function_name = EX_CONSTANT(opline->op2);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_VAR == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if (IS_CONST != IS_CONST) {
|
|
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_VAR != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if (IS_CONST == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_VAR == IS_UNUSED) {
|
|
zend_constant *c;
|
|
zval *retval;
|
|
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
|
|
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
|
|
char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
|
|
if (!actual) {
|
|
ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2))));
|
|
} else {
|
|
actual++;
|
|
ZVAL_STRINGL(EX_VAR(opline->result.var),
|
|
actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
|
|
}
|
|
/* non-qualified constant - allow text substitution */
|
|
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
|
Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
} else {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
|
|
}
|
|
retval = EX_VAR(opline->result.var);
|
|
ZVAL_COPY_VALUE(retval, &c->value);
|
|
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
|
|
if (Z_OPT_COPYABLE_P(retval)) {
|
|
zval_copy_ctor_func(retval);
|
|
} else {
|
|
Z_ADDREF_P(retval);
|
|
}
|
|
}
|
|
} else {
|
|
/* class constant */
|
|
zend_class_entry *ce;
|
|
zval *value;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
ZVAL_DEREF(value);
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
goto constant_fetch_end;
|
|
} else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
|
ZVAL_DEREF(value);
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
goto constant_fetch_end;
|
|
}
|
|
}
|
|
|
|
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
|
ZVAL_DEREF(value);
|
|
if (Z_CONSTANT_P(value)) {
|
|
EG(scope) = ce;
|
|
zval_update_constant(value, 1);
|
|
EG(scope) = EX(func)->op_array.scope;
|
|
}
|
|
if (IS_VAR == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
|
|
}
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
} else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
|
|
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
}
|
|
constant_fetch_end:
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *offset = EX_CONSTANT(opline->op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
unset_dim_again:
|
|
if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
|
|
} else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if (IS_CONST == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
|
|
} else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *key = EX_CONSTANT(opline->op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
|
|
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
|
|
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_VAR);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *variable_ptr;
|
|
zval *value_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
if (!(free_op2 != NULL)) {
|
|
PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
|
}
|
|
zend_error(E_STRICT, "Only variables should be assigned by reference");
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
return ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!(free_op2 != NULL)) {
|
|
PZVAL_LOCK(value_ptr);
|
|
}
|
|
}
|
|
|
|
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_VAR == IS_VAR &&
|
|
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) &&
|
|
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
|
|
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
|
|
}
|
|
if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
|
|
(IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) {
|
|
variable_ptr = &EG(uninitialized_zval);
|
|
} else {
|
|
zend_assign_to_variable_reference(variable_ptr, value_ptr);
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!(free_op2 != NULL)) {
|
|
Z_DELREF_P(variable_ptr);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = NULL;
|
|
|
|
do {
|
|
if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_VAR != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object_ptr;
|
|
zend_free_op free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = NULL;
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
|
|
zval *property_name = NULL;
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = NULL;
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_VAR == IS_CONST &&
|
|
IS_UNUSED == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_VAR != IS_CONST &&
|
|
IS_UNUSED == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
|
|
function_name = NULL;
|
|
if (IS_UNUSED != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_UNUSED == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_VAR == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if (IS_UNUSED != IS_CONST) {
|
|
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_VAR != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *offset = NULL;
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_UNUSED != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = EX_VAR(opline->op1.var);
|
|
if (Z_TYPE_P(var_ptr) != IS_OBJECT &&
|
|
!Z_ISREF_P(var_ptr) &&
|
|
Z_REFCOUNTED_P(var_ptr) &&
|
|
Z_REFCOUNT_P(var_ptr) > 1) {
|
|
|
|
Z_DELREF_P(var_ptr);
|
|
ZVAL_DUP(EX_VAR(opline->op1.var), var_ptr);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *key = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op_data1;
|
|
zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
do {
|
|
if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_VAR != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *var_ptr;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_VAR_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_VAR_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_VAR_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_VAR_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
if (IS_CV == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object_ptr;
|
|
zend_free_op free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
|
|
zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
|
|
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_CV);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *variable_ptr;
|
|
zval *value_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_CV == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
if (!0) {
|
|
PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
|
}
|
|
zend_error(E_STRICT, "Only variables should be assigned by reference");
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
return ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!0) {
|
|
PZVAL_LOCK(value_ptr);
|
|
}
|
|
}
|
|
|
|
variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_VAR == IS_VAR &&
|
|
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) &&
|
|
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
|
|
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
|
|
}
|
|
if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
|
|
(IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) {
|
|
variable_ptr = &EG(uninitialized_zval);
|
|
} else {
|
|
zend_assign_to_variable_reference(variable_ptr, value_ptr);
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!0) {
|
|
Z_DELREF_P(variable_ptr);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
|
|
}
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_VAR == IS_CONST &&
|
|
IS_CV == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_VAR != IS_CONST &&
|
|
IS_CV == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if (IS_CV != IS_UNUSED) {
|
|
|
|
|
|
function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
if (IS_CV != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_VAR == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if (IS_CV != IS_CONST) {
|
|
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_VAR != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if (IS_CV == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
unset_dim_again:
|
|
if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
|
|
} else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if (IS_CV == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
|
|
} else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_VAR != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_binary_assign_op_helper_SPEC_VAR_CV(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2, free_op_data1;
|
|
zval *object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2, free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
do {
|
|
if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_VAR != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR));
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
FREE_OP(free_op_data1);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *var_ptr;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_VAR != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_VAR_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_VAR_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_VAR == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *object_ptr;
|
|
zend_free_op free_op2, free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
zend_free_op free_op2;
|
|
zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_class_entry *ce;
|
|
zend_object *object;
|
|
zend_function *fbc;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
/* no function found. try a static method in class */
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
}
|
|
|
|
if (IS_VAR == IS_CONST &&
|
|
(IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if (IS_VAR != IS_CONST &&
|
|
(IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
(fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
|
|
/* do nothing */
|
|
} else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
|
|
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Function name must be a string");
|
|
}
|
|
}
|
|
|
|
if (ce->get_static_method) {
|
|
fbc = ce->get_static_method(ce, Z_STR_P(function_name));
|
|
} else {
|
|
fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
}
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0)) {
|
|
if (IS_VAR == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
|
|
}
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
} else {
|
|
if (UNEXPECTED(ce->constructor == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call constructor");
|
|
}
|
|
if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot call private %s::__construct()", ce->name->val);
|
|
}
|
|
fbc = ce->constructor;
|
|
}
|
|
|
|
object = NULL;
|
|
if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
|
|
if (Z_OBJ(EX(This))) {
|
|
object = Z_OBJ(EX(This));
|
|
GC_REFCOUNT(object)++;
|
|
}
|
|
if (!object ||
|
|
!instanceof_function(object->ce, ce)) {
|
|
/* We are calling method of the other (incompatible) class,
|
|
but passing $this. This is done for compatibility with php-4. */
|
|
if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
|
|
zend_error(
|
|
object ? E_DEPRECATED : E_STRICT,
|
|
"Non-static method %s::%s() should not be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
} else {
|
|
/* An internal function assumes $this is present and won't check that. So PHP would crash by allowing the call. */
|
|
zend_error_noreturn(
|
|
E_ERROR,
|
|
"Non-static method %s::%s() cannot be called statically%s",
|
|
fbc->common.scope->name->val, fbc->common.function_name->val,
|
|
object ? ", assuming $this from incompatible context" : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (IS_VAR != IS_CONST) {
|
|
/* previous opcode is ZEND_FETCH_CLASS */
|
|
if ((opline-1)->extended_value == ZEND_FETCH_CLASS_PARENT || (opline-1)->extended_value == ZEND_FETCH_CLASS_SELF) {
|
|
ce = EX(called_scope);
|
|
}
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, ce, object, EX(call));
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
|
|
EX(call)->return_value = NULL;
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_VAR == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_VAR != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_VAR == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_VAR != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
unset_dim_again:
|
|
if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
do {
|
|
if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_binary_assign_op_helper_SPEC_VAR_TMPVAR(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *obj;
|
|
zend_class_entry *ce;
|
|
zend_function *clone;
|
|
zend_object_clone_obj_t clone_call;
|
|
|
|
SAVE_OPLINE();
|
|
obj = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
do {
|
|
if (IS_UNUSED == IS_CONST ||
|
|
(IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
|
|
obj = Z_REFVAL_P(obj);
|
|
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
|
|
}
|
|
} while (0);
|
|
|
|
ce = Z_OBJCE_P(obj);
|
|
clone = ce ? ce->clone : NULL;
|
|
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
|
if (UNEXPECTED(clone_call == NULL)) {
|
|
if (ce) {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object");
|
|
}
|
|
}
|
|
|
|
if (ce && clone) {
|
|
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
|
/* Ensure that if we're calling a private function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(ce != EG(scope))) {
|
|
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
|
/* Ensure that if we're calling a protected function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
|
|
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
|
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
|
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
|
}
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXIT_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *ptr = NULL;
|
|
|
|
do {
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
} else {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(ptr)) {
|
|
ptr = Z_REFVAL_P(ptr);
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
break;
|
|
}
|
|
}
|
|
zend_print_variable(ptr);
|
|
}
|
|
} while (0);
|
|
|
|
}
|
|
#endif
|
|
zend_bailout();
|
|
ZEND_VM_NEXT_OPCODE(); /* Never reached */
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *object = _get_obj_zval_ptr_unused(execute_data);
|
|
zval *property = EX_CONSTANT(opline->op2);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = EX_CONSTANT(opline->op2);
|
|
|
|
do {
|
|
if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property = EX_CONSTANT(opline->op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property = EX_CONSTANT(opline->op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
property = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property_name = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *str = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_char_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
add_char_to_string(str, str, EX_CONSTANT(opline->op2));
|
|
|
|
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
|
/*CHECK_EXCEPTION();*/
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *str = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_string_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
add_string_to_string(str, str, EX_CONSTANT(opline->op2));
|
|
|
|
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
|
|
/*CHECK_EXCEPTION();*/
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CONST != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if (IS_CONST != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
zend_constant *c;
|
|
zval *retval;
|
|
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
|
|
if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
|
|
char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
|
|
if (!actual) {
|
|
ZVAL_STR(EX_VAR(opline->result.var), zend_string_copy(Z_STR_P(EX_CONSTANT(opline->op2))));
|
|
} else {
|
|
actual++;
|
|
ZVAL_STRINGL(EX_VAR(opline->result.var),
|
|
actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
|
|
}
|
|
/* non-qualified constant - allow text substitution */
|
|
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
|
|
Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
} else {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
|
|
}
|
|
retval = EX_VAR(opline->result.var);
|
|
ZVAL_COPY_VALUE(retval, &c->value);
|
|
if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
|
|
if (Z_OPT_COPYABLE_P(retval)) {
|
|
zval_copy_ctor_func(retval);
|
|
} else {
|
|
Z_ADDREF_P(retval);
|
|
}
|
|
}
|
|
} else {
|
|
/* class constant */
|
|
zend_class_entry *ce;
|
|
zval *value;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
ZVAL_DEREF(value);
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
goto constant_fetch_end;
|
|
} else if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op1.var));
|
|
if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
|
|
ZVAL_DEREF(value);
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
goto constant_fetch_end;
|
|
}
|
|
}
|
|
|
|
if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
|
|
ZVAL_DEREF(value);
|
|
if (Z_CONSTANT_P(value)) {
|
|
EG(scope) = ce;
|
|
zval_update_constant(value, 1);
|
|
EG(scope) = EX(func)->op_array.scope;
|
|
}
|
|
if (IS_UNUSED == IS_CONST) {
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
|
|
} else {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
|
|
}
|
|
ZVAL_DUP(EX_VAR(opline->result.var), value);
|
|
} else if (Z_STRLEN_P(EX_CONSTANT(opline->op2)) == sizeof("class")-1 && memcmp(Z_STRVAL_P(EX_CONSTANT(opline->op2)), "class", sizeof("class") - 1) == 0) {
|
|
/* "class" is assigned as a case-sensitive keyword from zend_do_resolve_class_name */
|
|
ZVAL_STR_COPY(EX_VAR(opline->result.var), ce->name);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
}
|
|
constant_fetch_end:
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_UNUSED != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
unset_dim_again:
|
|
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
|
|
} else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if (IS_CONST == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
|
|
} else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CONST & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = NULL;
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_UNUSED != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_UNUSED == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *key = EX_CONSTANT(opline->op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = NULL;
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_UNUSED != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_UNUSED == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = NULL;
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_UNUSED != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_UNUSED == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = NULL;
|
|
|
|
do {
|
|
if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_UNUSED != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = NULL;
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_UNUSED != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_UNUSED == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *key = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *object = _get_obj_zval_ptr_unused(execute_data);
|
|
zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
do {
|
|
if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_UNUSED_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_UNUSED_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_UNUSED_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_UNUSED_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *str = EX_VAR(opline->result.var);
|
|
zval *var;
|
|
zval var_copy;
|
|
int use_copy = 0;
|
|
|
|
SAVE_OPLINE();
|
|
var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_string_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
if (Z_TYPE_P(var) != IS_STRING) {
|
|
use_copy = zend_make_printable_zval(var, &var_copy);
|
|
|
|
if (use_copy) {
|
|
var = &var_copy;
|
|
}
|
|
}
|
|
add_string_to_string(str, str, var);
|
|
|
|
if (use_copy) {
|
|
zend_string_release(Z_STR_P(var));
|
|
}
|
|
/* original comment, possibly problematic:
|
|
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
|
|
* (Zeev): I don't think it's problematic, we only use variables
|
|
* which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
|
|
* string offsets or overloaded objects
|
|
*/
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if (IS_CV != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_UNUSED != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
unset_dim_again:
|
|
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
|
|
} else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if (IS_CV == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
|
|
} else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CV & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = NULL;
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_UNUSED != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = NULL;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_UNUSED == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2, free_op_data1;
|
|
zval *object = _get_obj_zval_ptr_unused(execute_data);
|
|
zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2, free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
do {
|
|
if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR));
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_UNUSED_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_UNUSED_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_UNUSED_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_UNUSED == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *str = EX_VAR(opline->result.var);
|
|
zval *var;
|
|
zval var_copy;
|
|
int use_copy = 0;
|
|
|
|
SAVE_OPLINE();
|
|
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
/* Initialize for erealloc in add_string_to_string */
|
|
ZVAL_EMPTY_STRING(str);
|
|
}
|
|
|
|
if (Z_TYPE_P(var) != IS_STRING) {
|
|
use_copy = zend_make_printable_zval(var, &var_copy);
|
|
|
|
if (use_copy) {
|
|
var = &var_copy;
|
|
}
|
|
}
|
|
add_string_to_string(str, str, var);
|
|
|
|
if (use_copy) {
|
|
zend_string_release(Z_STR_P(var));
|
|
}
|
|
/* original comment, possibly problematic:
|
|
* FREE_OP is missing intentionally here - we're always working on the same temporary variable
|
|
* (Zeev): I don't think it's problematic, we only use variables
|
|
* which aren't affected by FREE_OP(Ts, )'s anyway, unless they're
|
|
* string offsets or overloaded objects
|
|
*/
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_obj_zval_ptr_unused(execute_data);
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_UNUSED != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
unset_dim_again:
|
|
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
do {
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_obj_zval_ptr_unused(execute_data);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_not_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *val;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val));
|
|
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
fast_increment_function(var_ptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
increment_function(var_ptr);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
fast_decrement_function(var_ptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
decrement_function(var_ptr);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
fast_increment_function(var_ptr);
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
zval_opt_copy_ctor(var_ptr);
|
|
|
|
increment_function(var_ptr);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *var_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
fast_decrement_function(var_ptr);
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
ZVAL_DEREF(var_ptr);
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr);
|
|
zval_opt_copy_ctor(var_ptr);
|
|
|
|
decrement_function(var_ptr);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *z;
|
|
|
|
SAVE_OPLINE();
|
|
z = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (Z_TYPE_P(z) == IS_STRING) {
|
|
zend_string *str = Z_STR_P(z);
|
|
|
|
if (str->len != 0) {
|
|
zend_write(str->val, str->len);
|
|
}
|
|
} else {
|
|
zend_string *str = _zval_get_string_func(z);
|
|
|
|
if (str->len != 0) {
|
|
zend_write(str->val, str->len);
|
|
}
|
|
zend_string_release(str);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRINT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
|
return ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if (IS_CV == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline++;
|
|
} else {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if (IS_CV == IS_CV) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
} else {
|
|
opline++;
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) {
|
|
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if (IS_CV == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
|
|
} else {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
if (IS_CV == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
opline++;
|
|
} else {
|
|
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
if (IS_CV == IS_CV) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
if (i_zend_is_true(val)) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
opline++;
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (!EX(return_value)) {
|
|
|
|
} else {
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_CV == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) {
|
|
zval_copy_ctor_func(EX(return_value));
|
|
}
|
|
}
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(retval_ptr)) {
|
|
ZVAL_COPY(EX(return_value), Z_REFVAL_P(retval_ptr));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
}
|
|
}
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *retval_ptr;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
|
|
do {
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR ||
|
|
(IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) {
|
|
/* Not supposed to happen, but we'll allow it */
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
|
|
retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (!EX(return_value)) {
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (IS_CV != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor_no_imm(EX(return_value));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
retval_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot return string offsets by reference");
|
|
}
|
|
|
|
if (IS_CV == IS_VAR) {
|
|
if (retval_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) {
|
|
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
|
if (EX(return_value)) {
|
|
ZVAL_NEW_REF(EX(return_value), retval_ptr);
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (EX(return_value)) {
|
|
ZVAL_MAKE_REF(retval_ptr);
|
|
Z_ADDREF_P(retval_ptr);
|
|
ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr));
|
|
Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF;
|
|
}
|
|
} while (0);
|
|
|
|
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
do {
|
|
if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
|
|
value = Z_REFVAL_P(value);
|
|
if (EXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Can only throw objects");
|
|
}
|
|
} while (0);
|
|
|
|
zend_exception_save();
|
|
if (IS_CV != IS_TMP_VAR) {
|
|
if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
|
|
zend_throw_exception_object(value);
|
|
zend_exception_restore();
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *varptr, *arg;
|
|
|
|
|
|
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
if (Z_ISREF_P(varptr)) {
|
|
ZVAL_COPY(arg, Z_REFVAL_P(varptr));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varptr, *arg;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (!(opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND)) {
|
|
if (!ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
return ZEND_SEND_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) ||
|
|
(Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) &&
|
|
(Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) {
|
|
|
|
ZVAL_MAKE_REF(varptr);
|
|
if (IS_CV == IS_CV) {
|
|
Z_ADDREF_P(varptr);
|
|
}
|
|
} else {
|
|
if ((opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) ?
|
|
!(opline->extended_value & ZEND_ARG_SEND_SILENT) :
|
|
!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
zend_error(E_STRICT, "Only variables should be passed by reference");
|
|
}
|
|
}
|
|
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varptr, *arg;
|
|
|
|
SAVE_OPLINE();
|
|
varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(varptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Only variables can be passed by reference");
|
|
}
|
|
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
if (IS_CV == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) {
|
|
ZVAL_NEW_REF(arg, &EG(uninitialized_zval));
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (Z_ISREF_P(varptr)) {
|
|
Z_ADDREF_P(varptr);
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
} else if (IS_CV == IS_VAR &&
|
|
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT)) {
|
|
ZVAL_NEW_REF(arg, varptr);
|
|
} else {
|
|
ZVAL_NEW_REF(arg, varptr);
|
|
Z_ADDREF_P(arg);
|
|
ZVAL_REF(varptr, Z_REF_P(arg));
|
|
}
|
|
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *varptr, *arg;
|
|
|
|
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
return ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
varptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
arg = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
if (Z_ISREF_P(varptr)) {
|
|
ZVAL_COPY(arg, Z_REFVAL_P(varptr));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(arg, varptr);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(arg)) Z_ADDREF_P(arg);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SEND_USER_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *arg, *param, tmp;
|
|
|
|
|
|
arg = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
param = ZEND_CALL_ARG(EX(call), opline->op2.num);
|
|
|
|
if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
// TODO: Scalar values don't have reference counters anymore.
|
|
// They are assumed to be 1, and they may be easily passed by
|
|
// reference now. However, previously scalars with refcount==1
|
|
// might be passed and with refcount>1 might not. We can support
|
|
// only single behavior ???
|
|
#if 0
|
|
if (Z_REFCOUNTED_P(arg) &&
|
|
// This solution breaks the following test (omit warning message) ???
|
|
// Zend/tests/bug61273.phpt
|
|
// ext/reflection/tests/bug42976.phpt
|
|
// ext/standard/tests/general_functions/call_user_func_array_variation_001.phpt
|
|
#else
|
|
if (!Z_REFCOUNTED_P(arg) ||
|
|
// This solution breaks the following test (emit warning message) ???
|
|
// ext/pdo_sqlite/tests/pdo_005.phpt
|
|
#endif
|
|
(!Z_ISREF_P(arg) /*&& Z_REFCOUNT_P(arg) > 1???*/)) {
|
|
|
|
if (!ARG_MAY_BE_SENT_BY_REF(EX(call)->func, opline->op2.num)) {
|
|
|
|
zend_error(E_WARNING, "Parameter %d to %s%s%s() expected to be a reference, value given",
|
|
opline->op2.num,
|
|
EX(call)->func->common.scope ? EX(call)->func->common.scope->name->val : "",
|
|
EX(call)->func->common.scope ? "::" : "",
|
|
EX(call)->func->common.function_name->val);
|
|
|
|
if (EX(call)->func->common.fn_flags & ZEND_ACC_CLOSURE) {
|
|
OBJ_RELEASE((zend_object*)EX(call)->func->common.prototype);
|
|
}
|
|
if (Z_OBJ(EX(call)->This)) {
|
|
OBJ_RELEASE(Z_OBJ(EX(call)->This));
|
|
}
|
|
EX(call)->func = (zend_function*)&zend_pass_function;
|
|
EX(call)->called_scope = NULL;
|
|
Z_OBJ(EX(call)->This) = NULL;
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (Z_REFCOUNTED_P(arg)) {
|
|
Z_DELREF_P(arg);
|
|
}
|
|
ZVAL_DUP(&tmp, arg);
|
|
ZVAL_NEW_REF(arg, &tmp);
|
|
Z_ADDREF_P(arg);
|
|
} else if (!Z_ISREF_P(arg)) {
|
|
ZVAL_NEW_REF(arg, arg);
|
|
Z_ADDREF_P(arg);
|
|
} else if (Z_REFCOUNTED_P(arg)) {
|
|
Z_ADDREF_P(arg);
|
|
}
|
|
ZVAL_COPY_VALUE(param, arg);
|
|
} else if (Z_ISREF_P(arg) &&
|
|
/* don't separate references for __call */
|
|
(EX(call)->func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) == 0) {
|
|
ZVAL_DUP(param, Z_REFVAL_P(arg));
|
|
} else {
|
|
ZVAL_COPY(param, arg);
|
|
}
|
|
|
|
ZEND_CALL_NUM_ARGS(EX(call)) = opline->op2.num;
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *val;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val));
|
|
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *obj;
|
|
zend_class_entry *ce;
|
|
zend_function *clone;
|
|
zend_object_clone_obj_t clone_call;
|
|
|
|
SAVE_OPLINE();
|
|
obj = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
do {
|
|
if (IS_CV == IS_CONST ||
|
|
(IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
|
|
obj = Z_REFVAL_P(obj);
|
|
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
|
|
}
|
|
} while (0);
|
|
|
|
ce = Z_OBJCE_P(obj);
|
|
clone = ce ? ce->clone : NULL;
|
|
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
|
if (UNEXPECTED(clone_call == NULL)) {
|
|
if (ce) {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object");
|
|
}
|
|
}
|
|
|
|
if (ce && clone) {
|
|
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
|
/* Ensure that if we're calling a private function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(ce != EG(scope))) {
|
|
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
|
/* Ensure that if we're calling a protected function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
|
|
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
|
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
|
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
|
}
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
/* This code is taken from convert_to_null. However, it does not seems very useful,
|
|
* because a conversion to null always results in the same value. This could only
|
|
* be relevant if a cast_object handler for IS_NULL has some kind of side-effect. */
|
|
#if 0
|
|
if (IS_CV == IS_VAR || IS_CV == IS_CV) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
if (Z_TYPE_P(expr) == IS_OBJECT && Z_OBJ_HT_P(expr)->cast_object) {
|
|
if (Z_OBJ_HT_P(expr)->cast_object(expr, result, IS_NULL) == SUCCESS) {
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
ZVAL_NULL(result);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(result, zend_is_true(expr));
|
|
break;
|
|
case IS_LONG:
|
|
ZVAL_LONG(result, zval_get_long(expr));
|
|
break;
|
|
case IS_DOUBLE:
|
|
ZVAL_DOUBLE(result, zval_get_double(expr));
|
|
break;
|
|
case IS_STRING:
|
|
ZVAL_STR(result, zval_get_string(expr));
|
|
break;
|
|
default:
|
|
if (IS_CV & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(expr);
|
|
}
|
|
/* If value is already of correct type, return it directly */
|
|
if (Z_TYPE_P(expr) == opline->extended_value) {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
if (IS_CV == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(result))) {
|
|
zval_copy_ctor_func(result);
|
|
}
|
|
} else if (IS_CV != IS_TMP_VAR) {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
if (opline->extended_value == IS_ARRAY) {
|
|
if (Z_TYPE_P(expr) != IS_OBJECT) {
|
|
ZVAL_NEW_ARR(result);
|
|
zend_hash_init(Z_ARRVAL_P(result), 8, NULL, ZVAL_PTR_DTOR, 0);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_index_add_new(Z_ARRVAL_P(result), 0, expr);
|
|
if (IS_CV == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
Z_ADDREF_P(result);
|
|
convert_to_array(result);
|
|
}
|
|
} else {
|
|
if (Z_TYPE_P(expr) != IS_ARRAY) {
|
|
object_init(result);
|
|
if (Z_TYPE_P(expr) != IS_NULL) {
|
|
expr = zend_hash_str_add_new(Z_OBJPROP_P(result), "scalar", sizeof("scalar")-1, expr);
|
|
if (IS_CV == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(expr))) {
|
|
zval_copy_ctor_func(expr);
|
|
}
|
|
} else {
|
|
if (Z_OPT_REFCOUNTED_P(expr)) Z_ADDREF_P(expr);
|
|
}
|
|
}
|
|
} else {
|
|
ZVAL_COPY_VALUE(result, expr);
|
|
zval_opt_copy_ctor(result);
|
|
convert_to_object(result);
|
|
}
|
|
}
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_op_array *new_op_array=NULL;
|
|
|
|
zval *inc_filename;
|
|
zval tmp_inc_filename;
|
|
zend_bool failure_retval=0;
|
|
|
|
SAVE_OPLINE();
|
|
inc_filename = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
ZVAL_UNDEF(&tmp_inc_filename);
|
|
if (Z_TYPE_P(inc_filename) != IS_STRING) {
|
|
ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
|
|
inc_filename = &tmp_inc_filename;
|
|
}
|
|
|
|
if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
|
|
if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
|
|
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
} else {
|
|
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
}
|
|
} else {
|
|
switch (opline->extended_value) {
|
|
case ZEND_INCLUDE_ONCE:
|
|
case ZEND_REQUIRE_ONCE: {
|
|
zend_file_handle file_handle;
|
|
char *resolved_path;
|
|
|
|
resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename));
|
|
if (resolved_path) {
|
|
failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
|
|
} else {
|
|
resolved_path = Z_STRVAL_P(inc_filename);
|
|
}
|
|
|
|
if (failure_retval) {
|
|
/* do nothing, file already included */
|
|
} else if (SUCCESS == zend_stream_open(resolved_path, &file_handle)) {
|
|
|
|
if (!file_handle.opened_path) {
|
|
file_handle.opened_path = estrdup(resolved_path);
|
|
}
|
|
|
|
if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
|
|
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE));
|
|
zend_destroy_file_handle(&file_handle);
|
|
} else {
|
|
zend_file_handle_dtor(&file_handle);
|
|
failure_retval=1;
|
|
}
|
|
} else {
|
|
if (opline->extended_value == ZEND_INCLUDE_ONCE) {
|
|
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
} else {
|
|
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
}
|
|
}
|
|
if (resolved_path != Z_STRVAL_P(inc_filename)) {
|
|
efree(resolved_path);
|
|
}
|
|
}
|
|
break;
|
|
case ZEND_INCLUDE:
|
|
case ZEND_REQUIRE:
|
|
new_op_array = compile_filename(opline->extended_value, inc_filename);
|
|
break;
|
|
case ZEND_EVAL: {
|
|
char *eval_desc = zend_make_compiled_string_description("eval()'d code");
|
|
|
|
new_op_array = zend_compile_string(inc_filename, eval_desc);
|
|
efree(eval_desc);
|
|
}
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp_inc_filename));
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
} else if (EXPECTED(new_op_array != NULL)) {
|
|
zval *return_value = NULL;
|
|
zend_execute_data *call;
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
return_value = EX_VAR(opline->result.var);
|
|
}
|
|
|
|
new_op_array->scope = EG(scope); /* ??? */
|
|
|
|
call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE,
|
|
(zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL);
|
|
|
|
if (EX(symbol_table)) {
|
|
call->symbol_table = EX(symbol_table);
|
|
} else {
|
|
call->symbol_table = zend_rebuild_symbol_table();
|
|
}
|
|
|
|
call->prev_execute_data = execute_data;
|
|
i_init_code_execute_data(call, new_op_array, return_value);
|
|
if (EXPECTED(zend_execute_ex == execute_ex)) {
|
|
ZEND_VM_ENTER();
|
|
} else {
|
|
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
|
zend_execute_ex(call);
|
|
}
|
|
|
|
destroy_op_array(new_op_array);
|
|
efree_size(new_op_array, sizeof(zend_op_array));
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
} else if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *array_ptr, *array_ref, iterator, tmp;
|
|
HashTable *fe_ht;
|
|
zend_object_iterator *iter = NULL;
|
|
zend_class_entry *ce = NULL;
|
|
zend_bool is_empty = 0;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if ((IS_CV == IS_CV || IS_CV == IS_VAR) &&
|
|
(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
ZVAL_DEREF(array_ptr);
|
|
if (Z_TYPE_P(array_ptr) == IS_ARRAY) {
|
|
SEPARATE_ARRAY(array_ptr);
|
|
if (!Z_ISREF_P(array_ref)) {
|
|
ZVAL_NEW_REF(array_ref, array_ref);
|
|
array_ptr = Z_REFVAL_P(array_ref);
|
|
}
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce->get_iterator == NULL) {
|
|
Z_ADDREF_P(array_ptr);
|
|
}
|
|
array_ref = array_ptr;
|
|
} else {
|
|
if (Z_REFCOUNTED_P(array_ref)) Z_ADDREF_P(array_ref);
|
|
}
|
|
} else {
|
|
array_ptr = array_ref = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (IS_CV & (IS_VAR|IS_CV)) {
|
|
ZVAL_DEREF(array_ptr);
|
|
}
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&tmp, array_ptr);
|
|
if (Z_OPT_IMMUTABLE_P(&tmp)) {
|
|
zval_copy_ctor_func(&tmp);
|
|
}
|
|
array_ref = array_ptr = &tmp;
|
|
if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (ce && ce->get_iterator) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_TYPE_P(array_ptr) == IS_OBJECT) {
|
|
ce = Z_OBJCE_P(array_ptr);
|
|
if (!ce->get_iterator) {
|
|
if (IS_CV == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
} else if (Z_IMMUTABLE_P(array_ref)) {
|
|
if (IS_CV == IS_CV) {
|
|
zval_copy_ctor_func(array_ref);
|
|
Z_ADDREF_P(array_ref);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&tmp, array_ref);
|
|
zval_copy_ctor_func(&tmp);
|
|
array_ptr = array_ref = &tmp;
|
|
}
|
|
} else if (Z_REFCOUNTED_P(array_ref)) {
|
|
if (IS_CV == IS_CONST ||
|
|
(IS_CV == IS_CV &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 1) ||
|
|
(IS_CV == IS_VAR &&
|
|
!Z_ISREF_P(array_ref) &&
|
|
Z_REFCOUNT_P(array_ref) > 2)) {
|
|
if (IS_CV == IS_VAR) {
|
|
Z_DELREF_P(array_ref);
|
|
}
|
|
ZVAL_DUP(&tmp, array_ref);
|
|
array_ptr = array_ref = &tmp;
|
|
} else if (IS_CV == IS_CV || IS_CV == IS_VAR) {
|
|
if (Z_ISREF_P(array_ref) && Z_REFCOUNT_P(array_ref) == 1) {
|
|
ZVAL_UNREF(array_ref);
|
|
array_ptr = array_ref;
|
|
}
|
|
if (Z_IMMUTABLE_P(array_ptr)) {
|
|
zval_copy_ctor_func(array_ptr);
|
|
} else if (Z_ISREF_P(array_ref) &&
|
|
Z_COPYABLE_P(array_ptr) &&
|
|
Z_REFCOUNT_P(array_ptr) > 1) {
|
|
Z_DELREF_P(array_ptr);
|
|
zval_copy_ctor_func(array_ptr);
|
|
}
|
|
if (IS_CV == IS_CV) {
|
|
Z_ADDREF_P(array_ref);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ce && ce->get_iterator) {
|
|
iter = ce->get_iterator(ce, array_ptr, opline->extended_value & ZEND_FE_FETCH_BYREF);
|
|
|
|
if (IS_CV == IS_VAR && !(opline->extended_value & ZEND_FE_FETCH_BYREF)) {
|
|
|
|
}
|
|
if (iter && EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(&iterator, &iter->std);
|
|
array_ptr = array_ref = &iterator;
|
|
} else {
|
|
if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
if (!EG(exception)) {
|
|
zend_throw_exception_ex(NULL, 0, "Object of type %s did not create an Iterator", ce->name->val);
|
|
}
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), array_ref);
|
|
|
|
if (iter) {
|
|
iter->index = 0;
|
|
if (iter->funcs->rewind) {
|
|
iter->funcs->rewind(iter);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
}
|
|
is_empty = iter->funcs->valid(iter) != SUCCESS;
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor(array_ref);
|
|
if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
iter->index = -1; /* will be set to 0 before using next handler */
|
|
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
|
|
HashPointer *ptr = (HashPointer*)EX_VAR((opline+2)->op1.var);
|
|
HashPosition pos = 0;
|
|
Bucket *p;
|
|
|
|
while (1) {
|
|
if (pos >= fe_ht->nNumUsed) {
|
|
is_empty = 1;
|
|
if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
p = fe_ht->arData + pos;
|
|
if (Z_TYPE(p->val) == IS_UNDEF ||
|
|
(Z_TYPE(p->val) == IS_INDIRECT &&
|
|
Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
|
|
pos++;
|
|
continue;
|
|
}
|
|
if (!ce ||
|
|
!p->key ||
|
|
zend_check_property_access(Z_OBJ_P(array_ptr), p->key) == SUCCESS) {
|
|
break;
|
|
}
|
|
pos++;
|
|
}
|
|
fe_ht->nInternalPointer = pos;
|
|
ptr->pos = pos;
|
|
ptr->ht = fe_ht;
|
|
ptr->h = fe_ht->arData[pos].h;
|
|
ptr->key = fe_ht->arData[pos].key;
|
|
is_empty = 0;
|
|
} else {
|
|
zend_error(E_WARNING, "Invalid argument supplied for foreach()");
|
|
is_empty = 1;
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && opline->extended_value & ZEND_FE_FETCH_BYREF) {
|
|
|
|
}
|
|
if (is_empty) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
do {
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
} else {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(ptr)) {
|
|
ptr = Z_REFVAL_P(ptr);
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
break;
|
|
}
|
|
}
|
|
zend_print_variable(ptr);
|
|
}
|
|
} while (0);
|
|
|
|
}
|
|
#endif
|
|
zend_bailout();
|
|
ZEND_VM_NEXT_OPCODE(); /* Never reached */
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
if (i_zend_is_true(value)) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_CV == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_CV == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_COALESCE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
int is_ref = 0;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
|
|
if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) {
|
|
is_ref = 1;
|
|
value = Z_REFVAL_P(value);
|
|
}
|
|
|
|
if (Z_TYPE_P(value) > IS_NULL) {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_CV == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
} else if (IS_CV == IS_VAR && is_ref) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
|
|
}
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(value)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(EX_VAR(opline->result.var), value);
|
|
if (IS_CV == IS_CONST) {
|
|
if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) {
|
|
zval_copy_ctor_func(EX_VAR(opline->result.var));
|
|
}
|
|
} else if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
try_strlen:
|
|
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
|
} else {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
|
|
value = Z_REFVAL_P(value);
|
|
goto try_strlen;
|
|
} else if (Z_TYPE_P(value) < IS_TRUE) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
|
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
|
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
|
zend_string *str = zval_get_string(value);
|
|
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
|
zend_string_release(str);
|
|
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
|
zend_string *str;
|
|
zval tmp;
|
|
|
|
ZVAL_COPY(&tmp, value);
|
|
if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) {
|
|
goto strlen_error;
|
|
}
|
|
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
|
zval_dtor(&tmp);
|
|
} else {
|
|
strlen_error:
|
|
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
|
|
switch (opline->extended_value) {
|
|
case IS_NULL:
|
|
case IS_LONG:
|
|
case IS_DOUBLE:
|
|
case IS_STRING:
|
|
case IS_ARRAY:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == opline->extended_value);
|
|
break;
|
|
case _IS_BOOL:
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), Z_TYPE_P(value) == IS_TRUE || Z_TYPE_P(value) == IS_FALSE);
|
|
break;
|
|
case IS_OBJECT:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
zend_class_entry *ce = Z_OBJCE_P(value);
|
|
if (ce->name->len == sizeof("__PHP_Incomplete_Class") - 1
|
|
&& !strncmp(ce->name->val, "__PHP_Incomplete_Class", ce->name->len)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
case IS_RESOURCE:
|
|
if (Z_TYPE_P(value) == opline->extended_value) {
|
|
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(value));
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), type_name != NULL);
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
zval *property = EX_CONSTANT(opline->op2);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = EX_CONSTANT(opline->op2);
|
|
|
|
do {
|
|
if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_CV != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CONST(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *var_ptr;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op2);
|
|
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CONST != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CONST(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
property = EX_CONSTANT(opline->op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_CV_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_CV_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
property = EX_CONSTANT(opline->op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_CV_CONST(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_CV_CONST(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if (IS_CV != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
|
|
}
|
|
}
|
|
|
|
if (IS_CV != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_CONST == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = EX_CONSTANT(opline->op2);
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
property = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
try_fetch_list:
|
|
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
|
|
zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), EX_CONSTANT(opline->op2), IS_CONST, BP_VAR_R);
|
|
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
|
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
|
zval *result = EX_VAR(opline->result.var);
|
|
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
|
|
|
|
if (retval) {
|
|
if (result != retval) {
|
|
ZVAL_COPY(result, retval);
|
|
}
|
|
} else {
|
|
ZVAL_NULL(result);
|
|
}
|
|
} else if (Z_TYPE_P(container) == IS_REFERENCE) {
|
|
container = Z_REFVAL_P(container);
|
|
goto try_fetch_list;
|
|
} else {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
property_name = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object_ptr;
|
|
zend_free_op free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = EX_CONSTANT(opline->op2);
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CONST);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
|
|
zval *property_name = EX_CONSTANT(opline->op2);
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = EX_CONSTANT(opline->op2);
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = EX_CONSTANT(opline->op2);
|
|
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_CONST == IS_TMP_VAR) {
|
|
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_CONST);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CONST != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if (IS_CONST != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CV == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *offset = EX_CONSTANT(opline->op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CV != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CV == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CV != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CV == IS_CV &&
|
|
IS_CONST == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
unset_dim_again:
|
|
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
|
|
} else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if (IS_CONST == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
|
|
} else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CV == IS_CV &&
|
|
IS_CONST == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CONST & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr;
|
|
zend_bool result;
|
|
|
|
SAVE_OPLINE();
|
|
expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
try_instanceof:
|
|
if (Z_TYPE_P(expr) == IS_OBJECT) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
result = instanceof_function(Z_OBJCE_P(expr), ce);
|
|
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
|
|
expr = Z_REFVAL_P(expr);
|
|
goto try_instanceof;
|
|
} else {
|
|
result = 0;
|
|
}
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CV != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CV == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CONST != IS_UNUSED) {
|
|
|
|
zval *key = EX_CONSTANT(opline->op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CONST == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CONST == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CONST == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_binary_assign_op_helper_SPEC_CV_CONST(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varname;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
uint32_t idx;
|
|
|
|
SAVE_OPLINE();
|
|
varname = EX_CONSTANT(opline->op2);
|
|
|
|
/* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
|
|
idx = (uint32_t)(uintptr_t)CACHED_PTR(Z_CACHE_SLOT_P(varname)) - 1;
|
|
if (EXPECTED(idx < EG(symbol_table).ht.nNumUsed)) {
|
|
Bucket *p = EG(symbol_table).ht.arData + idx;
|
|
|
|
if (EXPECTED(Z_TYPE(p->val) != IS_UNDEF) &&
|
|
(EXPECTED(p->key == Z_STR_P(varname)) ||
|
|
(EXPECTED(p->h == Z_STR_P(varname)->h) &&
|
|
EXPECTED(p->key != NULL) &&
|
|
EXPECTED(p->key->len == Z_STRLEN_P(varname)) &&
|
|
EXPECTED(memcmp(p->key->val, Z_STRVAL_P(varname), Z_STRLEN_P(varname)) == 0)))) {
|
|
|
|
value = &EG(symbol_table).ht.arData[idx].val;
|
|
goto check_indirect;
|
|
}
|
|
}
|
|
|
|
value = zend_hash_find(&EG(symbol_table).ht, Z_STR_P(varname));
|
|
if (UNEXPECTED(value == NULL)) {
|
|
value = zend_hash_add_new(&EG(symbol_table).ht, Z_STR_P(varname), &EG(uninitialized_zval));
|
|
idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
|
|
/* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
|
|
CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1));
|
|
} else {
|
|
idx = ((char*)value - (char*)EG(symbol_table).ht.arData) / sizeof(Bucket);
|
|
/* Store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
|
|
CACHE_PTR(Z_CACHE_SLOT_P(varname), (void*)(uintptr_t)(idx + 1));
|
|
check_indirect:
|
|
/* GLOBAL variable may be an INDIRECT pointer to CV */
|
|
if (UNEXPECTED(Z_TYPE_P(value) == IS_INDIRECT)) {
|
|
value = Z_INDIRECT_P(value);
|
|
if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
|
|
ZVAL_NULL(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
zend_assign_to_variable_reference(variable_ptr, value);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
|
|
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CV != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CV == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_TMP_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_TMP_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_TMP_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_TMP_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if (IS_CV != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
|
|
}
|
|
}
|
|
|
|
if (IS_CV != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
|
|
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_VAR == IS_TMP_VAR) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_VAR);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *variable_ptr;
|
|
zval *value_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_VAR == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
if (!(free_op2 != NULL)) {
|
|
PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
|
}
|
|
zend_error(E_STRICT, "Only variables should be assigned by reference");
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
return ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!(free_op2 != NULL)) {
|
|
PZVAL_LOCK(value_ptr);
|
|
}
|
|
}
|
|
|
|
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_CV == IS_VAR &&
|
|
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) &&
|
|
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
|
|
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
|
|
}
|
|
if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
|
|
(IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) {
|
|
variable_ptr = &EG(uninitialized_zval);
|
|
} else {
|
|
zend_assign_to_variable_reference(variable_ptr, value_ptr);
|
|
}
|
|
|
|
if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!(free_op2 != NULL)) {
|
|
Z_DELREF_P(variable_ptr);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
|
|
}
|
|
|
|
if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CV == IS_CV &&
|
|
IS_VAR == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CV == IS_CV &&
|
|
IS_VAR == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr;
|
|
zend_bool result;
|
|
|
|
SAVE_OPLINE();
|
|
expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
try_instanceof:
|
|
if (Z_TYPE_P(expr) == IS_OBJECT) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
result = instanceof_function(Z_OBJCE_P(expr), ce);
|
|
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
|
|
expr = Z_REFVAL_P(expr);
|
|
goto try_instanceof;
|
|
} else {
|
|
result = 0;
|
|
}
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CV != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CV == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *key = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_VAR == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_VAR == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_VAR == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = NULL;
|
|
|
|
do {
|
|
if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_CV != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_UNUSED != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_UNUSED(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if (IS_CV != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
|
|
}
|
|
}
|
|
|
|
if (IS_CV != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_UNUSED == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
|
|
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object_ptr;
|
|
zend_free_op free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = NULL;
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_UNUSED);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
|
|
zval *property_name = NULL;
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = NULL;
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CV == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *offset = NULL;
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_UNUSED != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CV != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CV == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CV != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CV == IS_CV &&
|
|
IS_UNUSED == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if (IS_CV == IS_CV &&
|
|
IS_UNUSED == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
|
|
zval tmp, *varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CV != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CV == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
|
|
zval *key = NULL;
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_UNUSED == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_UNUSED == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_UNUSED == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_identical_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_not_identical_function(result,
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
zval *property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
do {
|
|
if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_CV != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV);
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_CV(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *var_ptr;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || (IS_CV != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_CV(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_CV_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_CV_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_CV_CV(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_CV_CV(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
|
|
} else {
|
|
if (IS_CV == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object_ptr;
|
|
zend_free_op free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, IS_CV);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
|
|
zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
|
|
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, IS_CV);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
|
|
}
|
|
|
|
/* zend_assign_to_variable() always takes care of op2, never free it! */
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *variable_ptr;
|
|
zval *value_ptr;
|
|
|
|
SAVE_OPLINE();
|
|
value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_CV == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
if (!0) {
|
|
PZVAL_LOCK(value_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
|
}
|
|
zend_error(E_STRICT, "Only variables should be assigned by reference");
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
return ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!0) {
|
|
PZVAL_LOCK(value_ptr);
|
|
}
|
|
}
|
|
|
|
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
|
|
}
|
|
if (IS_CV == IS_VAR &&
|
|
UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) &&
|
|
UNEXPECTED(!Z_ISREF_P(variable_ptr))) {
|
|
zend_error_noreturn(E_ERROR, "Cannot assign by reference to overloaded object");
|
|
}
|
|
if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) ||
|
|
(IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) {
|
|
variable_ptr = &EG(uninitialized_zval);
|
|
} else {
|
|
zend_assign_to_variable_reference(variable_ptr, value_ptr);
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_NEW) {
|
|
if (!0) {
|
|
Z_DELREF_P(variable_ptr);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr);
|
|
}
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if (IS_CV != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CV == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CV != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CV == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CV != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
unset_dim_again:
|
|
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
|
|
} else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if (IS_CV == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
|
|
} else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CV & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
/* The generator object is stored in EX(return_value) */
|
|
zend_generator *generator = (zend_generator *) EX(return_value);
|
|
|
|
if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield from finally in a force-closed generator");
|
|
}
|
|
|
|
/* Destroy the previously yielded value */
|
|
zval_ptr_dtor(&generator->value);
|
|
|
|
/* Destroy the previously yielded key */
|
|
zval_ptr_dtor(&generator->key);
|
|
|
|
/* Set the new yielded value */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
|
|
if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
|
|
/* Constants and temporary variables aren't yieldable by reference,
|
|
* but we still allow them with a notice. */
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zval *value;
|
|
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
|
|
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
|
|
|
|
/* Temporary variables don't need ctor copying */
|
|
if (IS_CV != IS_TMP_VAR) {
|
|
zval_opt_copy_ctor(&generator->value);
|
|
}
|
|
} else {
|
|
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot yield string offsets by reference");
|
|
}
|
|
|
|
/* If a function call result is yielded and the function did
|
|
* not return by reference we throw a notice. */
|
|
if (IS_CV == IS_VAR &&
|
|
(value_ptr == &EG(uninitialized_zval) ||
|
|
(opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
|
!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) {
|
|
zend_error(E_NOTICE, "Only variable references should be yielded by reference");
|
|
} else {
|
|
ZVAL_MAKE_REF(value_ptr);
|
|
}
|
|
ZVAL_COPY(&generator->value, value_ptr);
|
|
|
|
}
|
|
} else {
|
|
zval *value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->value, value);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
|
|
ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->value, value);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(value)) Z_ADDREF_P(value);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
/* If no value was specified yield null */
|
|
ZVAL_NULL(&generator->value);
|
|
}
|
|
|
|
/* Set the new yielded key */
|
|
if (IS_CV != IS_UNUSED) {
|
|
|
|
zval *key = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
/* Consts, temporary variables and references need copying */
|
|
if (IS_CV == IS_CONST) {
|
|
ZVAL_DUP(&generator->key, key);
|
|
} else if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
} else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
|
|
ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
|
|
|
|
} else {
|
|
ZVAL_COPY_VALUE(&generator->key, key);
|
|
if (IS_CV == IS_CV) {
|
|
if (Z_OPT_REFCOUNTED_P(key)) Z_ADDREF_P(key);
|
|
}
|
|
}
|
|
|
|
if (Z_TYPE(generator->key) == IS_LONG
|
|
&& Z_LVAL(generator->key) > generator->largest_used_integer_key
|
|
) {
|
|
generator->largest_used_integer_key = Z_LVAL(generator->key);
|
|
}
|
|
} else {
|
|
/* If no key was specified we use auto-increment keys */
|
|
generator->largest_used_integer_key++;
|
|
ZVAL_LONG(&generator->key, generator->largest_used_integer_key);
|
|
}
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
/* If the return value of yield is used set the send
|
|
* target and initialize it to NULL */
|
|
generator->send_target = EX_VAR(opline->result.var);
|
|
ZVAL_NULL(generator->send_target);
|
|
} else {
|
|
generator->send_target = NULL;
|
|
}
|
|
|
|
/* We increment to the next op, so we are at the correct position when the
|
|
* generator is resumed. */
|
|
ZEND_VM_INC_OPCODE();
|
|
|
|
/* The GOTO VM uses a local opline variable. We need to set the opline
|
|
* variable in execute_data so we don't resume at an old position. */
|
|
SAVE_OPLINE();
|
|
|
|
ZEND_VM_RETURN();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_binary_assign_op_helper_SPEC_CV_CV(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2, free_op_data1;
|
|
zval *object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
zval *property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zval *value;
|
|
zval *zptr;
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
do {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
binary_op(zptr, zptr, value);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
|
|
}
|
|
} else {
|
|
zval *z;
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property &&
|
|
(z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
|
|
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
binary_op(z, z, value);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), z);
|
|
}
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to assign property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2, free_op_data1;
|
|
zval *var_ptr, rv;
|
|
zval *value, *container, *dim;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
do {
|
|
if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
|
|
if (IS_CV != IS_UNUSED) {
|
|
ZVAL_DEREF(container);
|
|
}
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
|
|
break;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR));
|
|
value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
var_ptr = Z_INDIRECT(rv);
|
|
|
|
if (UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
FREE_OP(free_op_data1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_CV_TMPVAR(int (*binary_op)(zval *result, zval *op1, zval *op2), ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *var_ptr;
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
|
|
}
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) {
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
ZVAL_DEREF(var_ptr);
|
|
SEPARATE_ZVAL_NOREF(var_ptr);
|
|
|
|
binary_op(var_ptr, var_ptr, value);
|
|
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_ADD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SUB_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MUL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIV_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_MOD_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_SR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_CONCAT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_OR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_AND_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
# if 0 || (IS_CV != IS_UNUSED)
|
|
if (EXPECTED(opline->extended_value == 0)) {
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
# endif
|
|
if (EXPECTED(opline->extended_value == ZEND_ASSIGN_DIM)) {
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else /* if (EXPECTED(opline->extended_value == ZEND_ASSIGN_OBJ)) */ {
|
|
return zend_binary_assign_op_obj_helper_SPEC_CV_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
#else
|
|
return zend_binary_assign_op_dim_helper_SPEC_CV_TMPVAR(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
SEPARATE_ZVAL_NOREF(zptr);
|
|
|
|
incdec_op(zptr);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, zptr);
|
|
}
|
|
} else {
|
|
zval rv;
|
|
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DEREF(z);
|
|
SEPARATE_ZVAL_NOREF(z);
|
|
incdec_op(z);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(retval, z);
|
|
}
|
|
Z_OBJ_HT_P(object)->write_property(object, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMPVAR(incdec_t incdec_op, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zval *property;
|
|
zval *retval;
|
|
zval *zptr;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
retval = EX_VAR(opline->result.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
|
|
}
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
if (UNEXPECTED(!make_real_object(&object))) {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
|
|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
|
|
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
|
|
|
|
ZVAL_DEREF(zptr);
|
|
ZVAL_COPY_VALUE(retval, zptr);
|
|
zval_opt_copy_ctor(zptr);
|
|
|
|
incdec_op(zptr);
|
|
} else {
|
|
if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
|
|
zval rv;
|
|
zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), &rv);
|
|
zval z_copy;
|
|
|
|
if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
|
|
zval rv;
|
|
zval *value = Z_OBJ_HT_P(z)->get(z, &rv);
|
|
|
|
if (Z_REFCOUNT_P(z) == 0) {
|
|
zend_objects_store_del(Z_OBJ_P(z));
|
|
}
|
|
ZVAL_COPY_VALUE(z, value);
|
|
}
|
|
ZVAL_DUP(retval, z);
|
|
ZVAL_DUP(&z_copy, z);
|
|
incdec_op(&z_copy);
|
|
if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
|
|
Z_OBJ_HT_P(object)->write_property(object, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL));
|
|
zval_ptr_dtor(&z_copy);
|
|
zval_ptr_dtor(z);
|
|
} else {
|
|
zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
|
|
ZVAL_NULL(retval);
|
|
}
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
} else {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use [] for reading");
|
|
}
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_r_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_r_no_object:
|
|
zend_error(E_NOTICE, "Trying to get property of non-object");
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *container;
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
/* Behave like FETCH_OBJ_W */
|
|
zend_free_op free_op1, free_op2;
|
|
zval *property;
|
|
|
|
SAVE_OPLINE();
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
container = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context");
|
|
}
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
return ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container, *property;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an object");
|
|
}
|
|
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
if (IS_CV == IS_VAR && READY_TO_DESTROY(free_op1)) {
|
|
EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zval *property_name;
|
|
|
|
SAVE_OPLINE();
|
|
object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(property_name)) : NULL));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
/* assign_obj has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *object_ptr;
|
|
zend_free_op free_op2, free_op_data1;
|
|
zval rv;
|
|
zval *value;
|
|
zval *variable_ptr;
|
|
zval *dim;
|
|
|
|
SAVE_OPLINE();
|
|
object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
|
|
|
|
if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use string offset as an array");
|
|
}
|
|
|
|
try_assign_dim:
|
|
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
|
|
try_assign_dim_array:
|
|
dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zend_fetch_dimension_address_W(&rv, object_ptr, dim, (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
|
|
variable_ptr = Z_INDIRECT(rv);
|
|
if (UNEXPECTED(variable_ptr == &EG(error_zval))) {
|
|
FREE_OP(free_op_data1);
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
} else {
|
|
value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type);
|
|
if ((opline+1)->op1_type == IS_VAR) {
|
|
FREE_OP(free_op_data1);
|
|
}
|
|
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
}
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
|
|
zend_free_op free_op2;
|
|
zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING) &&
|
|
EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
|
|
zend_long offset;
|
|
|
|
dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
|
|
zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
|
|
FREE_OP(free_op_data1);
|
|
} else if (EXPECTED(Z_ISREF_P(object_ptr))) {
|
|
object_ptr = Z_REFVAL_P(object_ptr);
|
|
goto try_assign_dim;
|
|
} else {
|
|
goto try_assign_dim_array;
|
|
}
|
|
|
|
/* assign_dim has two opcodes! */
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_INC_OPCODE();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_free_op free_op2;
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
zval *expr_ptr, new_expr;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
|
|
(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot create references to/from string offsets");
|
|
}
|
|
ZVAL_MAKE_REF(expr_ptr);
|
|
Z_ADDREF_P(expr_ptr);
|
|
|
|
} else {
|
|
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_TMP_VAR) {
|
|
ZVAL_COPY_VALUE(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
} else if (IS_CV == IS_CONST) {
|
|
if (!Z_IMMUTABLE_P(expr_ptr)) {
|
|
ZVAL_DUP(&new_expr, expr_ptr);
|
|
expr_ptr = &new_expr;
|
|
}
|
|
} else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(expr_ptr)) {
|
|
expr_ptr = Z_REFVAL_P(expr_ptr);
|
|
if (Z_REFCOUNTED_P(expr_ptr)) Z_ADDREF_P(expr_ptr);
|
|
|
|
} else if (IS_CV == IS_CV && Z_REFCOUNTED_P(expr_ptr)) {
|
|
Z_ADDREF_P(expr_ptr);
|
|
}
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
|
zend_free_op free_op2;
|
|
zval *offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
zend_string *str;
|
|
zend_ulong hval;
|
|
|
|
add_again:
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index:
|
|
zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
|
|
break;
|
|
case IS_STRING:
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index;
|
|
}
|
|
}
|
|
str_index:
|
|
zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
|
|
break;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto add_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type");
|
|
zval_ptr_dtor(expr_ptr);
|
|
/* do nothing */
|
|
break;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else {
|
|
zend_hash_next_index_insert(Z_ARRVAL_P(EX_VAR(opline->result.var)), expr_ptr);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zval *array;
|
|
uint32_t size;
|
|
USE_OPLINE
|
|
|
|
array = EX_VAR(opline->result.var);
|
|
if (IS_CV != IS_UNUSED) {
|
|
size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;
|
|
} else {
|
|
size = 0;
|
|
}
|
|
ZVAL_NEW_ARR(array);
|
|
zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
if (IS_CV != IS_UNUSED) {
|
|
/* Explicitly initialize array as not-packed if flag is set */
|
|
if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {
|
|
zend_hash_real_init(Z_ARRVAL_P(array), 0);
|
|
}
|
|
}
|
|
|
|
if (IS_CV == IS_UNUSED) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
#if 0 || IS_CV != IS_UNUSED
|
|
} else {
|
|
return ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
zval *offset;
|
|
zend_ulong hval;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
unset_dim_again:
|
|
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht;
|
|
|
|
offset_again:
|
|
SEPARATE_ARRAY(container);
|
|
ht = Z_ARRVAL_P(container);
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_LONG:
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_dim:
|
|
zend_hash_index_del(ht, hval);
|
|
break;
|
|
case IS_STRING:
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
|
|
goto num_index_dim;
|
|
}
|
|
}
|
|
if (ht == &EG(symbol_table).ht) {
|
|
zend_delete_global_variable(Z_STR_P(offset));
|
|
} else {
|
|
zend_hash_del(ht, Z_STR_P(offset));
|
|
}
|
|
break;
|
|
case IS_NULL:
|
|
zend_hash_del(ht, STR_EMPTY_ALLOC());
|
|
break;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_dim;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_dim;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_dim;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto offset_again;
|
|
break;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in unset");
|
|
break;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot use object as array");
|
|
}
|
|
//??? if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
|
|
//??? zval_copy_ctor(offset);
|
|
//??? }
|
|
Z_OBJ_HT_P(container)->unset_dimension(container, offset);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
} else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto unset_dim_again;
|
|
} else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
ZEND_VM_CONTINUE(); /* bailed out before */
|
|
} else {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
|
|
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Cannot unset string offsets");
|
|
}
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
do {
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (Z_TYPE_P(container) != IS_OBJECT) {
|
|
break;
|
|
}
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
if (Z_OBJ_HT_P(container)->unset_property) {
|
|
Z_OBJ_HT_P(container)->unset_property(container, offset, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to unset property of non-object");
|
|
}
|
|
} while (0);
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
isset_dim_obj_again:
|
|
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_binary_assign_op_helper_SPEC_CV_TMPVAR(pow_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_not_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *val;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), !i_zend_is_true(val));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *z;
|
|
|
|
SAVE_OPLINE();
|
|
z = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (Z_TYPE_P(z) == IS_STRING) {
|
|
zend_string *str = Z_STR_P(z);
|
|
|
|
if (str->len != 0) {
|
|
zend_write(str->val, str->len);
|
|
}
|
|
} else {
|
|
zend_string *str = _zval_get_string_func(z);
|
|
|
|
if (str->len != 0) {
|
|
zend_write(str->val, str->len);
|
|
}
|
|
zend_string_release(str);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_PRINT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
|
return ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline++;
|
|
} else {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
} else {
|
|
opline++;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (EXPECTED(Z_TYPE_P(val) == IS_TRUE)) {
|
|
ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
|
|
} else {
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
|
|
ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2));
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
|
|
if (i_zend_is_true(val)) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
opline++;
|
|
} else {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *val;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op2));
|
|
ZEND_VM_CONTINUE();
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
ZEND_VM_SET_OPCODE(opline + 1);
|
|
ZEND_VM_CONTINUE();
|
|
}
|
|
}
|
|
if (i_zend_is_true(val)) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
opline = OP_JMP_ADDR(opline, opline->op2);
|
|
} else {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
opline++;
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
ZEND_VM_JMP(opline);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FREE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *val;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
val = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
if (Z_TYPE_P(val) == IS_TRUE) {
|
|
ZVAL_TRUE(EX_VAR(opline->result.var));
|
|
} else if (EXPECTED(Z_TYPE_P(val) <= IS_TRUE)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
} else {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), i_zend_is_true(val));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *obj;
|
|
zend_class_entry *ce;
|
|
zend_function *clone;
|
|
zend_object_clone_obj_t clone_call;
|
|
|
|
SAVE_OPLINE();
|
|
obj = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST ||
|
|
((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
|
|
obj = Z_REFVAL_P(obj);
|
|
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "__clone method called on non-object");
|
|
}
|
|
} while (0);
|
|
|
|
ce = Z_OBJCE_P(obj);
|
|
clone = ce ? ce->clone : NULL;
|
|
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
|
|
if (UNEXPECTED(clone_call == NULL)) {
|
|
if (ce) {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name->val);
|
|
} else {
|
|
zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object");
|
|
}
|
|
}
|
|
|
|
if (ce && clone) {
|
|
if (clone->op_array.fn_flags & ZEND_ACC_PRIVATE) {
|
|
/* Ensure that if we're calling a private function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(ce != EG(scope))) {
|
|
zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
|
|
/* Ensure that if we're calling a protected function, we're allowed to do so.
|
|
*/
|
|
if (UNEXPECTED(!zend_check_protected(zend_get_function_root_class(clone), EG(scope)))) {
|
|
zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name->val, EG(scope) ? EG(scope)->name->val : "");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (EXPECTED(EG(exception) == NULL)) {
|
|
ZVAL_OBJ(EX_VAR(opline->result.var), clone_call(obj));
|
|
if (UNEXPECTED(!RETURN_VALUE_USED(opline)) || UNEXPECTED(EG(exception) != NULL)) {
|
|
OBJ_RELEASE(Z_OBJ_P(EX_VAR(opline->result.var)));
|
|
}
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_op_array *new_op_array=NULL;
|
|
zend_free_op free_op1;
|
|
zval *inc_filename;
|
|
zval tmp_inc_filename;
|
|
zend_bool failure_retval=0;
|
|
|
|
SAVE_OPLINE();
|
|
inc_filename = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
ZVAL_UNDEF(&tmp_inc_filename);
|
|
if (Z_TYPE_P(inc_filename) != IS_STRING) {
|
|
ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
|
|
inc_filename = &tmp_inc_filename;
|
|
}
|
|
|
|
if (opline->extended_value != ZEND_EVAL && strlen(Z_STRVAL_P(inc_filename)) != Z_STRLEN_P(inc_filename)) {
|
|
if (opline->extended_value == ZEND_INCLUDE_ONCE || opline->extended_value == ZEND_INCLUDE) {
|
|
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
} else {
|
|
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
}
|
|
} else {
|
|
switch (opline->extended_value) {
|
|
case ZEND_INCLUDE_ONCE:
|
|
case ZEND_REQUIRE_ONCE: {
|
|
zend_file_handle file_handle;
|
|
char *resolved_path;
|
|
|
|
resolved_path = zend_resolve_path(Z_STRVAL_P(inc_filename), (int)Z_STRLEN_P(inc_filename));
|
|
if (resolved_path) {
|
|
failure_retval = zend_hash_str_exists(&EG(included_files), resolved_path, (int)strlen(resolved_path));
|
|
} else {
|
|
resolved_path = Z_STRVAL_P(inc_filename);
|
|
}
|
|
|
|
if (failure_retval) {
|
|
/* do nothing, file already included */
|
|
} else if (SUCCESS == zend_stream_open(resolved_path, &file_handle)) {
|
|
|
|
if (!file_handle.opened_path) {
|
|
file_handle.opened_path = estrdup(resolved_path);
|
|
}
|
|
|
|
if (zend_hash_str_add_empty_element(&EG(included_files), file_handle.opened_path, (int)strlen(file_handle.opened_path))) {
|
|
new_op_array = zend_compile_file(&file_handle, (opline->extended_value==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE));
|
|
zend_destroy_file_handle(&file_handle);
|
|
} else {
|
|
zend_file_handle_dtor(&file_handle);
|
|
failure_retval=1;
|
|
}
|
|
} else {
|
|
if (opline->extended_value == ZEND_INCLUDE_ONCE) {
|
|
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
} else {
|
|
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, Z_STRVAL_P(inc_filename));
|
|
}
|
|
}
|
|
if (resolved_path != Z_STRVAL_P(inc_filename)) {
|
|
efree(resolved_path);
|
|
}
|
|
}
|
|
break;
|
|
case ZEND_INCLUDE:
|
|
case ZEND_REQUIRE:
|
|
new_op_array = compile_filename(opline->extended_value, inc_filename);
|
|
break;
|
|
case ZEND_EVAL: {
|
|
char *eval_desc = zend_make_compiled_string_description("eval()'d code");
|
|
|
|
new_op_array = zend_compile_string(inc_filename, eval_desc);
|
|
efree(eval_desc);
|
|
}
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
if (Z_TYPE(tmp_inc_filename) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp_inc_filename));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
} else if (EXPECTED(new_op_array != NULL)) {
|
|
zval *return_value = NULL;
|
|
zend_execute_data *call;
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
return_value = EX_VAR(opline->result.var);
|
|
}
|
|
|
|
new_op_array->scope = EG(scope); /* ??? */
|
|
|
|
call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_CODE,
|
|
(zend_function*)new_op_array, 0, EX(called_scope), Z_OBJ(EX(This)), NULL);
|
|
|
|
if (EX(symbol_table)) {
|
|
call->symbol_table = EX(symbol_table);
|
|
} else {
|
|
call->symbol_table = zend_rebuild_symbol_table();
|
|
}
|
|
|
|
call->prev_execute_data = execute_data;
|
|
i_init_code_execute_data(call, new_op_array, return_value);
|
|
if (EXPECTED(zend_execute_ex == execute_ex)) {
|
|
ZEND_VM_ENTER();
|
|
} else {
|
|
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
|
zend_execute_ex(call);
|
|
}
|
|
|
|
destroy_op_array(new_op_array);
|
|
efree_size(new_op_array, sizeof(zend_op_array));
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zend_throw_exception_internal(NULL);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
} else if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), failure_retval);
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_EXIT_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
#if 0 || ((IS_TMP_VAR|IS_VAR) != IS_UNUSED)
|
|
USE_OPLINE
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
|
|
zend_free_op free_op1;
|
|
zval *ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
do {
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
} else {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(ptr)) {
|
|
ptr = Z_REFVAL_P(ptr);
|
|
if (Z_TYPE_P(ptr) == IS_LONG) {
|
|
EG(exit_status) = Z_LVAL_P(ptr);
|
|
break;
|
|
}
|
|
}
|
|
zend_print_variable(ptr);
|
|
}
|
|
} while (0);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
#endif
|
|
zend_bailout();
|
|
ZEND_VM_NEXT_OPCODE(); /* Never reached */
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
try_strlen:
|
|
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
|
|
} else {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
|
|
value = Z_REFVAL_P(value);
|
|
goto try_strlen;
|
|
} else if (Z_TYPE_P(value) < IS_TRUE) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 0);
|
|
} else if (Z_TYPE_P(value) == IS_TRUE) {
|
|
ZVAL_LONG(EX_VAR(opline->result.var), 1);
|
|
} else if (Z_TYPE_P(value) <= IS_DOUBLE) {
|
|
zend_string *str = zval_get_string(value);
|
|
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
|
zend_string_release(str);
|
|
} else if (Z_TYPE_P(value) == IS_OBJECT) {
|
|
zend_string *str;
|
|
zval tmp;
|
|
|
|
ZVAL_COPY(&tmp, value);
|
|
if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) {
|
|
goto strlen_error;
|
|
}
|
|
ZVAL_LONG(EX_VAR(opline->result.var), str->len);
|
|
zval_dtor(&tmp);
|
|
} else {
|
|
strlen_error:
|
|
zend_error(E_WARNING, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
try_fetch_list:
|
|
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
|
|
zval *value = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), EX_CONSTANT(opline->op2), IS_CONST, BP_VAR_R);
|
|
|
|
ZVAL_COPY(EX_VAR(opline->result.var), value);
|
|
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
|
|
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
|
|
zval *result = EX_VAR(opline->result.var);
|
|
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
|
|
|
|
if (retval) {
|
|
if (result != retval) {
|
|
ZVAL_COPY(result, retval);
|
|
}
|
|
} else {
|
|
ZVAL_NULL(result);
|
|
}
|
|
} else if (Z_TYPE_P(container) == IS_REFERENCE) {
|
|
container = Z_REFVAL_P(container);
|
|
goto try_fetch_list;
|
|
} else {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = EX_CONSTANT(opline->op2);
|
|
|
|
if (IS_CONST != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if (IS_CONST != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CONST == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
|
|
IS_CONST == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
|
|
IS_CONST == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_free_op free_op1;
|
|
zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_CONST != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
isset_dim_obj_again:
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CONST != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CONST & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = EX_CONSTANT(opline->op2);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr;
|
|
zend_bool result;
|
|
|
|
SAVE_OPLINE();
|
|
expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
try_instanceof:
|
|
if (Z_TYPE_P(expr) == IS_OBJECT) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_CONST == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
result = instanceof_function(Z_OBJCE_P(expr), ce);
|
|
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
|
|
expr = Z_REFVAL_P(expr);
|
|
goto try_instanceof;
|
|
} else {
|
|
result = 0;
|
|
}
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
EX_CONSTANT(opline->op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
|
|
IS_VAR == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
|
|
IS_VAR == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_free_op free_op1;
|
|
zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_VAR != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *expr;
|
|
zend_bool result;
|
|
|
|
SAVE_OPLINE();
|
|
expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
try_instanceof:
|
|
if (Z_TYPE_P(expr) == IS_OBJECT) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_VAR == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
ZVAL_FALSE(EX_VAR(opline->result.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
result = instanceof_function(Z_OBJCE_P(expr), ce);
|
|
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
|
|
expr = Z_REFVAL_P(expr);
|
|
goto try_instanceof;
|
|
} else {
|
|
result = 0;
|
|
}
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(int type, ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *varname;
|
|
zval *retval;
|
|
zend_string *name;
|
|
HashTable *target_symbol_table;
|
|
|
|
SAVE_OPLINE();
|
|
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
|
|
name = Z_STR_P(varname);
|
|
} else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
|
|
name = Z_STR_P(varname);
|
|
zend_string_addref(name);
|
|
} else {
|
|
name = zval_get_string(varname);
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
retval = zend_std_get_static_property(ce, name, 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
retval = zend_hash_find(target_symbol_table, name);
|
|
if (retval == NULL) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
/* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
|
|
} else if (Z_TYPE_P(retval) == IS_INDIRECT) {
|
|
retval = Z_INDIRECT_P(retval);
|
|
if (Z_TYPE_P(retval) == IS_UNDEF) {
|
|
switch (type) {
|
|
case BP_VAR_R:
|
|
case BP_VAR_UNSET:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_IS:
|
|
retval = &EG(uninitialized_zval);
|
|
break;
|
|
case BP_VAR_RW:
|
|
zend_error(E_NOTICE,"Undefined variable: %s", name->val);
|
|
/* break missing intentionally */
|
|
case BP_VAR_W:
|
|
ZVAL_NULL(retval);
|
|
break;
|
|
EMPTY_SWITCH_DEFAULT_CASE()
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) {
|
|
if (Z_CONSTANT_P(retval)) {
|
|
zval_update_constant(retval, 1);
|
|
}
|
|
} else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
}
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
zend_string_release(name);
|
|
}
|
|
|
|
ZEND_ASSERT(retval != NULL);
|
|
if (type == BP_VAR_R || type == BP_VAR_IS) {
|
|
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
|
|
ZVAL_UNREF(retval);
|
|
}
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
} else {
|
|
ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_RW, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
|
|
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
} else {
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_UNSET, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval tmp, *varname;
|
|
HashTable *target_symbol_table;
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
|
|
IS_UNUSED == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
zval *var = EX_VAR(opline->op1.var);
|
|
|
|
if (Z_REFCOUNTED_P(var)) {
|
|
zend_refcounted *garbage = Z_COUNTED_P(var);
|
|
|
|
if (!--GC_REFCOUNT(garbage)) {
|
|
ZVAL_UNDEF(var);
|
|
_zval_dtor_func_for_ptr(garbage ZEND_FILE_LINE_CC);
|
|
} else {
|
|
GC_ZVAL_CHECK_POSSIBLE_ROOT(var);
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
} else {
|
|
ZVAL_UNDEF(var);
|
|
}
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
zend_std_unset_static_property(ce, Z_STR_P(varname), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *value;
|
|
|
|
SAVE_OPLINE();
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
|
|
IS_UNUSED == IS_UNUSED &&
|
|
(opline->extended_value & ZEND_QUICK_SET)) {
|
|
value = EX_VAR(opline->op1.var);
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!i_zend_is_true(value));
|
|
CHECK_EXCEPTION();
|
|
}
|
|
ZEND_VM_NEXT_OPCODE();
|
|
} else {
|
|
zend_free_op free_op1;
|
|
zval tmp, *varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
ZVAL_UNDEF(&tmp);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
|
|
ZVAL_STR(&tmp, zval_get_string(varname));
|
|
varname = &tmp;
|
|
}
|
|
|
|
if (IS_UNUSED != IS_UNUSED) {
|
|
zend_class_entry *ce;
|
|
|
|
if (IS_UNUSED == IS_CONST) {
|
|
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
|
|
ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
|
|
} else {
|
|
ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, 0);
|
|
if (UNEXPECTED(ce == NULL)) {
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
|
|
}
|
|
} else {
|
|
ce = Z_CE_P(EX_VAR(opline->op2.var));
|
|
}
|
|
value = zend_std_get_static_property(ce, Z_STR_P(varname), 1, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(varname)) : NULL));
|
|
} else {
|
|
HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
|
|
value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
|
|
}
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
|
|
zend_string_release(Z_STR(tmp));
|
|
}
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
value && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL));
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
ZVAL_BOOL(EX_VAR(opline->result.var),
|
|
!value || !i_zend_is_true(value));
|
|
}
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_free_op free_op1;
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if (IS_CV != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if (IS_CV != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if (IS_CV == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
isset_dim_obj_again:
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if (IS_CV != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if (IS_CV & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_add_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_sub_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mul_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_div_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
fast_mod_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
shift_left_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
shift_right_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
concat_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_not_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_is_smaller_or_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_or_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_and_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
bitwise_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
boolean_xor_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1;
|
|
zval *container;
|
|
zend_free_op free_op2;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
} else {
|
|
goto fetch_obj_is_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) {
|
|
fetch_obj_is_no_object:
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
} else {
|
|
zval *retval;
|
|
|
|
/* here we are sure we are dealing with an object */
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(Z_OBJCE_P(container) == CACHED_PTR(Z_CACHE_SLOT_P(offset)))) {
|
|
zend_property_info *prop_info = CACHED_PTR(Z_CACHE_SLOT_P(offset) + 1);
|
|
zend_object *zobj = Z_OBJ_P(container);
|
|
|
|
if (EXPECTED(prop_info)) {
|
|
retval = OBJ_PROP(zobj, prop_info->offset);
|
|
if (EXPECTED(Z_TYPE_P(retval) != IS_UNDEF)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
} else if (EXPECTED(zobj->properties != NULL)) {
|
|
retval = zend_hash_find(zobj->properties, Z_STR_P(offset));
|
|
if (EXPECTED(retval)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL), EX_VAR(opline->result.var));
|
|
|
|
if (retval != EX_VAR(opline->result.var)) {
|
|
ZVAL_COPY(EX_VAR(opline->result.var), retval);
|
|
}
|
|
} while (0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zval *function_name;
|
|
zend_free_op free_op1, free_op2;
|
|
zval *object;
|
|
zend_function *fbc;
|
|
zend_class_entry *called_scope;
|
|
zend_object *obj;
|
|
|
|
SAVE_OPLINE();
|
|
|
|
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
|
|
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
zend_error_noreturn(E_ERROR, "Method name must be a string");
|
|
}
|
|
|
|
object = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
|
|
do {
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
|
|
uint32_t nesting = 1;
|
|
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(object)) {
|
|
object = Z_REFVAL_P(object);
|
|
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED(EG(exception) != NULL)) {
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
zend_error(E_RECOVERABLE_ERROR, "Call to a member function %s() on %s", Z_STRVAL_P(function_name), zend_get_type_by_const(Z_TYPE_P(object)));
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
if (EG(exception) != NULL) {
|
|
HANDLE_EXCEPTION();
|
|
}
|
|
|
|
/* No exception raised: Skip over arguments until fcall opcode with correct
|
|
* nesting level. Return NULL (except when return value unused) */
|
|
do {
|
|
opline++;
|
|
if (opline->opcode == ZEND_INIT_FCALL ||
|
|
opline->opcode == ZEND_INIT_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME ||
|
|
opline->opcode == ZEND_INIT_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
|
|
opline->opcode == ZEND_INIT_USER_CALL ||
|
|
opline->opcode == ZEND_NEW
|
|
) {
|
|
nesting++;
|
|
} else if (opline->opcode == ZEND_DO_FCALL) {
|
|
nesting--;
|
|
}
|
|
} while (nesting);
|
|
|
|
if (RETURN_VALUE_USED(opline)) {
|
|
ZVAL_NULL(EX_VAR(opline->result.var));
|
|
}
|
|
|
|
/* We've skipped EXT_FCALL_BEGIND, so also skip the ending opcode */
|
|
if ((opline + 1)->opcode == ZEND_EXT_FCALL_END) {
|
|
opline++;
|
|
}
|
|
ZEND_VM_JMP(++opline);
|
|
}
|
|
} while (0);
|
|
|
|
obj = Z_OBJ_P(object);
|
|
called_scope = obj->ce;
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST ||
|
|
EXPECTED((fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope)) == NULL)) {
|
|
zend_object *orig_obj = obj;
|
|
|
|
if (UNEXPECTED(obj->handlers->get_method == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Object does not support method calls");
|
|
}
|
|
|
|
/* First, locate the function. */
|
|
fbc = obj->handlers->get_method(&obj, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
|
|
if (UNEXPECTED(fbc == NULL)) {
|
|
zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", obj->ce->name->val, Z_STRVAL_P(function_name));
|
|
}
|
|
if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
|
|
EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
|
|
EXPECTED((fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_NEVER_CACHE)) == 0) &&
|
|
EXPECTED(obj == orig_obj)) {
|
|
CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), called_scope, fbc);
|
|
}
|
|
}
|
|
|
|
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
|
|
obj = NULL;
|
|
} else {
|
|
GC_REFCOUNT(obj)++; /* For $this pointer */
|
|
}
|
|
|
|
EX(call) = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
|
|
fbc, opline->extended_value, called_scope, obj, EX(call));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *result = EX_VAR(opline->result.var);
|
|
|
|
SAVE_OPLINE();
|
|
fast_equal_function(result,
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
int result;
|
|
zend_ulong hval;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
isset_dim_obj_again:
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
|
|
HashTable *ht = Z_ARRVAL_P(container);
|
|
zval *value;
|
|
zend_string *str;
|
|
|
|
isset_again:
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
|
|
str = Z_STR_P(offset);
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
|
|
if (ZEND_HANDLE_NUMERIC(str, hval)) {
|
|
goto num_index_prop;
|
|
}
|
|
}
|
|
str_index_prop:
|
|
value = zend_hash_find_ind(ht, str);
|
|
} else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
hval = Z_LVAL_P(offset);
|
|
num_index_prop:
|
|
value = zend_hash_index_find(ht, hval);
|
|
} else {
|
|
switch (Z_TYPE_P(offset)) {
|
|
case IS_DOUBLE:
|
|
hval = zend_dval_to_lval(Z_DVAL_P(offset));
|
|
goto num_index_prop;
|
|
case IS_NULL:
|
|
str = STR_EMPTY_ALLOC();
|
|
goto str_index_prop;
|
|
case IS_FALSE:
|
|
hval = 0;
|
|
goto num_index_prop;
|
|
case IS_TRUE:
|
|
hval = 1;
|
|
goto num_index_prop;
|
|
case IS_RESOURCE:
|
|
hval = Z_RES_HANDLE_P(offset);
|
|
goto num_index_prop;
|
|
case IS_REFERENCE:
|
|
offset = Z_REFVAL_P(offset);
|
|
goto isset_again;
|
|
default:
|
|
zend_error(E_WARNING, "Illegal offset type in isset or empty");
|
|
value = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (opline->extended_value & ZEND_ISSET) {
|
|
/* > IS_NULL means not IS_UNDEF and not IS_NULL */
|
|
result = value != NULL && Z_TYPE_P(value) > IS_NULL &&
|
|
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
|
|
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
|
|
result = (value == NULL || !i_zend_is_true(value));
|
|
}
|
|
} else if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
|
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
|
|
result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
zend_error(E_NOTICE, "Trying to check element of non-array");
|
|
result = 0;
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
|
|
zval tmp;
|
|
|
|
result = 0;
|
|
if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
|
|
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
|
|
ZVAL_DEREF(offset);
|
|
}
|
|
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|
|
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
|
|
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
|
|
ZVAL_DUP(&tmp, offset);
|
|
convert_to_long(&tmp);
|
|
offset = &tmp;
|
|
}
|
|
}
|
|
if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
|
|
if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
|
|
if ((opline->extended_value & ZEND_ISSET) ||
|
|
Z_STRVAL_P(container)[offset->value.lval] != '0') {
|
|
result = 1;
|
|
}
|
|
}
|
|
}
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
} else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
goto isset_dim_obj_again;
|
|
} else {
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
zval *container;
|
|
int result;
|
|
zval *offset;
|
|
|
|
SAVE_OPLINE();
|
|
container = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
|
|
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
|
|
|
|
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
|
container = Z_REFVAL_P(container);
|
|
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
|
|
goto isset_no_object;
|
|
}
|
|
} else {
|
|
goto isset_no_object;
|
|
}
|
|
}
|
|
if (UNEXPECTED(!Z_OBJ_HT_P(container)->has_property)) {
|
|
zend_error(E_NOTICE, "Trying to check property of non-object");
|
|
isset_no_object:
|
|
result = ((opline->extended_value & ZEND_ISSET) == 0);
|
|
} else {
|
|
result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_RUN_TIME_CACHE() + Z_CACHE_SLOT_P(offset)) : NULL));
|
|
if ((opline->extended_value & ZEND_ISSET) == 0) {
|
|
result = !result;
|
|
}
|
|
}
|
|
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
ZVAL_BOOL(EX_VAR(opline->result.var), result);
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
USE_OPLINE
|
|
zend_free_op free_op1, free_op2;
|
|
|
|
SAVE_OPLINE();
|
|
pow_function(EX_VAR(opline->result.var),
|
|
_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
|
|
_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
|
|
zval_ptr_dtor_nogc(free_op1);
|
|
zval_ptr_dtor_nogc(free_op2);
|
|
CHECK_EXCEPTION();
|
|
ZEND_VM_NEXT_OPCODE();
|
|
}
|
|
|
|
static int ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type);
|
|
ZEND_VM_NEXT_OPCODE(); /* Never reached */
|
|
}
|
|
|
|
|
|
void zend_init_opcodes_handlers(void)
|
|
{
|
|
static const opcode_handler_t labels[] = {
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_NOP_SPEC_HANDLER,
|
|
ZEND_ADD_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_SPEC_CONST_CV_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ADD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ADD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_SPEC_CV_CV_HANDLER,
|
|
ZEND_SUB_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_SUB_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_SUB_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SUB_SPEC_CONST_CV_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SUB_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SUB_SPEC_CV_CONST_HANDLER,
|
|
ZEND_SUB_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_SUB_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SUB_SPEC_CV_CV_HANDLER,
|
|
ZEND_MUL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_MUL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_MUL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MUL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MUL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MUL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_MUL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_MUL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MUL_SPEC_CV_CV_HANDLER,
|
|
ZEND_DIV_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DIV_SPEC_CONST_CV_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DIV_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DIV_SPEC_CV_CONST_HANDLER,
|
|
ZEND_DIV_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_DIV_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DIV_SPEC_CV_CV_HANDLER,
|
|
ZEND_MOD_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MOD_SPEC_CONST_CV_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MOD_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MOD_SPEC_CV_CONST_HANDLER,
|
|
ZEND_MOD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_MOD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_MOD_SPEC_CV_CV_HANDLER,
|
|
ZEND_SL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_SL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_SL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_SL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_SL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SL_SPEC_CV_CV_HANDLER,
|
|
ZEND_SR_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_SR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_SR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SR_SPEC_CONST_CV_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_SR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_SR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SR_SPEC_CV_CV_HANDLER,
|
|
ZEND_CONCAT_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONCAT_SPEC_CONST_CV_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONCAT_SPEC_CV_CONST_HANDLER,
|
|
ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONCAT_SPEC_CV_CV_HANDLER,
|
|
ZEND_BW_OR_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_OR_SPEC_CONST_CV_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_OR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_OR_SPEC_CV_CV_HANDLER,
|
|
ZEND_BW_AND_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_AND_SPEC_CONST_CV_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_AND_SPEC_CV_CONST_HANDLER,
|
|
ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_AND_SPEC_CV_CV_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CONST_CV_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_XOR_SPEC_CV_CV_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BW_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BW_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_NOT_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER,
|
|
ZEND_CAST_SPEC_CONST_HANDLER,
|
|
ZEND_CAST_SPEC_CONST_HANDLER,
|
|
ZEND_CAST_SPEC_CONST_HANDLER,
|
|
ZEND_CAST_SPEC_CONST_HANDLER,
|
|
ZEND_CAST_SPEC_CONST_HANDLER,
|
|
ZEND_CAST_SPEC_TMP_HANDLER,
|
|
ZEND_CAST_SPEC_TMP_HANDLER,
|
|
ZEND_CAST_SPEC_TMP_HANDLER,
|
|
ZEND_CAST_SPEC_TMP_HANDLER,
|
|
ZEND_CAST_SPEC_TMP_HANDLER,
|
|
ZEND_CAST_SPEC_VAR_HANDLER,
|
|
ZEND_CAST_SPEC_VAR_HANDLER,
|
|
ZEND_CAST_SPEC_VAR_HANDLER,
|
|
ZEND_CAST_SPEC_VAR_HANDLER,
|
|
ZEND_CAST_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CAST_SPEC_CV_HANDLER,
|
|
ZEND_CAST_SPEC_CV_HANDLER,
|
|
ZEND_CAST_SPEC_CV_HANDLER,
|
|
ZEND_CAST_SPEC_CV_HANDLER,
|
|
ZEND_CAST_SPEC_CV_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CONST_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CONST_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CONST_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CONST_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CONST_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_TMP_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_TMP_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_TMP_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_TMP_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_TMP_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_VAR_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_VAR_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_VAR_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_VAR_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CV_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CV_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CV_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CV_HANDLER,
|
|
ZEND_QM_ASSIGN_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_ADD_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SUB_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_MUL_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_DIV_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_MOD_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SL_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_SR_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_CONCAT_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_OR_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_AND_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_INC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_INC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_INC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_INC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_INC_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_INC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_INC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_INC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_INC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_INC_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_CV_HANDLER,
|
|
ZEND_PRE_DEC_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_INC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_INC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_INC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_INC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_INC_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_INC_SPEC_CV_HANDLER,
|
|
ZEND_POST_INC_SPEC_CV_HANDLER,
|
|
ZEND_POST_INC_SPEC_CV_HANDLER,
|
|
ZEND_POST_INC_SPEC_CV_HANDLER,
|
|
ZEND_POST_INC_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_POST_DEC_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_DEC_SPEC_CV_HANDLER,
|
|
ZEND_POST_DEC_SPEC_CV_HANDLER,
|
|
ZEND_POST_DEC_SPEC_CV_HANDLER,
|
|
ZEND_POST_DEC_SPEC_CV_HANDLER,
|
|
ZEND_POST_DEC_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER,
|
|
ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_SPEC_CV_TMP_HANDLER,
|
|
ZEND_ASSIGN_SPEC_CV_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER,
|
|
ZEND_ECHO_SPEC_CONST_HANDLER,
|
|
ZEND_ECHO_SPEC_CONST_HANDLER,
|
|
ZEND_ECHO_SPEC_CONST_HANDLER,
|
|
ZEND_ECHO_SPEC_CONST_HANDLER,
|
|
ZEND_ECHO_SPEC_CONST_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_ECHO_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ECHO_SPEC_CV_HANDLER,
|
|
ZEND_ECHO_SPEC_CV_HANDLER,
|
|
ZEND_ECHO_SPEC_CV_HANDLER,
|
|
ZEND_ECHO_SPEC_CV_HANDLER,
|
|
ZEND_ECHO_SPEC_CV_HANDLER,
|
|
ZEND_PRINT_SPEC_CONST_HANDLER,
|
|
ZEND_PRINT_SPEC_CONST_HANDLER,
|
|
ZEND_PRINT_SPEC_CONST_HANDLER,
|
|
ZEND_PRINT_SPEC_CONST_HANDLER,
|
|
ZEND_PRINT_SPEC_CONST_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_PRINT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRINT_SPEC_CV_HANDLER,
|
|
ZEND_PRINT_SPEC_CV_HANDLER,
|
|
ZEND_PRINT_SPEC_CV_HANDLER,
|
|
ZEND_PRINT_SPEC_CV_HANDLER,
|
|
ZEND_PRINT_SPEC_CV_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMP_SPEC_HANDLER,
|
|
ZEND_JMPZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_JMPZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZNZ_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CONST_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_JMPNZ_EX_SPEC_CV_HANDLER,
|
|
ZEND_CASE_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CASE_SPEC_CONST_CV_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CASE_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CASE_SPEC_CV_CONST_HANDLER,
|
|
ZEND_CASE_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_CASE_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CASE_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BRK_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BRK_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BRK_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BRK_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BRK_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CONT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_SPEC_CONST_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_BOOL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BOOL_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_SPEC_CV_HANDLER,
|
|
ZEND_BOOL_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_CHAR_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_STRING_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_STRING_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_VAR_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_ADD_VAR_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_VAR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ADD_VAR_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_VAR_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_BEGIN_SILENCE_SPEC_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_END_SILENCE_SPEC_TMP_HANDLER,
|
|
ZEND_END_SILENCE_SPEC_TMP_HANDLER,
|
|
ZEND_END_SILENCE_SPEC_TMP_HANDLER,
|
|
ZEND_END_SILENCE_SPEC_TMP_HANDLER,
|
|
ZEND_END_SILENCE_SPEC_TMP_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_DO_FCALL_SPEC_HANDLER,
|
|
ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_FCALL_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_RETURN_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_RETURN_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_SPEC_CV_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_SPEC_HANDLER,
|
|
ZEND_RECV_INIT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_RECV_INIT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_RECV_INIT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_RECV_INIT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_RECV_INIT_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_SPEC_TMP_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_EX_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_REF_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_REF_SPEC_CV_HANDLER,
|
|
ZEND_NEW_SPEC_CONST_HANDLER,
|
|
ZEND_NEW_SPEC_CONST_HANDLER,
|
|
ZEND_NEW_SPEC_CONST_HANDLER,
|
|
ZEND_NEW_SPEC_CONST_HANDLER,
|
|
ZEND_NEW_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NEW_SPEC_VAR_HANDLER,
|
|
ZEND_NEW_SPEC_VAR_HANDLER,
|
|
ZEND_NEW_SPEC_VAR_HANDLER,
|
|
ZEND_NEW_SPEC_VAR_HANDLER,
|
|
ZEND_NEW_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FREE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
|
|
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER,
|
|
ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CONST_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CONST_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CONST_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CONST_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CONST_HANDLER,
|
|
ZEND_FE_RESET_SPEC_TMP_HANDLER,
|
|
ZEND_FE_RESET_SPEC_TMP_HANDLER,
|
|
ZEND_FE_RESET_SPEC_TMP_HANDLER,
|
|
ZEND_FE_RESET_SPEC_TMP_HANDLER,
|
|
ZEND_FE_RESET_SPEC_TMP_HANDLER,
|
|
ZEND_FE_RESET_SPEC_VAR_HANDLER,
|
|
ZEND_FE_RESET_SPEC_VAR_HANDLER,
|
|
ZEND_FE_RESET_SPEC_VAR_HANDLER,
|
|
ZEND_FE_RESET_SPEC_VAR_HANDLER,
|
|
ZEND_FE_RESET_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CV_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CV_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CV_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CV_HANDLER,
|
|
ZEND_FE_RESET_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FE_FETCH_SPEC_VAR_HANDLER,
|
|
ZEND_FE_FETCH_SPEC_VAR_HANDLER,
|
|
ZEND_FE_FETCH_SPEC_VAR_HANDLER,
|
|
ZEND_FE_FETCH_SPEC_VAR_HANDLER,
|
|
ZEND_FE_FETCH_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_EXIT_SPEC_CONST_HANDLER,
|
|
ZEND_EXIT_SPEC_CONST_HANDLER,
|
|
ZEND_EXIT_SPEC_CONST_HANDLER,
|
|
ZEND_EXIT_SPEC_CONST_HANDLER,
|
|
ZEND_EXIT_SPEC_CONST_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_TMPVAR_HANDLER,
|
|
ZEND_EXIT_SPEC_UNUSED_HANDLER,
|
|
ZEND_EXIT_SPEC_UNUSED_HANDLER,
|
|
ZEND_EXIT_SPEC_UNUSED_HANDLER,
|
|
ZEND_EXIT_SPEC_UNUSED_HANDLER,
|
|
ZEND_EXIT_SPEC_UNUSED_HANDLER,
|
|
ZEND_EXIT_SPEC_CV_HANDLER,
|
|
ZEND_EXIT_SPEC_CV_HANDLER,
|
|
ZEND_EXIT_SPEC_CV_HANDLER,
|
|
ZEND_EXIT_SPEC_CV_HANDLER,
|
|
ZEND_EXIT_SPEC_CV_HANDLER,
|
|
ZEND_FETCH_R_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_R_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_R_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_R_SPEC_CV_VAR_HANDLER,
|
|
ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_W_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_W_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_W_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_W_SPEC_CV_VAR_HANDLER,
|
|
ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER,
|
|
ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER,
|
|
ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER,
|
|
ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER,
|
|
ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER,
|
|
ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_GOTO_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_GOTO_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_GOTO_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_GOTO_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_GOTO_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_STMT_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_FCALL_END_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_EXT_NOP_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_TICKS_SPEC_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_NO_REF_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_CATCH_SPEC_CONST_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_THROW_SPEC_CONST_HANDLER,
|
|
ZEND_THROW_SPEC_CONST_HANDLER,
|
|
ZEND_THROW_SPEC_CONST_HANDLER,
|
|
ZEND_THROW_SPEC_CONST_HANDLER,
|
|
ZEND_THROW_SPEC_CONST_HANDLER,
|
|
ZEND_THROW_SPEC_TMP_HANDLER,
|
|
ZEND_THROW_SPEC_TMP_HANDLER,
|
|
ZEND_THROW_SPEC_TMP_HANDLER,
|
|
ZEND_THROW_SPEC_TMP_HANDLER,
|
|
ZEND_THROW_SPEC_TMP_HANDLER,
|
|
ZEND_THROW_SPEC_VAR_HANDLER,
|
|
ZEND_THROW_SPEC_VAR_HANDLER,
|
|
ZEND_THROW_SPEC_VAR_HANDLER,
|
|
ZEND_THROW_SPEC_VAR_HANDLER,
|
|
ZEND_THROW_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_THROW_SPEC_CV_HANDLER,
|
|
ZEND_THROW_SPEC_CV_HANDLER,
|
|
ZEND_THROW_SPEC_CV_HANDLER,
|
|
ZEND_THROW_SPEC_CV_HANDLER,
|
|
ZEND_THROW_SPEC_CV_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CONST_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CV_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CONST_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CV_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CONST_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CV_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CONST_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CV_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CONST_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER,
|
|
ZEND_FETCH_CLASS_SPEC_CV_HANDLER,
|
|
ZEND_CLONE_SPEC_CONST_HANDLER,
|
|
ZEND_CLONE_SPEC_CONST_HANDLER,
|
|
ZEND_CLONE_SPEC_CONST_HANDLER,
|
|
ZEND_CLONE_SPEC_CONST_HANDLER,
|
|
ZEND_CLONE_SPEC_CONST_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_TMPVAR_HANDLER,
|
|
ZEND_CLONE_SPEC_UNUSED_HANDLER,
|
|
ZEND_CLONE_SPEC_UNUSED_HANDLER,
|
|
ZEND_CLONE_SPEC_UNUSED_HANDLER,
|
|
ZEND_CLONE_SPEC_UNUSED_HANDLER,
|
|
ZEND_CLONE_SPEC_UNUSED_HANDLER,
|
|
ZEND_CLONE_SPEC_CV_HANDLER,
|
|
ZEND_CLONE_SPEC_CV_HANDLER,
|
|
ZEND_CLONE_SPEC_CV_HANDLER,
|
|
ZEND_CLONE_SPEC_CV_HANDLER,
|
|
ZEND_CLONE_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
|
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER,
|
|
ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_CV_HANDLER,
|
|
ZEND_SEND_VAR_SPEC_CV_HANDLER,
|
|
ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_SEND_ARRAY_SPEC_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_USER_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_USER_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_USER_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_USER_SPEC_VAR_HANDLER,
|
|
ZEND_SEND_USER_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
|
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
|
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
|
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
|
ZEND_SEND_USER_SPEC_CV_HANDLER,
|
|
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
|
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
|
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
|
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
|
ZEND_STRLEN_SPEC_CONST_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_STRLEN_SPEC_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_STRLEN_SPEC_CV_HANDLER,
|
|
ZEND_STRLEN_SPEC_CV_HANDLER,
|
|
ZEND_STRLEN_SPEC_CV_HANDLER,
|
|
ZEND_STRLEN_SPEC_CV_HANDLER,
|
|
ZEND_STRLEN_SPEC_CV_HANDLER,
|
|
ZEND_DEFINED_SPEC_CONST_HANDLER,
|
|
ZEND_DEFINED_SPEC_CONST_HANDLER,
|
|
ZEND_DEFINED_SPEC_CONST_HANDLER,
|
|
ZEND_DEFINED_SPEC_CONST_HANDLER,
|
|
ZEND_DEFINED_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CONST_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CONST_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CONST_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CONST_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CONST_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_TMP_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_TMP_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_TMP_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_TMP_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_TMP_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_VAR_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_VAR_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_VAR_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_VAR_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CV_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CV_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CV_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CV_HANDLER,
|
|
ZEND_TYPE_CHECK_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_VAR_CV_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_VAR_CV_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_DECLARE_FUNCTION_SPEC_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_HANDLE_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_USER_OPCODE_SPEC_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CONST_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CONST_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CONST_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CONST_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CONST_HANDLER,
|
|
ZEND_JMP_SET_SPEC_TMP_HANDLER,
|
|
ZEND_JMP_SET_SPEC_TMP_HANDLER,
|
|
ZEND_JMP_SET_SPEC_TMP_HANDLER,
|
|
ZEND_JMP_SET_SPEC_TMP_HANDLER,
|
|
ZEND_JMP_SET_SPEC_TMP_HANDLER,
|
|
ZEND_JMP_SET_SPEC_VAR_HANDLER,
|
|
ZEND_JMP_SET_SPEC_VAR_HANDLER,
|
|
ZEND_JMP_SET_SPEC_VAR_HANDLER,
|
|
ZEND_JMP_SET_SPEC_VAR_HANDLER,
|
|
ZEND_JMP_SET_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CV_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CV_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CV_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CV_HANDLER,
|
|
ZEND_JMP_SET_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_ADD_TRAIT_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_BIND_TRAITS_SPEC_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
|
|
ZEND_YIELD_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_YIELD_SPEC_CONST_TMP_HANDLER,
|
|
ZEND_YIELD_SPEC_CONST_VAR_HANDLER,
|
|
ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER,
|
|
ZEND_YIELD_SPEC_CONST_CV_HANDLER,
|
|
ZEND_YIELD_SPEC_TMP_CONST_HANDLER,
|
|
ZEND_YIELD_SPEC_TMP_TMP_HANDLER,
|
|
ZEND_YIELD_SPEC_TMP_VAR_HANDLER,
|
|
ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER,
|
|
ZEND_YIELD_SPEC_TMP_CV_HANDLER,
|
|
ZEND_YIELD_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_YIELD_SPEC_VAR_TMP_HANDLER,
|
|
ZEND_YIELD_SPEC_VAR_VAR_HANDLER,
|
|
ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER,
|
|
ZEND_YIELD_SPEC_VAR_CV_HANDLER,
|
|
ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER,
|
|
ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER,
|
|
ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER,
|
|
ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER,
|
|
ZEND_YIELD_SPEC_UNUSED_CV_HANDLER,
|
|
ZEND_YIELD_SPEC_CV_CONST_HANDLER,
|
|
ZEND_YIELD_SPEC_CV_TMP_HANDLER,
|
|
ZEND_YIELD_SPEC_CV_VAR_HANDLER,
|
|
ZEND_YIELD_SPEC_CV_UNUSED_HANDLER,
|
|
ZEND_YIELD_SPEC_CV_CV_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_CALL_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_FAST_RET_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_RECV_VARIADIC_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_SEND_UNPACK_SPEC_HANDLER,
|
|
ZEND_POW_SPEC_CONST_CONST_HANDLER,
|
|
ZEND_POW_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_POW_SPEC_CONST_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POW_SPEC_CONST_CV_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_CONST_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POW_SPEC_TMPVAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POW_SPEC_CV_CONST_HANDLER,
|
|
ZEND_POW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_POW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_POW_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_VAR_CONST_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_VAR_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_VAR_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_CV_CONST_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_CV_TMPVAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_COALESCE_SPEC_CONST_HANDLER,
|
|
ZEND_COALESCE_SPEC_CONST_HANDLER,
|
|
ZEND_COALESCE_SPEC_CONST_HANDLER,
|
|
ZEND_COALESCE_SPEC_CONST_HANDLER,
|
|
ZEND_COALESCE_SPEC_CONST_HANDLER,
|
|
ZEND_COALESCE_SPEC_TMP_HANDLER,
|
|
ZEND_COALESCE_SPEC_TMP_HANDLER,
|
|
ZEND_COALESCE_SPEC_TMP_HANDLER,
|
|
ZEND_COALESCE_SPEC_TMP_HANDLER,
|
|
ZEND_COALESCE_SPEC_TMP_HANDLER,
|
|
ZEND_COALESCE_SPEC_VAR_HANDLER,
|
|
ZEND_COALESCE_SPEC_VAR_HANDLER,
|
|
ZEND_COALESCE_SPEC_VAR_HANDLER,
|
|
ZEND_COALESCE_SPEC_VAR_HANDLER,
|
|
ZEND_COALESCE_SPEC_VAR_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_NULL_HANDLER,
|
|
ZEND_COALESCE_SPEC_CV_HANDLER,
|
|
ZEND_COALESCE_SPEC_CV_HANDLER,
|
|
ZEND_COALESCE_SPEC_CV_HANDLER,
|
|
ZEND_COALESCE_SPEC_CV_HANDLER,
|
|
ZEND_COALESCE_SPEC_CV_HANDLER,
|
|
ZEND_NULL_HANDLER
|
|
};
|
|
zend_opcode_handlers = (opcode_handler_t*)labels;
|
|
}
|
|
static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op)
|
|
{
|
|
static const int zend_vm_decode[] = {
|
|
_UNUSED_CODE, /* 0 */
|
|
_CONST_CODE, /* 1 = IS_CONST */
|
|
_TMP_CODE, /* 2 = IS_TMP_VAR */
|
|
_UNUSED_CODE, /* 3 */
|
|
_VAR_CODE, /* 4 = IS_VAR */
|
|
_UNUSED_CODE, /* 5 */
|
|
_UNUSED_CODE, /* 6 */
|
|
_UNUSED_CODE, /* 7 */
|
|
_UNUSED_CODE, /* 8 = IS_UNUSED */
|
|
_UNUSED_CODE, /* 9 */
|
|
_UNUSED_CODE, /* 10 */
|
|
_UNUSED_CODE, /* 11 */
|
|
_UNUSED_CODE, /* 12 */
|
|
_UNUSED_CODE, /* 13 */
|
|
_UNUSED_CODE, /* 14 */
|
|
_UNUSED_CODE, /* 15 */
|
|
_CV_CODE /* 16 = IS_CV */
|
|
};
|
|
return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]];
|
|
}
|
|
|
|
ZEND_API void zend_vm_set_opcode_handler(zend_op* op)
|
|
{
|
|
op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op);
|
|
}
|
|
|
|
ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS)
|
|
{
|
|
return ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
|
}
|
|
|