]> granicus.if.org Git - php/commitdiff
Fixed bug #39884 (ReflectionParameter::getClass() throws exception for type
authorIlia Alshanetsky <iliaa@php.net>
Fri, 22 Dec 2006 15:37:48 +0000 (15:37 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Fri, 22 Dec 2006 15:37:48 +0000 (15:37 +0000)
hint self).

NEWS
ext/reflection/php_reflection.c
ext/reflection/tests/bug39884.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 9166ab0179acc062ce99c7005b1c51d3222083e3..a1ae2abdd48079d3af74ddbd1d16e432dcd300be 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,8 @@ PHP                                                                        NEWS
 - Fixed bug #39903 (Notice message when executing __halt_compiler() more than 
   once). (Tony)
 - Fixed bug #39898 (FILTER_VALIDATE_URL validates \r\n\t etc). (Ilia)
+- Fixed bug #39884 (ReflectionParameter::getClass() throws exception for type
+  hint self). (thekid at php dot net)
 - Fixed bug #39873 (number_format() breaks with locale & decimal points).
   (Ilia)
 - Fixed bug #39869 (safe_read does not initialize errno).
index cf88d3f8606a2d0837e403baf0477295040f239b..f0ce6feed873fb0e2a36ac85f0b13febc3dcddb8 100644 (file)
@@ -1995,7 +1995,40 @@ ZEND_METHOD(reflection_parameter, getClass)
        GET_REFLECTION_OBJECT_PTR(param);
 
        if (param->arg_info->class_name) {
-               if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) {
+               /* Class name is stored as a string, we might also get "self" or "parent"
+                * - For "self", simply use the function scope. If scope is NULL then
+                *   the function is global and thus self does not make any sense
+                *
+                * - For "parent", use the function scope's parent. If scope is NULL then
+                *   the function is global and thus parent does not make any sense.
+                *   If the parent is NULL then the class does not extend anything and
+                *   thus parent does not make any sense, either.
+                *
+                * TODO: Think about moving these checks to the compiler or some sort of
+                * lint-mode.
+                */
+               if (0 == strncmp(param->arg_info->class_name, "self", sizeof("self")- 1)) {
+                       zend_class_entry *ce= param->fptr->common.scope;
+                       if (!ce) {
+                          zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
+                                  "Parameter uses 'self' as type hint but function is not a class member!");
+                          return;
+                       }
+                       pce= &ce;
+               } else if (0 == strncmp(param->arg_info->class_name, "parent", sizeof("parent")- 1)) {
+                       zend_class_entry *ce= param->fptr->common.scope;
+                       if (!ce) {
+                          zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
+                                  "Parameter uses 'parent' as type hint but function is not a class member!");
+                          return;
+                       }
+                       if (!ce->parent) {
+                          zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
+                                  "Parameter uses 'parent' as type hint although class does not have a parent!");
+                          return;
+                       }
+                       pce= &ce->parent;
+               } else if (zend_lookup_class(param->arg_info->class_name, param->arg_info->class_name_len, &pce TSRMLS_CC) == FAILURE) {
                        zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, 
                                "Class %s does not exist", param->arg_info->class_name);
                        return;
diff --git a/ext/reflection/tests/bug39884.phpt b/ext/reflection/tests/bug39884.phpt
new file mode 100644 (file)
index 0000000..dbc57ee
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #39884 (ReflectionParameter::getClass() throws exception for type hint self)
+--FILE--
+<?php
+class stubParamTest
+{
+    function paramTest(self $param)
+    {
+        // nothing to do
+    }
+}
+$test1 = new stubParamTest();
+$test2 = new stubParamTest();
+$test1->paramTest($test2);
+$refParam = new ReflectionParameter(array('stubParamTest', 'paramTest'), 'param');
+var_dump($refParam->getClass());
+?>
+--EXPECT--     
+object(ReflectionClass)#4 (1) {
+  ["name"]=>
+  string(13) "stubParamTest"
+}