com php-src: Fix bug 666222: NEWS Zend/tests/closure_bug6 6622.phpt Zend/zend_closures.c Zend/zend_vm _def.h Zend/zend_vm_execute.h

From: Date: Mon, 09 Jun 2014 01:59:23 +0000
Subject: com php-src: Fix bug 666222: NEWS Zend/tests/closure_bug6 6622.phpt Zend/zend_closures.c Zend/zend_vm _def.h Zend/zend_vm_execute.h
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-78749@lists.php.net to get a copy of this message
Commit: e030efa4f64b377acc5311a92b00a8576643bb11 Author: Levi Morrison <levim@php.net> Mon, 12 May 2014 21:53:08 -0600 Committer: Stanislav Malyshev <stas@php.net> Sun, 8 Jun 2014 18:59:23 -0700 Parents: 33926b19d09d54ee43854eb59a987cd812179a7f Branches: PHP-5.4 PHP-5.5 PHP-5.6 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=e030efa4f64b377acc5311a92b00a8576643bb11 Log: 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 Bugs: https://bugs.php.net/666222 https://bugs.php.net/66622 Changed paths: M NEWS A Zend/tests/closure_bug66622.phpt M Zend/zend_closures.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h Diff: diff --git a/NEWS b/NEWS index 7354aa9..65e2fad 100644 --- a/NEWS +++ b/NEWS @@ -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). diff --git a/Zend/tests/closure_bug66622.phpt b/Zend/tests/closure_bug66622.phpt new file mode 100644 index 0000000..1c9577d --- /dev/null +++ b/Zend/tests/closure_bug66622.phpt @@ -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 diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index c18972a..9ae82b4 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -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; } } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ab33468..a7ad3aa 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fa997b2..fba5f9c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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();

« previous php.cvs (#78749) next »