I'm going for a very conservative fix here, where the previous
logic is restored for the case where an object is passed to
method_exists(). We might want to check against EG(scope) instead,
but this seems like a safer choice.

This means that behavior in PHP 7.4 changes only for
method_exists('C', 'privateMethodNotOnC'), which should be sensible.
This commit is contained in:
Nikita Popov 2019-10-04 12:38:18 +02:00
parent 9659562cb5
commit ca652aafa8
4 changed files with 11 additions and 5 deletions

2
NEWS
View file

@ -6,6 +6,8 @@ PHP NEWS
. Fixed bug #78614 (Does not compile with DTRACE anymore). . Fixed bug #78614 (Does not compile with DTRACE anymore).
(tz at FreeBSD dot org) (tz at FreeBSD dot org)
. Fixed bug #78620 (Out of memory error). (cmb, Nikita) . Fixed bug #78620 (Out of memory error). (cmb, Nikita)
. Fixed bug #78632 (method_exists() in php74 works differently from php73 in
checking priv. methods). (Nikita)
- Pcntl: - Pcntl:
. Fixed bug #77335 (PHP is preventing SIGALRM from specifying SA_RESTART). . Fixed bug #77335 (PHP is preventing SIGALRM from specifying SA_RESTART).

View file

@ -40,7 +40,7 @@ var_dump($example->propertyBarExists());
?> ?>
--EXPECT-- --EXPECT--
bool(false) bool(true)
bool(true) bool(true)
bool(true) bool(true)
bool(true) bool(true)

View file

@ -1373,7 +1373,11 @@ ZEND_FUNCTION(method_exists)
zend_string_release_ex(lcname, 0); zend_string_release_ex(lcname, 0);
if (func) { if (func) {
RETURN_BOOL(!(func->common.fn_flags & ZEND_ACC_PRIVATE) || func->common.scope == ce); /* Exclude shadow properties when checking a method on a specific class. Include
* them when checking an object, as method_exists() generally ignores visibility.
* TODO: Should we use EG(scope) for the object case instead? */
RETURN_BOOL(Z_TYPE_P(klass) == IS_OBJECT
|| !(func->common.fn_flags & ZEND_ACC_PRIVATE) || func->common.scope == ce);
} }
if (Z_TYPE_P(klass) == IS_OBJECT) { if (Z_TYPE_P(klass) == IS_OBJECT) {

View file

@ -50,7 +50,7 @@ foreach ($methods as $method) {
echo "Done"; echo "Done";
?> ?>
--EXPECT-- --EXPECT--
---(Using string class name)--- ---(Using string class name)---
Does C::inherit_pub exist? bool(true) Does C::inherit_pub exist? bool(true)
Does C::inherit_prot exist? bool(true) Does C::inherit_prot exist? bool(true)
Does C::inherit_priv exist? bool(false) Does C::inherit_priv exist? bool(false)
@ -68,10 +68,10 @@ Does C::non_existent exist? bool(false)
---(Using object)--- ---(Using object)---
Does C::inherit_pub exist? bool(true) Does C::inherit_pub exist? bool(true)
Does C::inherit_prot exist? bool(true) Does C::inherit_prot exist? bool(true)
Does C::inherit_priv exist? bool(false) Does C::inherit_priv exist? bool(true)
Does C::inherit_static_pub exist? bool(true) Does C::inherit_static_pub exist? bool(true)
Does C::inherit_static_prot exist? bool(true) Does C::inherit_static_prot exist? bool(true)
Does C::inherit_static_priv exist? bool(false) Does C::inherit_static_priv exist? bool(true)
Does C::pub exist? bool(true) Does C::pub exist? bool(true)
Does C::prot exist? bool(true) Does C::prot exist? bool(true)
Does C::priv exist? bool(true) Does C::priv exist? bool(true)