From: Nikita Popov Date: Fri, 4 Oct 2019 10:38:18 +0000 (+0200) Subject: Fixed bug #78632 X-Git-Tag: php-7.4.0RC4~59 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ca652aafa8d293ac46a171b6b1326431aa13600c;p=php Fixed bug #78632 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. --- diff --git a/NEWS b/NEWS index 230a4844d3..4651faeb42 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . Fixed bug #78614 (Does not compile with DTRACE anymore). (tz at FreeBSD dot org) . 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: . Fixed bug #77335 (PHP is preventing SIGALRM from specifying SA_RESTART). diff --git a/Zend/tests/bug50810.phpt b/Zend/tests/bug50810.phpt index e36ab0c30b..b2a2931651 100644 --- a/Zend/tests/bug50810.phpt +++ b/Zend/tests/bug50810.phpt @@ -40,7 +40,7 @@ var_dump($example->propertyBarExists()); ?> --EXPECT-- -bool(false) +bool(true) bool(true) bool(true) bool(true) diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index e3bc2ad101..d3bf032c10 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1373,7 +1373,11 @@ ZEND_FUNCTION(method_exists) zend_string_release_ex(lcname, 0); 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) { diff --git a/ext/standard/tests/class_object/method_exists_basic_001.phpt b/ext/standard/tests/class_object/method_exists_basic_001.phpt index 8046051523..c0b656b3f9 100644 --- a/ext/standard/tests/class_object/method_exists_basic_001.phpt +++ b/ext/standard/tests/class_object/method_exists_basic_001.phpt @@ -50,7 +50,7 @@ foreach ($methods as $method) { echo "Done"; ?> --EXPECT-- - ---(Using string class name)--- +---(Using string class name)--- Does C::inherit_pub exist? bool(true) Does C::inherit_prot exist? bool(true) Does C::inherit_priv exist? bool(false) @@ -68,10 +68,10 @@ Does C::non_existent exist? bool(false) ---(Using object)--- Does C::inherit_pub 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_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::prot exist? bool(true) Does C::priv exist? bool(true)