From a19f511345d97b787b0889112d5df89e87fcbd79 Mon Sep 17 00:00:00 2001 From: Lior Kaplan Date: Thu, 10 Dec 2015 15:31:06 +0200 Subject: [PATCH 1/3] Align NEWS entry format for bug #71024 --- NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 784361eddd7..8f3d442e516 100644 --- a/NEWS +++ b/NEWS @@ -74,8 +74,8 @@ PHP NEWS by gcov. (Senthil) - Opcache: - . Fixed #71024 (Unable to use PHP 7.0 x64 side-by-side with PHP 5.6 x32 on - the same server). (Anatol) + . Fixed bug #71024 (Unable to use PHP 7.0 x64 side-by-side with PHP 5.6 x32 + on the same server). (Anatol) . Fixed bug #70991 (zend_file_cache.c:710: error: array type has incomplete element type). (Laruence) . Fixed bug #70977 (Segmentation fault with opcache.huge_code_pages=1). From 37f3425263f5d0f7f8bc8f8f9091efb26384a4f5 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 10 Dec 2015 18:12:59 +0100 Subject: [PATCH 2/3] Fix Foo::${42} and similar Fixes segfault on direct use, segfault on opcache evaluated use, leak on temporary use. Fixes analogeous segfault for ${42} on opcache eval as well. --- Zend/tests/int_static_prop_name.phpt | 43 ++++++++++++++++++++++++++ Zend/zend_compile.c | 1 + Zend/zend_vm_def.h | 3 ++ Zend/zend_vm_execute.h | 27 ++++++++++++++++ ext/opcache/Optimizer/zend_optimizer.c | 15 +++++++++ 5 files changed, 89 insertions(+) create mode 100644 Zend/tests/int_static_prop_name.phpt diff --git a/Zend/tests/int_static_prop_name.phpt b/Zend/tests/int_static_prop_name.phpt new file mode 100644 index 00000000000..bfdfc420529 --- /dev/null +++ b/Zend/tests/int_static_prop_name.phpt @@ -0,0 +1,43 @@ +--TEST-- +Using an integer as a static property name +--FILE-- +getMessage(), "\n"; +} + +try { + var_dump(Foo::${(int) 42}); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +try { + var_dump(Foo::${(int) $n}); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +int(24) +int(24) +int(24) +Access to undeclared static property: Foo::$42 +Access to undeclared static property: Foo::$42 +Access to undeclared static property: Foo::$42 + diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index da4b051c4c5..34246bdc04d 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2379,6 +2379,7 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t opline = zend_emit_op(result, ZEND_FETCH_R, &prop_node, NULL); } if (opline->op1_type == IS_CONST) { + convert_to_string(CT_CONSTANT(opline->op1)); zend_alloc_polymorphic_cache_slot(opline->op1.constant); } if (class_node.op_type == IS_CONST) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index bc41a0bacf0..4c01a5d1afd 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1537,6 +1537,9 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if (OP1_TYPE != IS_CONST) { + zend_string_release(name); + } FREE_OP1(); HANDLE_EXCEPTION(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 74adfe4da0a..0fd696d327d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4996,6 +4996,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if (IS_CONST != IS_CONST) { + zend_string_release(name); + } HANDLE_EXCEPTION(); } @@ -6912,6 +6915,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if (IS_CONST != IS_CONST) { + zend_string_release(name); + } HANDLE_EXCEPTION(); } @@ -7415,6 +7421,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if (IS_CONST != IS_CONST) { + zend_string_release(name); + } HANDLE_EXCEPTION(); } @@ -31013,6 +31022,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } HANDLE_EXCEPTION(); } @@ -33221,6 +33233,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } HANDLE_EXCEPTION(); } @@ -34165,6 +34180,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if (IS_CV != IS_CONST) { + zend_string_release(name); + } HANDLE_EXCEPTION(); } @@ -41357,6 +41375,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } @@ -42345,6 +42366,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } @@ -42753,6 +42777,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } retval = zend_std_get_static_property(ce, name, 0); if (UNEXPECTED(EG(exception))) { + if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { + zend_string_release(name); + } zval_ptr_dtor_nogc(free_op1); HANDLE_EXCEPTION(); } diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index aa5b6a8a236..e6cd1169511 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -175,6 +175,21 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, op_array->cache_size += sizeof(void*); zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); break; + case ZEND_FETCH_R: + case ZEND_FETCH_W: + case ZEND_FETCH_RW: + case ZEND_FETCH_IS: + case ZEND_FETCH_UNSET: + case ZEND_FETCH_FUNC_ARG: + TO_STRING_NOWARN(val); + ZEND_OP1_TYPE(opline) = IS_CONST; + opline->op1.constant = zend_optimizer_add_literal(op_array, val); + zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline))); + if (opline->extended_value == ZEND_FETCH_STATIC_MEMBER) { + Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size; + op_array->cache_size += 2 * sizeof(void*); + } + break; case ZEND_CONCAT: case ZEND_FAST_CONCAT: TO_STRING_NOWARN(val); From 798d168d73985624cfb50e9a86acce7f3446d6fb Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 10 Dec 2015 18:17:49 +0100 Subject: [PATCH 3/3] Make update_opN_const implementation symmetric So the main structure is the same... --- ext/opcache/Optimizer/zend_optimizer.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index e6cd1169511..8d13b9f4335 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -132,6 +132,10 @@ static inline void drop_leading_backslash(zval *val) { } } +static inline void alloc_cache_slots_op1(zend_op_array *op_array, zend_op *opline, uint32_t num) { + Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size; + op_array->cache_size += num * sizeof(void *); +} static inline void alloc_cache_slots_op2(zend_op_array *op_array, zend_op *opline, uint32_t num) { Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size; op_array->cache_size += num * sizeof(void *); @@ -160,19 +164,16 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_FREE: MAKE_NOP(opline); zval_dtor(val); - break; + return 1; case ZEND_INIT_STATIC_METHOD_CALL: case ZEND_CATCH: case ZEND_FETCH_CONSTANT: case ZEND_DEFINED: case ZEND_NEW: REQUIRES_STRING(val); - ZEND_OP1_TYPE(opline) = IS_CONST; drop_leading_backslash(val); opline->op1.constant = zend_optimizer_add_literal(op_array, val); - zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline))); - Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size; - op_array->cache_size += sizeof(void*); + alloc_cache_slots_op1(op_array, opline, 1); zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val))); break; case ZEND_FETCH_R: @@ -182,12 +183,9 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, case ZEND_FETCH_UNSET: case ZEND_FETCH_FUNC_ARG: TO_STRING_NOWARN(val); - ZEND_OP1_TYPE(opline) = IS_CONST; opline->op1.constant = zend_optimizer_add_literal(op_array, val); - zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline))); if (opline->extended_value == ZEND_FETCH_STATIC_MEMBER) { - Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size; - op_array->cache_size += 2 * sizeof(void*); + alloc_cache_slots_op1(op_array, opline, 2); } break; case ZEND_CONCAT: @@ -195,14 +193,14 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array, TO_STRING_NOWARN(val); /* break missing intentionally */ default: - ZEND_OP1_TYPE(opline) = IS_CONST; opline->op1.constant = zend_optimizer_add_literal(op_array, val); - if (Z_TYPE_P(val) == IS_STRING) { - zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline))); - } break; } + ZEND_OP1_TYPE(opline) = IS_CONST; + if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { + zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline))); + } return 1; }