Fixed inconsistent $this behavior

This commit is contained in:
Dmitry Stogov 2016-05-23 22:18:36 +03:00
parent 0cdbabe558
commit 41f1531b52
25 changed files with 556 additions and 181 deletions

View file

@ -31,40 +31,4 @@ $test->bar();
?>
--EXPECTF--
object(Exception)#%d (7) {
["message":protected]=>
string(3) "foo"
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(%d) "%s030.php"
["line":protected]=>
int(%d)
["trace":"Exception":private]=>
array(1) {
[0]=>
array(6) {
["file"]=>
string(%d) "%s030.php"
["line"]=>
int(%d)
["function"]=>
string(3) "bar"
["class"]=>
string(3) "foo"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
}
["previous":"Exception":private]=>
NULL
}
'test' => '0'
'test_2' => '1'
'test_3' => '2'
ok
Fatal error: Cannot re-assign $this in %s030.php on line 11

View file

@ -13,6 +13,4 @@ $x = $c->test();
print_r($x);
unset($c, $x);
--EXPECTF--
Array
(
)
Fatal error: Cannot unset $this in %sbug68370.php on line 4

View file

@ -0,0 +1,12 @@
--TEST--
$this as global variable
--FILE--
<?php
function foo() {
global $this;
var_dump($this);
}
foo();
?>
--EXPECTF--
Fatal error: Cannot use $this as global variable in %sthis_as_global.php on line 3

View file

@ -0,0 +1,11 @@
--TEST--
$this as parameter
--FILE--
<?php
function foo($this) {
var_dump($this);
}
foo(5);
?>
--EXPECTF--
Fatal error: Cannot use $this as parameter in %sthis_as_parameter.php on line 2

View file

@ -0,0 +1,12 @@
--TEST--
$this as static variable
--FILE--
<?php
function foo() {
static $this;
var_dump($this);
}
foo();
?>
--EXPECTF--
Fatal error: Cannot use $this as static variable in %sthis_as_static.php on line 3

View file

@ -0,0 +1,18 @@
--TEST--
$this in catch
--FILE--
<?php
class C {
function foo() {
try {
throw new Exception();
} catch (Exception $this) {
}
var_dump($this);
}
}
$obj = new C;
$obj->foo();
?>
--EXPECTF--
Fatal error: Cannot re-assign $this in %sthis_in_catch.php on line 6

View file

@ -0,0 +1,11 @@
--TEST--
$this in foreach
--FILE--
<?php
$a = [1];
foreach ($a as $this) {
var_dump($this);
}
?>
--EXPECTF--
Fatal error: Cannot re-assign $this in %sthis_in_foreach_001.php on line 3

View file

@ -0,0 +1,11 @@
--TEST--
$this in foreach
--FILE--
<?php
$a = [1];
foreach ($a as $this => $dummy) {
var_dump($this);
}
?>
--EXPECTF--
Fatal error: Cannot re-assign $this in %sthis_in_foreach_002.php on line 3

View file

@ -0,0 +1,11 @@
--TEST--
$this in foreach
--FILE--
<?php
$a = [1];
foreach ($a as &$this) {
var_dump($this);
}
?>
--EXPECTF--
Fatal error: Cannot re-assign $this in %sthis_in_foreach_003.php on line 3

View file

@ -0,0 +1,11 @@
--TEST--
$this in foreach
--FILE--
<?php
$a = [[1]];
foreach ($a as list($this)) {
var_dump($this);
}
?>
--EXPECTF--
Fatal error: Cannot re-assign $this in %sthis_in_foreach_004.php on line 3

View file

@ -0,0 +1,8 @@
--TEST--
$this in unset
--FILE--
<?php
unset($this);
?>
--EXPECTF--
Fatal error: Cannot unset $this in %sthis_in_unset.php on line 2

View file

@ -0,0 +1,17 @@
--TEST--
$this re-assign
--FILE--
<?php
function foo() {
$a = "this";
$$a = 0;
var_dump($$a);
}
foo();
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot re-assign $this in %sthis_reassign.php:4
Stack trace:
#0 %sthis_reassign.php(7): foo()
#1 {main}
thrown in %sthis_reassign.php on line 4

View file

@ -755,6 +755,9 @@ void zend_do_free(znode *op1) /* {{{ */
additional FREE opcode and simplify the FETCH handlers
their selves */
zend_emit_op(NULL, ZEND_FREE, op1, NULL);
} else if (opline->opcode == ZEND_FETCH_THIS) {
opline->opcode = ZEND_NOP;
opline->result_type = IS_UNUSED;
} else {
opline->result_type = IS_UNUSED;
}
@ -1927,6 +1930,13 @@ static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
{
zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
if (opline->opcode == ZEND_FETCH_THIS) {
if ((type & BP_VAR_MASK) == BP_VAR_IS) {
opline->opcode = ZEND_FETCH_THIS_IS;
}
return;
}
switch (type & BP_VAR_MASK) {
case BP_VAR_R:
return;
@ -2507,9 +2517,6 @@ static int zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
/* lookup_cv may be using another zend_string instance */
name = CG(active_op_array)->vars[EX_VAR_TO_NUM(result->u.op.var)];
if (zend_string_equals_literal(name, "this")) {
CG(active_op_array)->this_var = result->u.op.var;
}
return SUCCESS;
}
@ -2540,22 +2547,31 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
opline->extended_value = ZEND_FETCH_GLOBAL;
} else {
opline->extended_value = ZEND_FETCH_LOCAL;
/* there is a chance someone is accessing $this */
if (ast->kind != ZEND_AST_ZVAL
&& CG(active_op_array)->scope && CG(active_op_array)->this_var == (uint32_t)-1
) {
zend_string *key = CG(known_strings)[ZEND_STR_THIS];
CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key);
}
}
return opline;
}
/* }}} */
static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
{
if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
zval *name = zend_ast_get_zval(ast->child[0]);
return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "this");
}
return 0;
}
/* }}} */
static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
{
if (zend_try_compile_cv(result, ast) == FAILURE) {
zend_op *opline;
if (is_this_fetch(ast)) {
opline = zend_emit_op(result, ZEND_FETCH_THIS, NULL, NULL);
zend_adjust_for_fetch_type(opline, type);
} else if (zend_try_compile_cv(result, ast) == FAILURE) {
zend_op *opline = zend_compile_simple_var_no_cv(result, ast, type, delayed);
zend_adjust_for_fetch_type(opline, type);
}
@ -2636,17 +2652,6 @@ void zend_compile_dim(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
}
/* }}} */
static zend_bool is_this_fetch(zend_ast *ast) /* {{{ */
{
if (ast->kind == ZEND_AST_VAR && ast->child[0]->kind == ZEND_AST_ZVAL) {
zval *name = zend_ast_get_zval(ast->child[0]);
return Z_TYPE_P(name) == IS_STRING && zend_string_equals_literal(Z_STR_P(name), "this");
}
return 0;
}
/* }}} */
static zend_op *zend_delayed_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
{
zend_ast *obj_ast = ast->child[0];
@ -2944,7 +2949,8 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
offset = zend_delayed_compile_begin();
zend_delayed_compile_dim(result, var_ast, BP_VAR_W);
if (zend_is_assign_to_self(var_ast, expr_ast)) {
if (zend_is_assign_to_self(var_ast, expr_ast)
&& !is_this_fetch(expr_ast)) {
/* $a[0] = $a should evaluate the right $a first */
zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
} else {
@ -3886,7 +3892,9 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
convert_to_string(&name_node.u.constant);
}
if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
if (is_this_fetch(var_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as global variable");
} else if (zend_try_compile_cv(&result, var_ast) == SUCCESS) {
zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
zend_alloc_cache_slot(opline->op2.constant);
} else {
@ -3931,6 +3939,10 @@ static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_
}
zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value);
if (zend_string_equals_literal(Z_STR(var_node.u.constant), "this")) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as static variable");
}
opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &var_node);
opline->op1_type = IS_CV;
opline->op1.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR(var_node.u.constant)));
@ -3964,7 +3976,9 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
switch (var_ast->kind) {
case ZEND_AST_VAR:
if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
if (is_this_fetch(var_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot unset $this");
} else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
} else {
@ -4394,7 +4408,9 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */
opnum_fetch = get_next_op_number(CG(active_op_array));
opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
if (value_ast->kind == ZEND_AST_VAR &&
if (is_this_fetch(value_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
} else if (value_ast->kind == ZEND_AST_VAR &&
zend_try_compile_cv(&value_node, value_ast) == SUCCESS) {
SET_NODE(opline->op2, &value_node);
} else {
@ -4645,6 +4661,10 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
opline->op1.constant = zend_add_class_name_literal(CG(active_op_array),
zend_resolve_class_name_ast(class_ast));
if (zend_string_equals_literal(Z_STR_P(var_name), "this")) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
}
opline->op2_type = IS_CV;
opline->op2.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR_P(var_name)));
@ -4971,11 +4991,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR, "Redefinition of parameter $%s",
ZSTR_VAL(name));
} else if (zend_string_equals_literal(name, "this")) {
if ((op_array->scope || (op_array->fn_flags & ZEND_ACC_CLOSURE))
&& (op_array->fn_flags & ZEND_ACC_STATIC) == 0) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as parameter");
}
op_array->this_var = var_node.u.op.var;
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use $this as parameter");
}
if (op_array->fn_flags & ZEND_ACC_VARIADIC) {
@ -6958,7 +6974,9 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
switch (var_ast->kind) {
case ZEND_AST_VAR:
if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
if (is_this_fetch(var_ast)) {
opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_THIS, NULL, NULL);
} else if (zend_try_compile_cv(&var_node, var_ast) == SUCCESS) {
opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
} else {

View file

@ -363,8 +363,6 @@ struct _zend_op_array {
uint32_t *refcount;
uint32_t this_var;
uint32_t last;
zend_op *opcodes;

View file

@ -2146,7 +2146,7 @@ static zend_never_inline ZEND_COLD ZEND_NORETURN void ZEND_FASTCALL zend_interru
* +----------------------------------------+
*/
static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value, int check_this) /* {{{ */
static zend_always_inline void i_init_func_execute_data(zend_execute_data *execute_data, zend_op_array *op_array, zval *return_value) /* {{{ */
{
uint32_t first_extra_arg, num_args;
ZEND_ASSERT(EX(func) == (zend_function*)op_array);
@ -2204,11 +2204,6 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
} while (var != end);
}
if (check_this && op_array->this_var != (uint32_t)-1 && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
GC_REFCOUNT(Z_OBJ(EX(This)))++;
}
EX_LOAD_RUN_TIME_CACHE(op_array);
EX_LOAD_LITERALS(op_array);
@ -2232,13 +2227,6 @@ static zend_always_inline void i_init_code_execute_data(zend_execute_data *execu
EX(call) = NULL;
EX(return_value) = return_value;
if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
GC_REFCOUNT(Z_OBJ(EX(This)))++;
if (!zend_hash_add(EX(symbol_table), CG(known_strings)[ZEND_STR_THIS], &EX(This))) {
GC_REFCOUNT(Z_OBJ(EX(This)))--;
}
}
zend_attach_symbol_table(execute_data);
if (!op_array->run_time_cache) {
@ -2261,13 +2249,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
EX(return_value) = return_value;
if (EX_CALL_INFO() & ZEND_CALL_HAS_SYMBOL_TABLE) {
if (UNEXPECTED(op_array->this_var != (uint32_t)-1) && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
GC_REFCOUNT(Z_OBJ(EX(This)))++;
if (!zend_hash_add(EX(symbol_table), CG(known_strings)[ZEND_STR_THIS], &EX(This))) {
GC_REFCOUNT(Z_OBJ(EX(This)))--;
}
}
zend_attach_symbol_table(execute_data);
} else {
uint32_t first_extra_arg, num_args;
@ -2320,11 +2301,6 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
var++;
} while (var != end);
}
if (op_array->this_var != (uint32_t)-1 && EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EX(This)));
GC_REFCOUNT(Z_OBJ(EX(This)))++;
}
}
if (!op_array->run_time_cache) {

View file

@ -1165,7 +1165,6 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend
if (is_static) {
func->fn_flags |= ZEND_ACC_STATIC;
}
func->this_var = -1;
func->opcodes = &EG(call_trampoline_op);
func->prototype = fbc;

View file

@ -85,8 +85,6 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->static_variables = NULL;
op_array->last_try_catch = 0;
op_array->this_var = -1;
op_array->fn_flags = 0;
op_array->early_binding = -1;

View file

@ -1493,6 +1493,41 @@ ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
retval = zend_hash_find(target_symbol_table, name);
if (retval == NULL) {
if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
zval *result = EX_VAR(opline->result.var);
switch (type) {
case BP_VAR_R:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
zend_error(E_NOTICE,"Undefined variable: this");
}
break;
case BP_VAR_IS:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
}
break;
case BP_VAR_RW:
case BP_VAR_W:
zend_throw_error(NULL, "Cannot re-assign $this");
break;
case BP_VAR_UNSET:
zend_throw_error(NULL, "Cannot unset $this");
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
if (OP1_TYPE != IS_CONST) {
zend_string_release(name);
}
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@ -3618,7 +3653,7 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL))
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
ZEND_VM_ENTER();
}
@ -3641,7 +3676,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL))
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
ZEND_VM_ENTER();
} else {
@ -3738,7 +3773,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL))
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 1);
i_init_func_execute_data(call, &fbc->op_array, ret);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
@ -7898,8 +7933,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY)
if (UNEXPECTED(!fbc->op_array.run_time_cache)) {
init_func_run_time_cache(&fbc->op_array);
}
i_init_func_execute_data(call, &fbc->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
} else {
@ -8059,6 +8093,49 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
ZEND_VM_HANDLER(184, ZEND_FETCH_THIS, UNUSED, UNUSED)
{
USE_OPLINE
zval *result = EX_VAR(opline->result.var);
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
ZEND_VM_NEXT_OPCODE();
} else {
ZVAL_NULL(result);
SAVE_OPLINE();
zend_error(E_NOTICE,"Undefined variable: this");
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
}
ZEND_VM_HANDLER(185, ZEND_FETCH_THIS_IS, UNUSED, UNUSED)
{
USE_OPLINE
zval *result = EX_VAR(opline->result.var);
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
}
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(186, ZEND_ISSET_ISEMPTY_THIS, UNUSED, UNUSED)
{
USE_OPLINE
zval *result = EX_VAR(opline->result.var);
ZVAL_BOOL(EX_VAR(opline->result.var),
(opline->extended_value & ZEND_ISSET) ?
(Z_TYPE(EX(This)) == IS_OBJECT) :
(Z_TYPE(EX(This)) != IS_OBJECT));
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_TYPE_SPEC_HANDLER(ZEND_ADD, (res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG), ZEND_ADD_LONG_NO_OVERFLOW, CONST|TMPVARCV, CONST|TMPVARCV, SPEC(NO_CONST_CONST,COMMUTATIVE))
{
USE_OPLINE

View file

@ -707,7 +707,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HA
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
ZEND_VM_ENTER();
}
@ -729,7 +729,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_USED_HAND
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
ZEND_VM_ENTER();
}
@ -752,7 +752,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
ZEND_VM_ENTER();
} else {
@ -831,7 +831,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
ZEND_VM_ENTER();
} else {
@ -928,7 +928,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 1);
i_init_func_execute_data(call, &fbc->op_array, ret);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
@ -1057,7 +1057,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND
}
call->prev_execute_data = execute_data;
i_init_func_execute_data(call, &fbc->op_array, ret, 1);
i_init_func_execute_data(call, &fbc->op_array, ret);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
@ -1988,8 +1988,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
if (UNEXPECTED(!fbc->op_array.run_time_cache)) {
init_func_run_time_cache(&fbc->op_array);
}
i_init_func_execute_data(call, &fbc->op_array,
ret, (fbc->common.fn_flags & ZEND_ACC_STATIC) == 0);
i_init_func_execute_data(call, &fbc->op_array, ret);
if (EXPECTED(zend_execute_ex == execute_ex)) {
ZEND_VM_ENTER();
} else {
@ -6977,6 +6976,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
retval = zend_hash_find(target_symbol_table, name);
if (retval == NULL) {
if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
zval *result = EX_VAR(opline->result.var);
switch (type) {
case BP_VAR_R:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
zend_error(E_NOTICE,"Undefined variable: this");
}
break;
case BP_VAR_IS:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
}
break;
case BP_VAR_RW:
case BP_VAR_W:
zend_throw_error(NULL, "Cannot re-assign $this");
break;
case BP_VAR_UNSET:
zend_throw_error(NULL, "Cannot unset $this");
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
if (IS_CONST != IS_CONST) {
zend_string_release(name);
}
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@ -31742,6 +31776,49 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
ZEND_VM_RETURN();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *result = EX_VAR(opline->result.var);
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
ZEND_VM_NEXT_OPCODE();
} else {
ZVAL_NULL(result);
SAVE_OPLINE();
zend_error(E_NOTICE,"Undefined variable: this");
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_THIS_IS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *result = EX_VAR(opline->result.var);
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
}
ZEND_VM_NEXT_OPCODE();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *result = EX_VAR(opline->result.var);
ZVAL_BOOL(EX_VAR(opline->result.var),
(opline->extended_value & ZEND_ISSET) ?
(Z_TYPE(EX(This)) == IS_OBJECT) :
(Z_TYPE(EX(This)) != IS_OBJECT));
ZEND_VM_NEXT_OPCODE();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SPEC_UNUSED_CV(binary_op_type binary_op ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@ -44273,6 +44350,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
retval = zend_hash_find(target_symbol_table, name);
if (retval == NULL) {
if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
zval *result = EX_VAR(opline->result.var);
switch (type) {
case BP_VAR_R:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
zend_error(E_NOTICE,"Undefined variable: this");
}
break;
case BP_VAR_IS:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
}
break;
case BP_VAR_RW:
case BP_VAR_W:
zend_throw_error(NULL, "Cannot re-assign $this");
break;
case BP_VAR_UNSET:
zend_throw_error(NULL, "Cannot unset $this");
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
if (IS_CV != IS_CONST) {
zend_string_release(name);
}
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@ -56240,6 +56352,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
retval = zend_hash_find(target_symbol_table, name);
if (retval == NULL) {
if (UNEXPECTED(zend_string_equals(name, CG(known_strings)[ZEND_STR_THIS]))) {
zval *result = EX_VAR(opline->result.var);
switch (type) {
case BP_VAR_R:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
zend_error(E_NOTICE,"Undefined variable: this");
}
break;
case BP_VAR_IS:
if (EXPECTED(Z_TYPE(EX(This)) == IS_OBJECT)) {
ZVAL_OBJ(result, Z_OBJ(EX(This)));
Z_ADDREF_P(result);
} else {
ZVAL_NULL(result);
}
break;
case BP_VAR_RW:
case BP_VAR_W:
zend_throw_error(NULL, "Cannot re-assign $this");
break;
case BP_VAR_UNSET:
zend_throw_error(NULL, "Cannot unset $this");
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
zend_string_release(name);
}
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@ -63706,6 +63853,81 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_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_THIS_SPEC_UNUSED_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_THIS_IS_SPEC_UNUSED_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_ISSET_ISEMPTY_THIS_SPEC_UNUSED_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER,
ZEND_ADD_LONG_NO_OVERFLOW_SPEC_CONST_TMPVARCV_HANDLER,
ZEND_NULL_HANDLER,
@ -64707,9 +64929,9 @@ void zend_init_opcodes_handlers(void)
1423 | SPEC_RULE_OP1,
1428 | SPEC_RULE_OP1,
1433 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
4471,
4471,
4471,
4546,
4546,
4546,
1458 | SPEC_RULE_OP1,
1463 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
1488 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
@ -64758,7 +64980,7 @@ void zend_init_opcodes_handlers(void)
2197 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2222 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
2247 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
4471,
4546,
2272,
2273,
2274,
@ -64842,7 +65064,10 @@ void zend_init_opcodes_handlers(void)
3446 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3471 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3496 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
4471
3521 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3546 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
3571 | SPEC_RULE_OP1 | SPEC_RULE_OP2,
4546
};
zend_opcode_handlers = labels;
zend_handlers_count = sizeof(labels) / sizeof(void*);
@ -64949,7 +65174,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3521 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3596 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -64957,7 +65182,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3546 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3621 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -64965,7 +65190,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3571 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3646 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -64976,17 +65201,17 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3596 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3671 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} else if ((op1_info == MAY_BE_LONG && op2_info == MAY_BE_LONG)) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3621 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3696 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
} else if ((op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE)) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3646 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3721 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
}
break;
case ZEND_MUL:
@ -64994,7 +65219,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3671 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3746 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -65002,7 +65227,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3696 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3771 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -65010,7 +65235,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3721 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 3796 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -65021,7 +65246,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3746 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 3821 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -65029,7 +65254,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3821 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 3896 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -65040,7 +65265,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3896 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 3971 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -65048,7 +65273,7 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 3971 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 4046 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
if (op->op1_type > op->op2_type) {
zend_swap_operands(op);
}
@ -65059,12 +65284,12 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 4046 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 4121 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} else if ((op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE)) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 4121 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 4196 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
}
break;
case ZEND_IS_SMALLER_OR_EQUAL:
@ -65072,60 +65297,60 @@ ZEND_API void zend_vm_set_opcode_handler_ex(zend_op* op, uint32_t op1_info, uint
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 4196 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 4271 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
} else if ((op1_info == MAY_BE_DOUBLE && op2_info == MAY_BE_DOUBLE)) {
if (op->op1_type == IS_CONST && op->op2_type == IS_CONST) {
break;
}
spec = 4271 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
spec = 4346 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_SMART_BRANCH;
}
break;
case ZEND_QM_ASSIGN:
if ((op1_info == MAY_BE_DOUBLE)) {
spec = 4436 | SPEC_RULE_OP1;
spec = 4511 | SPEC_RULE_OP1;
} else if ((!(op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE))))) {
spec = 4441 | SPEC_RULE_OP1;
spec = 4516 | SPEC_RULE_OP1;
}
break;
case ZEND_PRE_INC:
if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) {
spec = 4346 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
spec = 4421 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if ((op1_info == MAY_BE_LONG)) {
spec = 4356 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
spec = 4431 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) {
spec = 4366 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
spec = 4441 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
}
break;
case ZEND_PRE_DEC:
if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) {
spec = 4376 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
spec = 4451 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if ((op1_info == MAY_BE_LONG)) {
spec = 4386 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
spec = 4461 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
} else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) {
spec = 4396 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
spec = 4471 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL;
}
break;
case ZEND_POST_INC:
if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) {
spec = 4406 | SPEC_RULE_OP1;
spec = 4481 | SPEC_RULE_OP1;
} else if ((op1_info == MAY_BE_LONG)) {
spec = 4411 | SPEC_RULE_OP1;
spec = 4486 | SPEC_RULE_OP1;
} else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) {
spec = 4416 | SPEC_RULE_OP1;
spec = 4491 | SPEC_RULE_OP1;
}
break;
case ZEND_POST_DEC:
if ((res_info == MAY_BE_LONG && op1_info == MAY_BE_LONG)) {
spec = 4421 | SPEC_RULE_OP1;
spec = 4496 | SPEC_RULE_OP1;
} else if ((op1_info == MAY_BE_LONG)) {
spec = 4426 | SPEC_RULE_OP1;
spec = 4501 | SPEC_RULE_OP1;
} else if ((op1_info == (MAY_BE_LONG|MAY_BE_DOUBLE))) {
spec = 4431 | SPEC_RULE_OP1;
spec = 4506 | SPEC_RULE_OP1;
}
break;
case ZEND_FETCH_DIM_R:
if ((!(op2_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)))) {
spec = 4446 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
spec = 4521 | SPEC_RULE_OP1 | SPEC_RULE_OP2;
}
break;
default:

View file

@ -21,7 +21,7 @@
#include <stdio.h>
#include <zend.h>
static const char *zend_vm_opcodes_names[184] = {
static const char *zend_vm_opcodes_names[187] = {
"ZEND_NOP",
"ZEND_ADD",
"ZEND_SUB",
@ -206,9 +206,12 @@ static const char *zend_vm_opcodes_names[184] = {
"ZEND_FETCH_CLASS_CONSTANT",
"ZEND_BIND_LEXICAL",
"ZEND_BIND_STATIC",
"ZEND_FETCH_THIS",
"ZEND_FETCH_THIS_IS",
"ZEND_ISSET_ISEMPTY_THIS",
};
static uint32_t zend_vm_opcodes_flags[184] = {
static uint32_t zend_vm_opcodes_flags[187] = {
0x00000000,
0x00000707,
0x00000707,
@ -393,6 +396,9 @@ static uint32_t zend_vm_opcodes_flags[184] = {
0x00000373,
0x00100101,
0x00100301,
0x00000101,
0x00000101,
0x00000101,
};
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {

View file

@ -250,7 +250,10 @@ END_EXTERN_C()
#define ZEND_FETCH_CLASS_CONSTANT 181
#define ZEND_BIND_LEXICAL 182
#define ZEND_BIND_STATIC 183
#define ZEND_FETCH_THIS 184
#define ZEND_FETCH_THIS_IS 185
#define ZEND_ISSET_ISEMPTY_THIS 186
#define ZEND_VM_LAST_OPCODE 183
#define ZEND_VM_LAST_OPCODE 186
#endif

View file

@ -72,9 +72,9 @@ typedef struct _literal_info {
info[n].u.num = (_num); \
} while (0)
#define LITERAL_INFO_OBJ(n, kind, merge, slots, related, _num) do { \
#define LITERAL_INFO_OBJ(n, kind, merge, slots, related) do { \
info[n].flags = (LITERAL_EX_OBJ | ((merge) ? LITERAL_MAY_MERGE : 0) | LITERAL_FLAGS(kind, slots, related)); \
info[n].u.num = (_num); \
info[n].u.num = (uint32_t)-1; \
} while (0)
static void optimizer_literal_obj_info(literal_info *info,
@ -92,7 +92,7 @@ static void optimizer_literal_obj_info(literal_info *info,
*/
if (Z_TYPE(op_array->literals[constant]) == IS_STRING &&
op_type == IS_UNUSED) {
LITERAL_INFO_OBJ(constant, kind, 1, slots, related, op_array->this_var);
LITERAL_INFO_OBJ(constant, kind, 1, slots, related);
} else {
LITERAL_INFO(constant, kind, 0, slots, related);
}
@ -421,9 +421,11 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
case IS_CONSTANT:
if (info[i].flags & LITERAL_MAY_MERGE) {
if (info[i].flags & LITERAL_EX_OBJ) {
int key_len = MAX_LENGTH_OF_LONG + sizeof("->") - 1 + Z_STRLEN(op_array->literals[i]);
int key_len = sizeof("$this->") - 1 + Z_STRLEN(op_array->literals[i]);
key = zend_string_alloc(key_len, 0);
ZSTR_LEN(key) = snprintf(ZSTR_VAL(key), ZSTR_LEN(key)-1, "%d->%s", info[i].u.num, Z_STRVAL(op_array->literals[i]));
memcpy(ZSTR_VAL(key), "$this->", sizeof("$this->") - 1);
memcpy(ZSTR_VAL(key) + sizeof("$this->") - 1, Z_STRVAL(op_array->literals[i]), Z_STRLEN(op_array->literals[i]) + 1);
ZSTR_LEN(key) = key_len;
} else if (info[i].flags & LITERAL_EX_CLASS) {
int key_len;
zval *class_name = &op_array->literals[(info[i].u.num < i) ? map[info[i].u.num] : info[i].u.num];

View file

@ -601,7 +601,6 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int
return (tmp->min <= tmp->max);
} else if (ssa->vars[var].definition < 0) {
if (var < op_array->last_var &&
var != EX_VAR_TO_NUM(op_array->this_var) &&
op_array->function_name) {
tmp->min = 0;
@ -3842,13 +3841,7 @@ int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const
}
} else {
for (i = 0; i < op_array->last_var; i++) {
if (i == EX_VAR_TO_NUM(op_array->this_var)) {
ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT;
ssa_var_info[i].ce = op_array->scope;
ssa_var_info[i].is_instanceof = 1;
} else {
ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN;
}
ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN;
ssa_var_info[i].has_range = 0;
}
}

View file

@ -54,21 +54,25 @@ try {
--EXPECTF--
Warning: The magic method __call() must have public visibility and cannot be static in %s on line 3
---> Invoke __call via simple method call.
NULL
object(A)#1 (0) {
}
Exception caught OK; continuing.
---> Invoke __call via scope resolution operator within instance.
NULL
object(A)#1 (0) {
}
Exception caught OK; continuing.
---> Invoke __call via scope resolution operator within child instance.
NULL
object(B)#2 (0) {
}
Exception caught OK; continuing.
---> Invoke __call via callback.
NULL
object(B)#2 (0) {
}
Exception caught OK; continuing.
==DONE==

View file

@ -28,12 +28,4 @@ TestClass::Test2(new stdClass);
?>
===DONE===
--EXPECTF--
Notice: Undefined variable: this in %sstatic_this.php on line %d
NULL
Notice: Undefined variable: this in %sstatic_this.php on line %d
NULL
object(stdClass)#%d (0) {
}
===DONE===
Fatal error: Cannot use $this as parameter in %sstatic_this.php on line 16