From: Nikita Popov Date: Mon, 27 May 2019 15:11:44 +0000 (+0200) Subject: BIND_STATIC of implicit binding may be undef X-Git-Tag: php-7.4.0alpha1~185 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fd23f9104a9772234a3469e341500cf1b9503f63;p=php BIND_STATIC of implicit binding may be undef Even though we don't need it at runtime, add the BIND_IMPLICIT flag to BIND_STATIC as well, so we can distinguish this case in type inference. This fixes a JIT miscompile in arrow_functions/002.phpt. --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index d0d5c7af19..b4d4012d7f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4012,7 +4012,7 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */ } /* }}} */ -static void zend_compile_static_var_common(zend_string *var_name, zval *value, uint32_t by_ref) /* {{{ */ +static void zend_compile_static_var_common(zend_string *var_name, zval *value, uint32_t mode) /* {{{ */ { zend_op *opline; if (!CG(active_op_array)->static_variables) { @@ -4031,7 +4031,7 @@ static void zend_compile_static_var_common(zend_string *var_name, zval *value, u opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, NULL); opline->op1_type = IS_CV; opline->op1.var = lookup_cv(var_name); - opline->extended_value = (uint32_t)((char*)value - (char*)CG(active_op_array)->static_variables->arData) | by_ref; + opline->extended_value = (uint32_t)((char*)value - (char*)CG(active_op_array)->static_variables->arData) | mode; } /* }}} */ @@ -5584,7 +5584,7 @@ static void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ } } - zend_compile_static_var_common(var_name, &zv, var_ast->attr); + zend_compile_static_var_common(var_name, &zv, var_ast->attr ? ZEND_BIND_REF : 0); } } /* }}} */ @@ -5595,7 +5595,7 @@ static void zend_compile_implicit_closure_uses(closure_info *info) ZEND_HASH_FOREACH_STR_KEY(&info->uses, var_name) zval zv; ZVAL_NULL(&zv); - zend_compile_static_var_common(var_name, &zv, 0); + zend_compile_static_var_common(var_name, &zv, ZEND_BIND_IMPLICIT); ZEND_HASH_FOREACH_END(); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8fae94fc49..50ce8c1e92 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8220,7 +8220,7 @@ ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, UNUSED, REF) ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht); } - value = (zval*)((char*)ht->arData + (opline->extended_value & ~ZEND_BIND_REF)); + value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT))); if (opline->extended_value & ZEND_BIND_REF) { if (Z_TYPE_P(value) == IS_CONSTANT_AST) { diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fbcd28de38..26bd027f3f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -50848,7 +50848,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_UNUSED_HAN ZEND_MAP_PTR_SET(EX(func)->op_array.static_variables_ptr, ht); } - value = (zval*)((char*)ht->arData + (opline->extended_value & ~ZEND_BIND_REF)); + value = (zval*)((char*)ht->arData + (opline->extended_value & ~(ZEND_BIND_REF|ZEND_BIND_IMPLICIT))); if (opline->extended_value & ZEND_BIND_REF) { if (Z_TYPE_P(value) == IS_CONSTANT_AST) { diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index d6e3b4fa0d..866cfd06bb 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -3025,6 +3025,9 @@ static int zend_update_type_info(const zend_op_array *op_array, case ZEND_BIND_STATIC: tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF | ((opline->extended_value & ZEND_BIND_REF) ? MAY_BE_REF : (MAY_BE_RC1 | MAY_BE_RCN)); + if (opline->extended_value & ZEND_BIND_IMPLICIT) { + tmp |= MAY_BE_UNDEF; + } UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def); break; case ZEND_SEND_VAR: