diff --git a/Zend/tests/024.phpt b/Zend/tests/024.phpt index ff35a5c895f13..f89c49e61380a 100644 --- a/Zend/tests/024.phpt +++ b/Zend/tests/024.phpt @@ -11,7 +11,7 @@ var_dump($a++); var_dump(++$b); var_dump($a->$b); var_dump($a->$b); -var_dump($a->$b->$c[1]); +var_dump($a->$b->{$c[1]}); ?> --EXPECTF-- diff --git a/Zend/tests/bug27669.phpt b/Zend/tests/bug27669.phpt index 4d513e91aa24b..43591a938614a 100644 --- a/Zend/tests/bug27669.phpt +++ b/Zend/tests/bug27669.phpt @@ -10,7 +10,7 @@ Bug #27669 (PHP 5 didn't support all possibilities for calling static methods dy } } $y[0] = 'hello'; - A::$y[0](); + A::{$y[0]}(); ?> ===DONE=== --EXPECTF-- diff --git a/Zend/tests/isset_003.phpt b/Zend/tests/isset_003.phpt index 4db42a933b6b7..92225b59066bb 100644 --- a/Zend/tests/isset_003.phpt +++ b/Zend/tests/isset_003.phpt @@ -14,7 +14,7 @@ var_dump(isset($a[0]->a)); var_dump(isset($c[0][1][2]->a->b->c->d)); -var_dump(isset(${$a}->{$b->$c[$d]})); +var_dump(isset(${$a}->{$b->{$c[$d]}})); var_dump(isset($GLOBALS)); diff --git a/Zend/tests/isset_003_2_4.phpt b/Zend/tests/isset_003_2_4.phpt index c05f3e26f4c1a..42d8cc6a089de 100644 --- a/Zend/tests/isset_003_2_4.phpt +++ b/Zend/tests/isset_003_2_4.phpt @@ -16,7 +16,7 @@ var_dump(isset($a[0]->a)); var_dump(isset($c[0][1][2]->a->b->c->d)); -var_dump(isset(${$a}->{$b->$c[$d]})); +var_dump(isset(${$a}->{$b->{$c[$d]}})); var_dump(isset($GLOBALS)); diff --git a/Zend/tests/varSyntax/globalNonSimpleVariableError.phpt b/Zend/tests/varSyntax/globalNonSimpleVariableError.phpt new file mode 100644 index 0000000000000..ed04921f89470 --- /dev/null +++ b/Zend/tests/varSyntax/globalNonSimpleVariableError.phpt @@ -0,0 +1,10 @@ +--TEST-- +Global keyword only accepts simple variables +--FILE-- +bar; + +?> +--EXPECTF-- +Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR), expecting ',' or ';' in %s on line %d diff --git a/Zend/tests/varSyntax/indirectFcall.phpt b/Zend/tests/varSyntax/indirectFcall.phpt new file mode 100644 index 0000000000000..4cc5c1171a993 --- /dev/null +++ b/Zend/tests/varSyntax/indirectFcall.phpt @@ -0,0 +1,53 @@ +--TEST-- +Indirect function calls +--FILE-- + 'id', 'b' => 'udef'])->a)()()()()('var_dump')(6); + +$id = function($x) { return $x; }; + +$id($id)('var_dump')(7); + +(function($x) { return $x; })('id')('var_dump')(8); + +($f = function($x = null) use (&$f) { + return $x ?: $f; +})()()()('var_dump')(9); + +class Test { + public static function id($x = [__CLASS__, 'id']) { return $x; } +} + +$obj = new Test; +[$obj, 'id']()('id')($id)('var_dump')(10); +['Test', 'id']()()('var_dump')(11); +'id'()('id')('var_dump')(12); +('i' . 'd')()('var_dump')(13); + +?> +--EXPECT-- +int(0) +int(1) +int(2) +int(3) +int(4) +int(5) +int(6) +int(7) +int(8) +int(9) +int(10) +int(11) +int(12) +int(13) diff --git a/Zend/tests/varSyntax/issetOnTemp.phpt b/Zend/tests/varSyntax/issetOnTemp.phpt new file mode 100644 index 0000000000000..cd7bc006cde8b --- /dev/null +++ b/Zend/tests/varSyntax/issetOnTemp.phpt @@ -0,0 +1,26 @@ +--TEST-- +isset() can be used on dereferences of temporary expressions +--FILE-- + 'b'])->a)); +var_dump(isset(['a' => 'b']->a)); +var_dump(isset("str"->a)); +var_dump(isset((['a' => 'b'] + [])->a)); +var_dump(isset((['a' => 'b'] + [])->a->b)); + +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(false) +bool(false) +bool(false) +bool(false) diff --git a/Zend/tests/varSyntax/newVariable.phpt b/Zend/tests/varSyntax/newVariable.phpt new file mode 100644 index 0000000000000..360f99ac36b68 --- /dev/null +++ b/Zend/tests/varSyntax/newVariable.phpt @@ -0,0 +1,39 @@ +--TEST-- +Variable as class name for new expression +--FILE-- + 'stdClass']; +$obj = (object) ['className' => 'stdClass']; + +class Test { + public static $className = 'stdClass'; +} +$test = 'Test'; +$weird = [0 => (object) ['foo' => 'Test']]; + +var_dump(new $className); +var_dump(new $array['className']); +var_dump(new $array{'className'}); +var_dump(new $obj->className); +var_dump(new Test::$className); +var_dump(new $test::$className); +var_dump(new $weird[0]->foo::$className); + +?> +--EXPECTF-- +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} +object(stdClass)#%d (0) { +} diff --git a/Zend/tests/varSyntax/parenthesesDeref.phpt b/Zend/tests/varSyntax/parenthesesDeref.phpt new file mode 100644 index 0000000000000..0ebfe9c5d7206 --- /dev/null +++ b/Zend/tests/varSyntax/parenthesesDeref.phpt @@ -0,0 +1,20 @@ +--TEST-- +Dereferencing expression parentheses +--FILE-- + 0, 'b' => 1])->b); + +$obj = (object) ['a' => 0, 'b' => ['var_dump', 1]]; +(clone $obj)->b[0](1); + +?> +--EXPECT-- +int(1) +int(1) +int(1) +int(1) diff --git a/Zend/tests/varSyntax/propertyOfStringError.phpt b/Zend/tests/varSyntax/propertyOfStringError.phpt new file mode 100644 index 0000000000000..85abc5849a7ff --- /dev/null +++ b/Zend/tests/varSyntax/propertyOfStringError.phpt @@ -0,0 +1,10 @@ +--TEST-- +Cannot take property of a string +--FILE-- +bar; + +?> +--EXPECTF-- +Notice: Trying to get property of non-object in %s on line %d diff --git a/Zend/tests/varSyntax/staticMember.phpt b/Zend/tests/varSyntax/staticMember.phpt new file mode 100644 index 0000000000000..22a1fa2b13215 --- /dev/null +++ b/Zend/tests/varSyntax/staticMember.phpt @@ -0,0 +1,37 @@ +--TEST-- +Static member access +--FILE-- + +--EXPECT-- +int(0) +int(0) +int(0) +int(0) +int(0) +int(0) +int(0) +int(1) +int(0) diff --git a/Zend/tests/varSyntax/tempDimFetchByRefError.phpt b/Zend/tests/varSyntax/tempDimFetchByRefError.phpt new file mode 100644 index 0000000000000..dbcac75ea9886 --- /dev/null +++ b/Zend/tests/varSyntax/tempDimFetchByRefError.phpt @@ -0,0 +1,11 @@ +--TEST-- +Passing a dimention fetch on a temporary by reference is not allowed +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use temporary expression in write context in %s on line %d diff --git a/Zend/tests/varSyntax/tempPropFetchByRefError.phpt b/Zend/tests/varSyntax/tempPropFetchByRefError.phpt new file mode 100644 index 0000000000000..f8298a936dca2 --- /dev/null +++ b/Zend/tests/varSyntax/tempPropFetchByRefError.phpt @@ -0,0 +1,11 @@ +--TEST-- +Passing a property fetch on a temporary by reference is not allowed +--FILE-- +prop); + +?> +--EXPECTF-- +Fatal error: Cannot use temporary expression in write context in %s on line %d diff --git a/Zend/tests/varSyntax/writeToTempExpr.phpt b/Zend/tests/varSyntax/writeToTempExpr.phpt new file mode 100644 index 0000000000000..daeaf2493811c --- /dev/null +++ b/Zend/tests/varSyntax/writeToTempExpr.phpt @@ -0,0 +1,10 @@ +--TEST-- +Writing to a temporary expression is not allowed +--FILE-- + +--EXPECTF-- +Fatal error: Cannot use temporary expression in write context in %s on line %d diff --git a/Zend/zend.c b/Zend/zend.c index 841fc38565cb4..aec5b331ee0ca 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1036,7 +1036,6 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ zend_stack function_call_stack; zend_stack switch_cond_stack; zend_stack foreach_copy_stack; - zend_stack object_stack; zend_stack declare_stack; zend_stack list_stack; zend_stack context_stack; @@ -1192,7 +1191,6 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ SAVE_STACK(function_call_stack); SAVE_STACK(switch_cond_stack); SAVE_STACK(foreach_copy_stack); - SAVE_STACK(object_stack); SAVE_STACK(declare_stack); SAVE_STACK(list_stack); SAVE_STACK(context_stack); @@ -1218,7 +1216,6 @@ ZEND_API void zend_error(int type, const char *format, ...) /* {{{ */ RESTORE_STACK(function_call_stack); RESTORE_STACK(switch_cond_stack); RESTORE_STACK(foreach_copy_stack); - RESTORE_STACK(object_stack); RESTORE_STACK(declare_stack); RESTORE_STACK(list_stack); RESTORE_STACK(context_stack); diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ea75c1503ae88..f5efd84144544 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -194,7 +194,6 @@ void zend_init_compiler_data_structures(TSRMLS_D) /* {{{ */ zend_stack_init(&CG(function_call_stack), sizeof(zend_function_call_entry)); zend_stack_init(&CG(switch_cond_stack), sizeof(zend_switch_entry)); zend_stack_init(&CG(foreach_copy_stack), sizeof(zend_op)); - zend_stack_init(&CG(object_stack), sizeof(znode)); zend_stack_init(&CG(declare_stack), sizeof(zend_declarables)); CG(active_class_entry) = NULL; zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0); @@ -242,7 +241,6 @@ void shutdown_compiler(TSRMLS_D) /* {{{ */ zend_stack_destroy(&CG(function_call_stack)); zend_stack_destroy(&CG(switch_cond_stack)); zend_stack_destroy(&CG(foreach_copy_stack)); - zend_stack_destroy(&CG(object_stack)); zend_stack_destroy(&CG(declare_stack)); zend_stack_destroy(&CG(list_stack)); zend_hash_destroy(&CG(filenames_table)); @@ -703,12 +701,10 @@ void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC) /* { } /* }}} */ -void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* {{{ */ +void zend_do_fetch_static_member(znode *result, znode *class_name, znode *member_name TSRMLS_DC) /* {{{ */ { znode class_node; zend_llist *fetch_list_ptr; - zend_llist_element *le; - zend_op *opline_ptr; zend_op opline; if (class_name->op_type == IS_CONST && @@ -718,65 +714,29 @@ void zend_do_fetch_static_member(znode *result, znode *class_name TSRMLS_DC) /* } else { zend_do_fetch_class(&class_node, class_name TSRMLS_CC); } + + zend_do_begin_variable_parse(TSRMLS_C); fetch_list_ptr = zend_stack_top(&CG(bp_stack)); - if (result->op_type == IS_CV) { - init_op(&opline TSRMLS_CC); + init_op(&opline TSRMLS_CC); - opline.opcode = ZEND_FETCH_W; - opline.result_type = IS_VAR; - opline.result.var = get_temporary_variable(CG(active_op_array)); - opline.op1_type = IS_CONST; - LITERAL_STR(opline.op1, STR_COPY(CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)])); + opline.opcode = ZEND_FETCH_W; + opline.result_type = IS_VAR; + opline.result.var = get_temporary_variable(CG(active_op_array)); + SET_NODE(opline.op1, member_name); + if (opline.op1_type == IS_CONST) { GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant); - if (class_node.op_type == IS_CONST) { - opline.op2_type = IS_CONST; - opline.op2.constant = - zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC); - } else { - SET_NODE(opline.op2, &class_node); - } - GET_NODE(result,opline.result); - opline.extended_value |= ZEND_FETCH_STATIC_MEMBER; - opline_ptr = &opline; - - zend_llist_add_element(fetch_list_ptr, &opline); + } + if (class_node.op_type == IS_CONST) { + opline.op2_type = IS_CONST; + opline.op2.constant = + zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC); } else { - le = fetch_list_ptr->head; - - opline_ptr = (zend_op *)le->data; - if (opline_ptr->opcode != ZEND_FETCH_W && opline_ptr->op1_type == IS_CV) { - init_op(&opline TSRMLS_CC); - opline.opcode = ZEND_FETCH_W; - opline.result_type = IS_VAR; - opline.result.var = get_temporary_variable(CG(active_op_array)); - opline.op1_type = IS_CONST; - LITERAL_STR(opline.op1, STR_COPY(CG(active_op_array)->vars[EX_VAR_TO_NUM(opline_ptr->op1.var)])); - GET_POLYMORPHIC_CACHE_SLOT(opline.op1.constant); - if (class_node.op_type == IS_CONST) { - opline.op2_type = IS_CONST; - opline.op2.constant = - zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC); - } else { - SET_NODE(opline.op2, &class_node); - } - opline.extended_value |= ZEND_FETCH_STATIC_MEMBER; - COPY_NODE(opline_ptr->op1, opline.result); - - zend_llist_prepend_element(fetch_list_ptr, &opline); - } else { - if (opline_ptr->op1_type == IS_CONST) { - GET_POLYMORPHIC_CACHE_SLOT(opline_ptr->op1.constant); - } - if (class_node.op_type == IS_CONST) { - opline_ptr->op2_type = IS_CONST; - opline_ptr->op2.constant = - zend_add_class_name_literal(CG(active_op_array), &class_node.u.constant TSRMLS_CC); - } else { - SET_NODE(opline_ptr->op2, &class_node); - } - opline_ptr->extended_value |= ZEND_FETCH_STATIC_MEMBER; - } + SET_NODE(opline.op2, &class_node); } + GET_NODE(result,opline.result); + opline.extended_value |= ZEND_FETCH_STATIC_MEMBER; + + zend_llist_add_element(fetch_list_ptr, &opline); } /* }}} */ @@ -1274,6 +1234,22 @@ void zend_do_begin_variable_parse(TSRMLS_D) /* {{{ */ } /* }}} */ +static zend_bool zend_can_parse_variable_for_write(znode *variable TSRMLS_DC) /* {{{ */ +{ + zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack)); + zend_llist_element *le = fetch_list_ptr->head; + for (le = fetch_list_ptr->head; le; le = le->next) { + zend_op *opline = (zend_op *) le->data; + if ((opline->opcode != ZEND_SEPARATE && opline->opcode != ZEND_FETCH_W) + && (opline->op1_type == IS_TMP_VAR || opline->op1_type == IS_CONST) + ) { + return 0; + } + } + return 1; +} +/* }}} */ + void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS_DC) /* {{{ */ { zend_llist *fetch_list_ptr = zend_stack_top(&CG(bp_stack)); @@ -1326,6 +1302,13 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS opline->op1_type = IS_CV; opline->op1.var = CG(active_op_array)->this_var; } + if (opline->opcode != ZEND_FETCH_W + && (opline->op1_type == IS_TMP_VAR || opline->op1_type == IS_CONST) + && (type != BP_VAR_R && type != BP_VAR_IS && type != BP_VAR_FUNC_ARG) + ) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use temporary expression in write context"); + } switch (type) { case BP_VAR_R: if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2_type == IS_UNUSED) { @@ -2001,35 +1984,22 @@ void zend_do_begin_method_call(znode *left_bracket TSRMLS_DC) /* {{{ */ zend_error_noreturn(E_COMPILE_ERROR, "Cannot call __clone() method on objects - use 'clone $obj' instead"); } - if (last_op->opcode == ZEND_FETCH_OBJ_R) { - if (last_op->op2_type == IS_CONST) { - zval name; - name = CONSTANT(last_op->op2.constant); - if (Z_TYPE(name) != IS_STRING) { - zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string"); - } - Z_STR(name) = STR_COPY(Z_STR(name)); - FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant); - last_op->op2.constant = - zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC); - GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant); - } - last_op->opcode = ZEND_INIT_METHOD_CALL; - last_op->result_type = IS_UNUSED; - last_op->result.num = CG(context).nested_calls; - Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME; - } else { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_INIT_FCALL_BY_NAME; - opline->result.num = CG(context).nested_calls; - SET_UNUSED(opline->op1); - if (left_bracket->op_type == IS_CONST) { - opline->op2_type = IS_CONST; - opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &left_bracket->u.constant TSRMLS_CC); - GET_CACHE_SLOT(opline->op2.constant); - } else { - SET_NODE(opline->op2, left_bracket); + /* Convert ZEND_FETCH_OBJ_R to ZEND_INIT_METHOD_CALL */ + last_op->opcode = ZEND_INIT_METHOD_CALL; + last_op->result_type = IS_UNUSED; + last_op->result.num = CG(context).nested_calls; + Z_LVAL(left_bracket->u.constant) = ZEND_INIT_FCALL_BY_NAME; + if (last_op->op2_type == IS_CONST) { + zval name; + name = CONSTANT(last_op->op2.constant); + if (Z_TYPE(name) != IS_STRING) { + zend_error_noreturn(E_COMPILE_ERROR, "Method name must be a string"); } + Z_STR(name) = STR_COPY(Z_STR(name)); + FREE_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant); + last_op->op2.constant = + zend_add_func_name_literal(CG(active_op_array), &name TSRMLS_CC); + GET_POLYMORPHIC_CACHE_SLOT(last_op->op2.constant); } zend_push_function_call_entry(NULL TSRMLS_CC); @@ -2071,7 +2041,7 @@ void zend_do_begin_dynamic_function_call(znode *function_name, int ns_call TSRML opline->opcode = ZEND_INIT_FCALL_BY_NAME; opline->result.num = CG(context).nested_calls; SET_UNUSED(opline->op1); - if (function_name->op_type == IS_CONST) { + if (function_name->op_type == IS_CONST && Z_TYPE(function_name->u.constant) == IS_STRING) { opline->op2_type = IS_CONST; opline->op2.constant = zend_add_func_name_literal(CG(active_op_array), &function_name->u.constant TSRMLS_CC); GET_CACHE_SLOT(opline->op2.constant); @@ -5594,22 +5564,6 @@ void zend_do_halt_compiler_register(TSRMLS_D) /* {{{ */ } /* }}} */ -void zend_do_push_object(const znode *object TSRMLS_DC) /* {{{ */ -{ - zend_stack_push(&CG(object_stack), object); -} -/* }}} */ - -void zend_do_pop_object(znode *object TSRMLS_DC) /* {{{ */ -{ - if (object) { - znode *tmp = zend_stack_top(&CG(object_stack)); - *object = *tmp; - } - zend_stack_del_top(&CG(object_stack)); -} -/* }}} */ - void zend_do_begin_new_object(znode *new_token, znode *class_type TSRMLS_DC) /* {{{ */ { zend_op *opline; @@ -6315,17 +6269,10 @@ void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC) /* { } /* }}} */ -void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC) /* {{{ */ +void zend_do_indirect_reference(znode *result, znode *variable TSRMLS_DC) /* {{{ */ { - int i; + fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC); - zend_do_end_variable_parse(variable, BP_VAR_R, 0 TSRMLS_CC); - for (i=1; iu.constant); i++) { - fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC); - *variable = *result; - } - zend_do_begin_variable_parse(TSRMLS_C); - fetch_simple_variable(result, variable, 1 TSRMLS_CC); /* there is a chance someone is accessing $this */ if (CG(active_op_array)->scope && CG(active_op_array)->this_var == -1) { zend_string *key = STR_INIT("this", sizeof("this")-1, 0); @@ -6449,18 +6396,19 @@ void zend_do_foreach_begin(znode *foreach_token, znode *open_brackets_token, zno zend_bool is_variable; zend_op dummy_opline; + open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array)); if (variable) { - if (zend_is_function_or_method_call(array)) { + if (zend_is_function_or_method_call(array) + || !zend_can_parse_variable_for_write(array TSRMLS_CC) + ) { is_variable = 0; + zend_do_end_variable_parse(array, BP_VAR_R, 0 TSRMLS_CC); } else { is_variable = 1; + zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC); } - /* save the location of FETCH_W instruction(s) */ - open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array)); - zend_do_end_variable_parse(array, BP_VAR_W, 0 TSRMLS_CC); } else { is_variable = 0; - open_brackets_token->u.op.opline_num = get_next_op_number(CG(active_op_array)); } /* save the location of FE_RESET */ @@ -6540,19 +6488,21 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token CG(active_op_array)->opcodes[foreach_token->u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE; } else { zend_op *fetch = &CG(active_op_array)->opcodes[foreach_token->u.op.opline_num]; - zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num]; - - /* Change "write context" into "read context" */ - fetch->extended_value = 0; /* reset ZEND_FE_RESET_VARIABLE */ - while (fetch != end) { - --fetch; - if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) { - zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); - } - if (fetch->opcode == ZEND_SEPARATE) { - MAKE_NOP(fetch); - } else { - fetch->opcode -= 3; /* FETCH_W -> FETCH_R */ + if (fetch->extended_value == ZEND_FE_RESET_VARIABLE) { + zend_op *end = &CG(active_op_array)->opcodes[open_brackets_token->u.op.opline_num]; + + /* Change "write context" into "read context" */ + fetch->extended_value = 0; /* reset ZEND_FE_RESET_VARIABLE */ + while (fetch != end) { + --fetch; + if (fetch->opcode == ZEND_FETCH_DIM_W && fetch->op2_type == IS_UNUSED) { + zend_error_noreturn(E_COMPILE_ERROR, "Cannot use [] for reading"); + } + if (fetch->opcode == ZEND_SEPARATE) { + MAKE_NOP(fetch); + } else { + fetch->opcode -= 3; /* FETCH_W -> FETCH_R */ + } } } } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 5b5397844ffdc..bb4142884d781 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -457,14 +457,14 @@ void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC); void zend_do_assign_ref(znode *result, znode *lvar, znode *rvar TSRMLS_DC); void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC); void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC); -void zend_do_indirect_references(znode *result, const znode *num_references, znode *variable TSRMLS_DC); +void zend_do_indirect_reference(znode *result, znode *variable TSRMLS_DC); void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC); void zend_do_fetch_global_variable(znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC); void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC); void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC); void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC); -void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC); +void zend_do_fetch_static_member(znode *result, znode *class_name, znode *member_name TSRMLS_DC); void zend_do_print(znode *result, znode *arg TSRMLS_DC); void zend_do_echo(znode *arg TSRMLS_DC); typedef int (*unary_op_type)(zval *, zval * TSRMLS_DC); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 2a29e337de5de..ee68a7be96cce 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -73,7 +73,7 @@ struct _zend_compiler_globals { zend_stack bp_stack; zend_stack switch_cond_stack; zend_stack foreach_copy_stack; - zend_stack object_stack; + zend_stack object_stack; /* TODO: remove */ zend_stack declare_stack; zend_class_entry *active_class_entry; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 43e20cd9ce5ed..013e3ddbf0b64 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -45,7 +45,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*); %} %pure_parser -%expect 3 +%expect 2 %code requires { #ifdef ZTS @@ -597,15 +597,12 @@ function_call_parameter: ; global_var_list: - global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); } - | global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); } + global_var_list ',' global_var + | global_var ; - global_var: - T_VARIABLE { $$ = $1; } - | '$' r_variable { $$ = $2; } - | '$' '{' expr '}' { $$ = $3; } + simple_variable { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL_LOCK TSRMLS_CC); } ; @@ -747,28 +744,6 @@ non_empty_for_expr: | expr { $$ = $1; } ; -chaining_method_or_property: - chaining_method_or_property variable_property { $$.EA = $2.EA; } - | variable_property { $$.EA = $1.EA; } -; - -chaining_dereference: - chaining_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - | '[' dim_offset ']' { zend_do_pop_object(&$1 TSRMLS_CC); fetch_array_dim(&$$, &$1, &$2 TSRMLS_CC); } -; - -chaining_instance_call: - chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); } chaining_method_or_property { $$ = $3; } - | chaining_dereference { zend_do_push_object(&$1 TSRMLS_CC); $$ = $1; } - | chaining_method_or_property { $$ = $1; } -; - -instance_call: - /* empty */ { $$ = $0; } - | { zend_do_push_object(&$0 TSRMLS_CC); zend_do_begin_variable_parse(TSRMLS_C); } - chaining_instance_call { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_end_variable_parse(&$2, BP_VAR_R, 0 TSRMLS_CC); } -; - new_expr: T_NEW class_name_reference { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} ; @@ -827,7 +802,6 @@ expr_without_variable: | expr T_INSTANCEOF class_name_reference { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); } | parenthesis_expr { $$ = $1; } | new_expr { $$ = $1; } - | '(' new_expr ')' { $$ = $2; } instance_call { $$ = $5; } | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); } expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); } @@ -844,8 +818,6 @@ expr_without_variable: | T_EXIT exit_expr { zend_do_exit(&$$, &$2 TSRMLS_CC); } | '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; } | scalar { $$ = $1; } - | combined_scalar_offset { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } - | combined_scalar { $$ = $1; } | '`' backticks_expr '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); } | T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); } | T_YIELD { zend_do_yield(&$$, NULL, NULL, 0 TSRMLS_CC); } @@ -864,15 +836,6 @@ yield_expr: | T_YIELD expr T_DOUBLE_ARROW variable { zend_do_yield(&$$, &$4, &$2, 1 TSRMLS_CC); } ; -combined_scalar_offset: - combined_scalar '[' dim_offset ']' { zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - | combined_scalar_offset '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - | T_CONSTANT_ENCAPSED_STRING '[' dim_offset ']' { $1.EA = 0; zend_do_begin_variable_parse(TSRMLS_C); fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - -combined_scalar: - T_ARRAY '(' array_pair_list ')' { $$ = $3; } - | '[' array_pair_list ']' { $$ = $2; } - function: T_FUNCTION { $$.u.op.opline_num = CG(zend_lineno); } ; @@ -896,15 +859,11 @@ function_call: function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } | T_NS_SEPARATOR namespace_name { $$.u.op.opline_num = zend_do_begin_function_call(&$2, 0 TSRMLS_CC); } function_call_parameter_list { zend_do_end_function_call(&$2, &$$, 0, $3.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } - | class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + | class_name T_PAAMAYIM_NEKUDOTAYIM member_name { $$.u.op.opline_num = zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list { zend_do_end_function_call($4.u.op.opline_num?NULL:&$3, &$$, $4.u.op.opline_num, $4.u.op.opline_num TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } - function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM member_name { zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { zend_do_end_variable_parse(&$3, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_class_member_function_call(&$1, &$3 TSRMLS_CC); } - function_call_parameter_list { zend_do_end_function_call(NULL, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } + | callable_expr { zend_do_begin_dynamic_function_call(&$1, 0 TSRMLS_CC); } function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 0, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} ; @@ -924,27 +883,8 @@ fully_qualified_class_name: class_name_reference: - class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } - | dynamic_class_name_reference { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } -; - - -dynamic_class_name_reference: - base_variable T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); } - object_property { zend_do_push_object(&$4 TSRMLS_CC); } dynamic_class_name_variable_properties - { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; } - | base_variable { $$ = $1; } -; - - -dynamic_class_name_variable_properties: - dynamic_class_name_variable_properties dynamic_class_name_variable_property - | /* empty */ -; - - -dynamic_class_name_variable_property: - T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } + class_name { zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } + | new_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); zend_do_fetch_class(&$$, &$1 TSRMLS_CC); } ; exit_expr: @@ -966,10 +906,15 @@ ctor_arguments: ; +dereferencable_scalar: + T_ARRAY '(' array_pair_list ')' { $$ = $3; } + | '[' array_pair_list ']' { $$ = $2; } + | T_CONSTANT_ENCAPSED_STRING { $$ = $1; } +; + common_scalar: T_LNUMBER { $$ = $1; } | T_DNUMBER { $$ = $1; } - | T_CONSTANT_ENCAPSED_STRING { $$ = $1; } | T_LINE { $$ = $1; } | T_FILE { $$ = $1; } | T_DIR { $$ = $1; } @@ -989,16 +934,21 @@ static_scalar: /* compile-time evaluated scalars */ static_scalar_value { zend_do_constant_expression(&$$, $1.u.ast TSRMLS_CC); } ; +static_scalar_base: + common_scalar { $$ = $1; } + | T_CONSTANT_ENCAPSED_STRING { $$ = $1; } + | T_CLASS_C { $$ = $1; } + | static_class_name_scalar { $$ = $1; } + | static_class_constant { $$ = $1; } + | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); } + | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); } + | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); } +; + static_scalar_value: - common_scalar { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } - | static_class_name_scalar { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } - | namespace_name { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT, 1 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } - | T_NAMESPACE T_NS_SEPARATOR namespace_name { $$.op_type = IS_CONST; ZVAL_EMPTY_STRING(&$$.u.constant); zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); $3 = $$; zend_do_fetch_constant(&$$, NULL, &$3, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } - | T_NS_SEPARATOR namespace_name { zval tmp; ZVAL_NEW_STR(&tmp, STR_ALLOC(Z_STRLEN($2.u.constant)+1, 0)); Z_STRVAL(tmp)[0] = '\\'; memcpy(Z_STRVAL(tmp) + 1, Z_STRVAL($2.u.constant), Z_STRLEN($2.u.constant)+1); if (Z_DELREF($2.u.constant) == 0) {efree(Z_STR($2.u.constant));} Z_STR($2.u.constant) = Z_STR(tmp); zend_do_fetch_constant(&$$, NULL, &$2, ZEND_CT, 0 TSRMLS_CC); $$.u.ast = zend_ast_create_constant(&$$.u.constant); } + static_scalar_base { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; } | '[' static_array_pair_list ']' { $$ = $2; } - | static_class_constant { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } - | T_CLASS_C { $$.u.ast = zend_ast_create_constant(&$1.u.constant); } | static_operation { $$ = $1; } ; @@ -1049,6 +999,7 @@ scalar: | '"' encaps_list '"' { $$ = $2; } | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; } | T_CLASS_C { if (Z_TYPE($1.u.constant) == IS_CONSTANT) {zend_do_fetch_constant(&$$, NULL, &$1, ZEND_RT, 1 TSRMLS_CC);} else {$$ = $1;} } + | dereferencable_scalar { $$ = $1; } ; @@ -1095,83 +1046,75 @@ rw_variable: zend_check_writable_variable(&$1); } ; -variable: - base_variable_with_function_calls T_OBJECT_OPERATOR { zend_do_push_object(&$1 TSRMLS_CC); } - object_property { zend_do_push_object(&$4 TSRMLS_CC); } method_or_not variable_properties - { zend_do_pop_object(&$$ TSRMLS_CC); $$.EA = $1.EA | ($7.EA ? $7.EA : $6.EA); } - | base_variable_with_function_calls { $$ = $1; } -; - -variable_properties: - variable_properties variable_property { $$.EA = $2.EA; } - | /* empty */ { $$.EA = 0; } -; - - -variable_property: - T_OBJECT_OPERATOR object_property { zend_do_push_object(&$2 TSRMLS_CC); } method_or_not { $$.EA = $4.EA; } -; - -array_method_dereference: - array_method_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - | method '[' dim_offset ']' { $1.EA = ZEND_PARSED_METHOD_CALL; fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } -; - -method: - { zend_do_pop_object(&$$ TSRMLS_CC); zend_do_begin_method_call(&$$ TSRMLS_CC); } - function_call_parameter_list { zend_do_end_function_call(&$1, &$$, 1, 1 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); } -; - -method_or_not: - method { $$ = $1; $$.EA = ZEND_PARSED_METHOD_CALL; zend_do_push_object(&$$ TSRMLS_CC); } - | array_method_dereference { $$ = $1; zend_do_push_object(&$$ TSRMLS_CC); } - | /* empty */ { $$.EA = ZEND_PARSED_MEMBER; } -; - -variable_without_objects: - reference_variable { $$ = $1; } - | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); } -; - -static_member: - class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); } - | variable_class_name T_PAAMAYIM_NEKUDOTAYIM variable_without_objects { $$ = $3; zend_do_fetch_static_member(&$$, &$1 TSRMLS_CC); } - -; - variable_class_name: - reference_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$=$1;; } + dereferencable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; } +; + +dereferencable: + variable { $$ = $1; } + | '(' expr ')' { $$ = $2; zend_do_begin_variable_parse(TSRMLS_C); $$.EA = 0; } + | dereferencable_scalar { $$ = $1; zend_do_begin_variable_parse(TSRMLS_C); $$.EA = 0; } +; + +callable_expr: + callable_variable { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); $$ = $1; } + | '(' expr ')' { $$ = $2; } + | dereferencable_scalar { $$ = $1; } +; + +callable_variable: + simple_variable + { zend_do_begin_variable_parse(TSRMLS_C); + fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); + $$.EA = ZEND_PARSED_VARIABLE; } + | dereferencable '[' dim_offset ']' + { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; } + | dereferencable '{' expr '}' + { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; } + | dereferencable T_OBJECT_OPERATOR member_name + { zend_do_fetch_property(&$$, &$1, &$3 TSRMLS_CC); + zend_do_begin_method_call(&$$ TSRMLS_CC); } + function_call_parameter_list + { zend_do_end_function_call(&$4, &$$, 1, 1 TSRMLS_CC); + zend_do_extended_fcall_end(TSRMLS_C); + $$.EA = ZEND_PARSED_METHOD_CALL; } + | function_call + { zend_do_begin_variable_parse(TSRMLS_C); + $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; } ; -array_function_dereference: - array_function_dereference '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - | function_call { zend_do_begin_variable_parse(TSRMLS_C); $1.EA = ZEND_PARSED_FUNCTION_CALL; } - '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$4 TSRMLS_CC); } +variable: + callable_variable { $$ = $1; } + | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; } + | dereferencable T_OBJECT_OPERATOR member_name + { zend_do_fetch_property(&$$, &$1, &$3 TSRMLS_CC); $$.EA = ZEND_PARSED_MEMBER; } ; -base_variable_with_function_calls: - base_variable { $$ = $1; } - | array_function_dereference { $$ = $1; } - | function_call { zend_do_begin_variable_parse(TSRMLS_C); $$ = $1; $$.EA = ZEND_PARSED_FUNCTION_CALL; } +simple_variable: + T_VARIABLE { $$ = $1; } + | '$' '{' expr '}' { $$ = $3; } + | '$' simple_variable { zend_do_indirect_reference(&$$, &$2 TSRMLS_CC); } ; +static_member: + class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { zend_do_fetch_static_member(&$$, &$1, &$3 TSRMLS_CC); } + | variable_class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable { zend_do_fetch_static_member(&$$, &$1, &$3 TSRMLS_CC); } -base_variable: - reference_variable { $$ = $1; $$.EA = ZEND_PARSED_VARIABLE; } - | simple_indirect_reference reference_variable { zend_do_indirect_references(&$$, &$1, &$2 TSRMLS_CC); $$.EA = ZEND_PARSED_VARIABLE; } - | static_member { $$ = $1; $$.EA = ZEND_PARSED_STATIC_MEMBER; } ; -reference_variable: - reference_variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - | reference_variable '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); } - | compound_variable { zend_do_begin_variable_parse(TSRMLS_C); fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); } -; - - -compound_variable: - T_VARIABLE { $$ = $1; } - | '$' '{' expr '}' { $$ = $3; } +new_variable: + simple_variable + { zend_do_begin_variable_parse(TSRMLS_C); + fetch_simple_variable(&$$, &$1, 1 TSRMLS_CC); } + | new_variable '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } + | new_variable '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); } + | new_variable T_OBJECT_OPERATOR member_name + { zend_do_fetch_property(&$$, &$1, &$3 TSRMLS_CC); } + | class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable + { zend_do_fetch_static_member(&$$, &$1, &$3 TSRMLS_CC); } + | new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable + { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); + zend_do_fetch_static_member(&$$, &$1, &$3 TSRMLS_CC); } ; dim_offset: @@ -1179,26 +1122,10 @@ dim_offset: | expr { $$ = $1; } ; - -object_property: - object_dim_list { $$ = $1; } - | variable_without_objects { zend_do_end_variable_parse(&$1, BP_VAR_R, 0 TSRMLS_CC); } { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);} -; - -object_dim_list: - object_dim_list '[' dim_offset ']' { fetch_array_dim(&$$, &$1, &$3 TSRMLS_CC); } - | object_dim_list '{' expr '}' { fetch_string_offset(&$$, &$1, &$3 TSRMLS_CC); } - | variable_name { znode tmp_znode; zend_do_pop_object(&tmp_znode TSRMLS_CC); zend_do_fetch_property(&$$, &tmp_znode, &$1 TSRMLS_CC);} -; - -variable_name: +member_name: T_STRING { $$ = $1; } | '{' expr '}' { $$ = $2; } -; - -simple_indirect_reference: - '$' { Z_LVAL($$.u.constant) = 1; } - | simple_indirect_reference '$' { Z_LVAL($$.u.constant)++; } + | simple_variable { fetch_simple_variable_ex(&$$, &$1, 0, ZEND_FETCH_R TSRMLS_CC); } ; assignment_list: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0b5dde159922a..84503b7d9f597 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1317,7 +1317,7 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMP|VAR|UNUSED|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -1332,7 +1332,7 @@ ZEND_VM_HANDLER(90, ZEND_FETCH_DIM_IS, VAR|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV) +ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMP|VAR|UNUSED|CV) { USE_OPLINE zval *container; @@ -1341,6 +1341,9 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, VAR|CV, CONST|TMP|VAR|UNUSED|CV) SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } container = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -1386,7 +1389,7 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HELPER(zend_fetch_property_address_read_helper, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1; @@ -1419,7 +1422,7 @@ ZEND_VM_HELPER(zend_fetch_property_address_read_helper, VAR|UNUSED|CV, CONST|TMP ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { ZEND_VM_DISPATCH_TO_HELPER(zend_fetch_property_address_read_helper); } @@ -1473,7 +1476,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1; @@ -1505,7 +1508,7 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, VAR|UNUSED|CV, CONST|TMP|VAR|CV) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zval *container; @@ -1519,6 +1522,9 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, VAR|UNUSED|CV, CONST|TMP|VAR|CV) property = GET_OP2_ZVAL_PTR(BP_VAR_R); container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_W); + if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + zend_error_noreturn(E_ERROR, "Cannot use temporary expression in write context"); + } if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -2595,7 +2601,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) zval *function_name_ptr, *function_name, *func; call_slot *call = EX(call_slots) + opline->result.num; - if (OP2_TYPE == IS_CONST) { + if (OP2_TYPE == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) { function_name_ptr = function_name = (zval*)(opline->op2.zv+1); if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); @@ -2646,7 +2652,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (OP2_TYPE != IS_CONST && OP2_TYPE != IS_TMP_VAR && + } else if (OP2_TYPE != 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, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -2657,7 +2663,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (OP2_TYPE == IS_CV) { FREE_OP2(); } @@ -2667,8 +2673,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV) CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (OP2_TYPE != IS_CONST && - EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) { zval *obj; zval *method; @@ -4628,7 +4633,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, UNUSED|CONST|VAR) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -4732,12 +4737,12 @@ ZEND_VM_C_LABEL(str_index_prop): FREE_OP2(); ZVAL_BOOL(EX_VAR(opline->result.var), result); - FREE_OP1_IF_VAR(); + FREE_OP1(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -4765,7 +4770,7 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, VAR|UNUSED|CV, CONST|TMP|VAR|C FREE_OP2(); ZVAL_BOOL(EX_VAR(opline->result.var), result); - FREE_OP1_IF_VAR(); + FREE_OP1(); CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a5b678c9d247b..b93f1ef88181c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1465,7 +1465,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE zval *function_name_ptr, *function_name, *func; call_slot *call = EX(call_slots) + opline->result.num; - if (IS_CONST == IS_CONST) { + if (IS_CONST == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) { function_name_ptr = function_name = (zval*)(opline->op2.zv+1); if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); @@ -1515,7 +1515,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CONST != IS_CONST && IS_CONST != IS_TMP_VAR && + } 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, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -1526,7 +1526,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_CONST == IS_CV) { } @@ -1536,8 +1536,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CONST != IS_CONST && - EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) { zval *obj; zval *method; @@ -1795,7 +1794,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H zval *function_name_ptr, *function_name, *func; call_slot *call = EX(call_slots) + opline->result.num; - if (IS_TMP_VAR == IS_CONST) { + if (IS_TMP_VAR == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) { function_name_ptr = function_name = (zval*)(opline->op2.zv+1); if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); @@ -1846,7 +1845,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_TMP_VAR != IS_CONST && IS_TMP_VAR != IS_TMP_VAR && + } else if (IS_TMP_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, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -1857,7 +1856,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_TMP_VAR == IS_CV) { zval_dtor(free_op2.var); } @@ -1867,8 +1866,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_TMP_VAR != IS_CONST && - EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) { zval *obj; zval *method; @@ -1984,7 +1982,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H zval *function_name_ptr, *function_name, *func; call_slot *call = EX(call_slots) + opline->result.num; - if (IS_VAR == IS_CONST) { + if (IS_VAR == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) { function_name_ptr = function_name = (zval*)(opline->op2.zv+1); if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); @@ -2035,7 +2033,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_VAR != IS_CONST && IS_VAR != IS_TMP_VAR && + } else if (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, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -2046,7 +2044,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_VAR == IS_CV) { zval_ptr_dtor_nogc(free_op2.var); } @@ -2056,8 +2054,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_H CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_VAR != IS_CONST && - EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) { zval *obj; zval *method; @@ -2211,7 +2208,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA zval *function_name_ptr, *function_name, *func; call_slot *call = EX(call_slots) + opline->result.num; - if (IS_CV == IS_CONST) { + if (IS_CV == IS_CONST && Z_TYPE_P(opline->op2.zv) == IS_STRING) { function_name_ptr = function_name = (zval*)(opline->op2.zv+1); if (CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv))) { call->fbc = CACHED_PTR(Z_CACHE_SLOT_P(opline->op2.zv)); @@ -2261,7 +2258,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CV != IS_CONST && IS_CV != IS_TMP_VAR && + } 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, &call->called_scope, &call->fbc, &call->object TSRMLS_CC) == SUCCESS) { @@ -2272,7 +2269,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA call->fbc->common.fn_flags & ZEND_ACC_CLOSURE) { /* Delay closure destruction until its invocation */ call->fbc->common.prototype = (zend_function*)function_name_ptr; - } else { + } else if (IS_CV == IS_CV) { } @@ -2282,8 +2279,7 @@ static int ZEND_FASTCALL ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HA CHECK_EXCEPTION(); ZEND_VM_NEXT_OPCODE(); - } else if (IS_CV != IS_CONST && - EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && + } else if (EXPECTED(Z_TYPE_P(function_name) == IS_ARRAY) && zend_hash_num_elements(Z_ARRVAL_P(function_name)) == 2) { zval *obj; zval *method; @@ -3729,6 +3725,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_ 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 = opline->op1.zv; + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + + + 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) TSRMLS_CC)) { + 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, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + + } else { + if (IS_CONST == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + + + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +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 = opline->op1.zv; + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + + 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) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1; + zval *property; + + SAVE_OPLINE(); + property = opline->op2.zv; + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_CONST_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4238,6 +4385,146 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_O 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; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = opline->op2.zv; + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + 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 = opline->op1.zv; + offset = opline->op2.zv; + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } 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_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4708,6 +4995,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + + SAVE_OPLINE(); + container = opline->op1.zv; + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + zval_dtor(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_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) TSRMLS_CC)) { + 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_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + zval_dtor(free_op2.var); + + } else { + if (IS_TMP_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + zval_dtor(free_op2.var); + + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1, free_op2; + zval *property; + + SAVE_OPLINE(); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + zval_dtor(free_op2.var); + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_CONST_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -4953,6 +5393,148 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HAN } } +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + int result; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_TMP_VAR != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_dtor(free_op2.var); + 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_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + int result; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_dtor(free_op2.var); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5536,6 +6118,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + + SAVE_OPLINE(); + container = opline->op1.zv; + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_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) TSRMLS_CC)) { + 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_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op2.var); + + } else { + if (IS_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_ptr_dtor_nogc(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + zend_free_op free_op2; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_ptr_dtor_nogc(free_op2.var); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* 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 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_CONST_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -5932,6 +6667,148 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + int result; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_VAR != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_ptr_dtor_nogc(free_op2.var); + 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_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *container; + int result; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_ptr_dtor_nogc(free_op2.var); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -6223,6 +7100,41 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HA 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) TSRMLS_CC)) { + 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 TSRMLS_CC); + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + + } else { + if (IS_UNUSED == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + + + } + 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 @@ -7043,6 +7955,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAN 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 = opline->op1.zv; + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + + + 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) TSRMLS_CC)) { + 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_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + + } else { + if (IS_CV == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = opline->op1.zv; + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + + + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +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 = opline->op1.zv; + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + + 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) TSRMLS_CC)) { + /* 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 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + + if (IS_CONST == IS_VAR && 0 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_CONST_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -7340,6 +8403,146 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HAND } } +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *container; + int result; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = opline->op1.zv; + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + 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 = opline->op1.zv; + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } 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_YIELD_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -8900,6 +10103,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HA ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + + zval_dtor(free_op1.var); + 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) TSRMLS_CC)) { + 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, opline->op2.zv, IS_CONST TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + 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 TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, opline->op2.zv, IS_CONST TSRMLS_CC); + + zval_dtor(free_op1.var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CONST(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 TSRMLS_CC); + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_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 TSRMLS_CC); + offset = opline->op2.zv; + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op1.var); + 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) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1; + zval *property; + + SAVE_OPLINE(); + property = opline->op2.zv; + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_TMP_CONST(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_FETCH_DIM_TMP_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9310,6 +10664,146 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_CONST_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + int result; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = opline->op2.zv; + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_CONST != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_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_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = opline->op2.zv; + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9747,6 +11241,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + zval_dtor(free_op2.var); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMP_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) TSRMLS_CC)) { + 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_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + zval_dtor(free_op2.var); + + } else { + if (IS_TMP_VAR == IS_UNUSED) { + zend_error_noreturn(E_ERROR, "Cannot use [] for reading"); + } + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_TMP_VAR TSRMLS_CC); + zval_dtor(free_op2.var); + zval_dtor(free_op1.var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_TMP(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 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op2.var); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_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 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op2.var); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* Behave like FETCH_OBJ_W */ + zend_free_op free_op1, free_op2; + zval *property; + + SAVE_OPLINE(); + property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + zval_dtor(free_op2.var); + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_TMP_TMP(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -9992,6 +11639,148 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDL } } +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; + int result; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_TMP_VAR != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_dtor(free_op2.var); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_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_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_TMP_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_dtor(free_op2.var); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10575,6 +12364,159 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HAND ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_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) TSRMLS_CC)) { + 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_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op2.var); + + } else { + if (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 TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2 TSRMLS_CC), IS_VAR TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + zval_dtor(free_op1.var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_VAR(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 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_ptr_dtor_nogc(free_op2.var); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMP_VAR_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 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_ptr_dtor_nogc(free_op2.var); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *container; + + if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + /* 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 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + zval_ptr_dtor_nogc(free_op2.var); + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_TMP_VAR(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -10971,6 +12913,148 @@ static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCOD ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *container; + int result; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_VAR != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_ptr_dtor_nogc(free_op2.var); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_VAR_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_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_VAR == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + zval_ptr_dtor_nogc(free_op2.var); + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11262,6 +13346,41 @@ static int ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HAND return zend_fetch_var_address_helper_SPEC_TMP_UNUSED(BP_VAR_IS, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +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) TSRMLS_CC)) { + 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 TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + 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 TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, NULL, IS_UNUSED TSRMLS_CC); + + zval_dtor(free_op1.var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -11950,6 +14069,157 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDL ZEND_VM_NEXT_OPCODE(); } +static int ZEND_FASTCALL ZEND_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + zend_fetch_dimension_address_read_IS(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + + zval_dtor(free_op1.var); + 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) TSRMLS_CC)) { + 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_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + 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 TSRMLS_CC); + zend_fetch_dimension_address_read_R(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC), IS_CV TSRMLS_CC); + + zval_dtor(free_op1.var); + } + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL zend_fetch_property_address_read_helper_SPEC_TMP_CV(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 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + 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 */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_R, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + +static int ZEND_FASTCALL ZEND_FETCH_OBJ_IS_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 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT) || + UNEXPECTED(Z_OBJ_HT_P(container)->read_property == NULL)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } else { + zval *retval; + + /* here we are sure we are dealing with an object */ + retval = Z_OBJ_HT_P(container)->read_property(container, offset, BP_VAR_IS, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1), EX_VAR(opline->result.var) TSRMLS_CC); + + if (retval != EX_VAR(opline->result.var)) { + ZVAL_COPY(EX_VAR(opline->result.var), retval); + } + } + + zval_dtor(free_op1.var); + 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) TSRMLS_CC)) { + /* 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 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { + zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); + } + zend_fetch_property_address(EX_VAR(opline->result.var), container, property, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(property) : -1), BP_VAR_W, 0 TSRMLS_CC); + + if (IS_TMP_VAR == IS_VAR && 1 && READY_TO_DESTROY(free_op1.var)) { + EXTRACT_ZVAL_PTR(EX_VAR(opline->result.var)); + } + + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_fetch_property_address_read_helper_SPEC_TMP_CV(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } +} + static int ZEND_FASTCALL ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -12192,6 +14462,146 @@ static int ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLE } } +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *container; + int result; + ulong hval; + zval *offset; + + SAVE_OPLINE(); + container = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(container); + zval *value = NULL; + zend_string *str; + +isset_again: + switch (Z_TYPE_P(offset)) { + case IS_DOUBLE: + hval = zend_dval_to_lval(Z_DVAL_P(offset)); + goto num_index_prop; + case IS_LONG: + hval = Z_LVAL_P(offset); +num_index_prop: + value = zend_hash_index_find(ht, hval); + break; + case IS_STRING: + str = Z_STR_P(offset); + if (IS_CV != IS_CONST) { + ZEND_HANDLE_NUMERIC_EX(str->val, str->len+1, hval, goto num_index_prop); + } +str_index_prop: + value = zend_hash_find_ind(ht, str); + break; + case IS_NULL: + str = STR_EMPTY_ALLOC(); + goto str_index_prop; + break; + case IS_FALSE: + hval = 0; + goto num_index_prop; + case IS_TRUE: + hval = 0; + 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; + break; + default: + zend_error(E_WARNING, "Illegal offset type in isset or empty"); + 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); + } else /* if (opline->extended_value & ZEND_ISEMPTY) */ { + result = (value == NULL || !i_zend_is_true(value TSRMLS_CC)); + } + } else if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_dimension) { + result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0 TSRMLS_CC); + } 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 (Z_TYPE_P(container) == IS_STRING) { /* string offsets */ + zval tmp; + + result = 0; + if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) { + 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 (Z_TYPE_P(offset) == IS_LONG) { + if (offset->value.lval >= 0 && 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 { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + +static int ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_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_tmp(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); + + if (Z_TYPE_P(container) == IS_OBJECT) { + if (Z_OBJ_HT_P(container)->has_property) { + result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? Z_CACHE_SLOT_P(offset) : -1) TSRMLS_CC); + } else { + zend_error(E_NOTICE, "Trying to check property of non-object"); + result = 0; + } + if ((opline->extended_value & ZEND_ISSET) == 0) { + result = !result; + } + } else { + result = ((opline->extended_value & ZEND_ISSET) == 0); + } + + ZVAL_BOOL(EX_VAR(opline->result.var), result); + zval_dtor(free_op1.var); + CHECK_EXCEPTION(); + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -14827,6 +17237,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -15003,6 +17416,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER(ZEND_OP property = opline->op2.zv; container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -17042,6 +19458,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -17220,6 +19639,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER(ZEND_OPCO property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -19167,6 +21589,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -19345,6 +21770,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER(ZEND_OPCO property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -21019,6 +23447,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER(ZEND_O SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -22532,6 +24963,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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 TSRMLS_CC); if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -22708,6 +25142,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER(ZEND_OPCOD property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1 TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -24409,6 +26846,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER(ZEND property = opline->op2.zv; container = _get_obj_zval_ptr_unused(TSRMLS_C); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -25770,6 +28210,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMP_HANDLER(ZEND_O property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -27048,6 +29491,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_VAR_HANDLER(ZEND_O property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -28837,6 +31283,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER(ZEND_OP property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_obj_zval_ptr_unused(TSRMLS_C); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -31761,6 +34210,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -31937,6 +34389,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPC property = opline->op2.zv; container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -33767,6 +36222,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -33945,6 +36403,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP_HANDLER(ZEND_OPCOD property = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -35775,6 +38236,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -35953,6 +38417,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCOD property = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2 TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -37509,6 +39976,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OP SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -38888,6 +41358,9 @@ static int ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call) TSRMLS_CC)) { + 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_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an array"); @@ -39064,6 +41537,9 @@ static int ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER(ZEND_OPCODE property = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var TSRMLS_CC); container = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var TSRMLS_CC); + 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(Z_TYPE_P(container) == IS_STR_OFFSET)) { zend_error_noreturn(E_ERROR, "Cannot use string offset as an object"); } @@ -41969,16 +44445,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_DIM_R_SPEC_CV_VAR_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_TMP_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_VAR_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_TMP_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_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_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_OBJ_R_SPEC_VAR_VAR_HANDLER, @@ -42169,16 +44645,16 @@ void zend_init_opcodes_handlers(void) 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_TMP_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMP_TMP_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMP_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_FETCH_DIM_IS_SPEC_TMP_CV_HANDLER, ZEND_FETCH_DIM_IS_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_DIM_IS_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_DIM_IS_SPEC_VAR_VAR_HANDLER, @@ -42194,16 +44670,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_DIM_IS_SPEC_CV_VAR_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_TMP_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_TMP_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMP_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_FETCH_OBJ_IS_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_OBJ_IS_SPEC_VAR_VAR_HANDLER, @@ -42244,16 +44720,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER, ZEND_FETCH_FUNC_ARG_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_FUNC_ARG_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMP_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_VAR_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_TMP_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_VAR_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_TMP_HANDLER, ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_VAR_HANDLER, @@ -42269,16 +44745,16 @@ void zend_init_opcodes_handlers(void) ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_VAR_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_TMP_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_VAR_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_TMP_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_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_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMP_HANDLER, ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_VAR_HANDLER, @@ -42794,16 +45270,16 @@ void zend_init_opcodes_handlers(void) 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_TMP_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_TMP_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_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_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP_CV_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_CONST_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_TMP_HANDLER, ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_VAR_VAR_HANDLER, @@ -43619,16 +46095,16 @@ void zend_init_opcodes_handlers(void) ZEND_ASSIGN_DIM_SPEC_CV_VAR_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_TMP_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_VAR_HANDLER, ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_TMP_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_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_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMP_CV_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_CONST_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_TMP_HANDLER, ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_VAR_VAR_HANDLER,