]> granicus.if.org Git - php/commitdiff
Fixed bug #78632
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 4 Oct 2019 10:38:18 +0000 (12:38 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 4 Oct 2019 10:41:49 +0000 (12:41 +0200)
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.

NEWS
Zend/tests/bug50810.phpt
Zend/zend_builtin_functions.c
ext/standard/tests/class_object/method_exists_basic_001.phpt

diff --git a/NEWS b/NEWS
index 230a4844d320d7d4509eef2bc1c975824457de48..4651faeb42e1a338d1c530375b5f50a848ed29ba 100644 (file)
--- 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).
index e36ab0c30b0f9f6352a7aea23e1da15b02478f59..b2a29316515b4db8c6aec01d8a33ad246afd584b 100644 (file)
@@ -40,7 +40,7 @@ var_dump($example->propertyBarExists());
 
 ?>
 --EXPECT--
-bool(false)
+bool(true)
 bool(true)
 bool(true)
 bool(true)
index e3bc2ad10103712ec45455c361ed3b42454242f0..d3bf032c1085a2193a6a6e06fdacb64d04e42930 100644 (file)
@@ -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) {
index 8046051523c56ca7935b261d77ac44f55ed3ddaf..c0b656b3f9e5fa587d7bb47bbb370f636bfdf965 100644 (file)
@@ -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)