1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 16:22:37 +01:00

Fix bug 666222

This also adds some smaller, isolated tests related to bug 66622.

Conflicts:
	Zend/zend_vm_def.h
	Zend/zend_vm_execute.h
This commit is contained in:
Levi Morrison
2014-05-12 21:53:08 -06:00
committed by Stanislav Malyshev
parent 33926b19d0
commit e030efa4f6
5 changed files with 56 additions and 5 deletions

2
NEWS
View File

@@ -6,6 +6,8 @@ PHP NEWS
. Fixed BC break introduced by patch for bug #67072. (Anatol)
. Fixed bug #67390 (insecure temporary file use in the configure script).
(Remi) (CVE-2014-3981)
. Fixed bug #66622 (Closures do not correctly capture the late bound class
(static::) in some cases). (Levi Morrison)
- Date:
. Fixed bug #67308 (Serialize of DateTime truncates fractions of second).

View File

@@ -0,0 +1,37 @@
--TEST--
Bug 66622: Closures do not correctly capture the late bound class (static::) in some cases
--FILE--
<?php
class A {
static function name() { return 'A'; }
function foo() {
$fn = function() { return static::name(); };
echo static::name() . ' vs ' . $fn() . "\n";
}
function bar() {
$fn = static function() { return static::name(); };
echo static::name() . ' vs ' . $fn() . "\n";
}
static function baz() {
$fn = function() { return static::name(); };
echo static::name() . ' vs ' . $fn() . "\n";
}
}
class B extends A {
static function name() { return 'B'; }
}
function test() {
(new B)->foo();
(new B)->bar();
(new B)->baz();
B::baz();
}
test();
--EXPECT--
B vs B
B vs B
B vs B
B vs B

View File

@@ -487,6 +487,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
}
}
closure->this_ptr = NULL;
/* Invariants:
* If the closure is unscoped, it has no bound object.
* The the closure is scoped, it's either static or it's bound */
@@ -498,10 +499,7 @@ ZEND_API void zend_create_closure(zval *res, zend_function *func, zend_class_ent
Z_ADDREF_P(this_ptr);
} else {
closure->func.common.fn_flags |= ZEND_ACC_STATIC;
closure->this_ptr = NULL;
}
} else {
closure->this_ptr = NULL;
}
}
/* }}} */

View File

@@ -5161,6 +5161,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
{
USE_OPLINE
zend_function *op_array;
int closure_is_static, closure_is_being_defined_inside_static_context;
SAVE_OPLINE();
@@ -5169,7 +5170,13 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED)
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
}
zend_create_closure(&EX_T(opline->result.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC);
closure_is_static = op_array->common.fn_flags & ZEND_ACC_STATIC;
closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->function_state.function->common.fn_flags & ZEND_ACC_STATIC;
if (closure_is_static || closure_is_being_defined_inside_static_context) {
zend_create_closure(&EX_T(opline->result.var).tmp_var, (zend_function *) op_array, EG(called_scope), NULL TSRMLS_CC);
} else {
zend_create_closure(&EX_T(opline->result.var).tmp_var, (zend_function *) op_array, EG(scope), EG(This) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();

View File

@@ -5847,6 +5847,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER
{
USE_OPLINE
zend_function *op_array;
int closure_is_static, closure_is_being_defined_inside_static_context;
SAVE_OPLINE();
@@ -5855,7 +5856,13 @@ static int ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER
zend_error_noreturn(E_ERROR, "Base lambda function for closure not found");
}
zend_create_closure(&EX_T(opline->result.var).tmp_var, op_array, EG(scope), EG(This) TSRMLS_CC);
closure_is_static = op_array->common.fn_flags & ZEND_ACC_STATIC;
closure_is_being_defined_inside_static_context = EX(prev_execute_data) && EX(prev_execute_data)->function_state.function->common.fn_flags & ZEND_ACC_STATIC;
if (closure_is_static || closure_is_being_defined_inside_static_context) {
zend_create_closure(&EX_T(opline->result.var).tmp_var, (zend_function *) op_array, EG(called_scope), NULL TSRMLS_CC);
} else {
zend_create_closure(&EX_T(opline->result.var).tmp_var, (zend_function *) op_array, EG(scope), EG(This) TSRMLS_CC);
}
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();