]> granicus.if.org Git - php/commitdiff
Fixed bug #33312 (ReflectionParameter methods do not work correctly)
authorDmitry Stogov <dmitry@php.net>
Mon, 13 Jun 2005 07:55:08 +0000 (07:55 +0000)
committerDmitry Stogov <dmitry@php.net>
Mon, 13 Jun 2005 07:55:08 +0000 (07:55 +0000)
NEWS
Zend/zend_reflection_api.c
ext/reflection/php_reflection.c
ext/reflection/tests/bug33312.phpt [new file with mode: 0755]

diff --git a/NEWS b/NEWS
index fec84950c763b77561bbf1a0dc862ec8a2255a45..fc33253506febf9a4ae45c6860635478c4ab1c8f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,9 @@
 PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+?? ??? 2005, PHP 5.1
+- Fixed bug #33312 (ReflectionParameter methods do not work correctly).
+  (Dmitry)
+
 11 Jun 2005, PHP 5.1 Beta 2
 - Fixed PDO shutdown problem (possible inifite loop running rollback on
   shutdown). (Wez)
index 450081b24ed92897199da946a2a6f0b62a5f6ce1..e1f61687f96de06c7bbc049cd448b085ee031c74 100644 (file)
@@ -508,6 +508,24 @@ static void _const_string(string *str, char *name, zval *value, char *indent TSR
 }
 /* }}} */
 
+/* {{{ _get_recv_opcode */
+static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset)
+{
+       zend_op *op = op_array->opcodes;
+       zend_op *end = op + op_array->last;
+
+       ++offset;
+       while (op < end) {
+               if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT) &&
+                   op->op1.u.constant.value.lval == offset) {
+                 return op;
+         }
+         ++op;
+       }
+       return NULL;
+}
+/* }}} */
+
 /* {{{ _parameter_string */
 static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC)
 {
@@ -537,8 +555,8 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
                string_printf(str, "$param%d", offset);
        }
        if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
-               zend_op *precv = &((zend_op_array*)fptr)->opcodes[offset*2 + 1];
-               if (precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
+               zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
+               if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
                        zval *zv, zv_copy;
                        int use_copy;
                        string_write(str, " = ", sizeof(" = ")-1);
@@ -1798,8 +1816,8 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
        if (param->offset < param->required) {
                RETURN_FALSE;
        }
-       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
-       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+       precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
+       if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -1827,8 +1845,8 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); 
                return;
        }
-       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
-       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+       precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
+       if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); 
                return;
        }
index 450081b24ed92897199da946a2a6f0b62a5f6ce1..e1f61687f96de06c7bbc049cd448b085ee031c74 100644 (file)
@@ -508,6 +508,24 @@ static void _const_string(string *str, char *name, zval *value, char *indent TSR
 }
 /* }}} */
 
+/* {{{ _get_recv_opcode */
+static zend_op* _get_recv_op(zend_op_array *op_array, zend_uint offset)
+{
+       zend_op *op = op_array->opcodes;
+       zend_op *end = op + op_array->last;
+
+       ++offset;
+       while (op < end) {
+               if ((op->opcode == ZEND_RECV || op->opcode == ZEND_RECV_INIT) &&
+                   op->op1.u.constant.value.lval == offset) {
+                 return op;
+         }
+         ++op;
+       }
+       return NULL;
+}
+/* }}} */
+
 /* {{{ _parameter_string */
 static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg_info *arg_info, zend_uint offset, zend_uint required, char* indent TSRMLS_DC)
 {
@@ -537,8 +555,8 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
                string_printf(str, "$param%d", offset);
        }
        if (fptr->type == ZEND_USER_FUNCTION && offset >= required) {
-               zend_op *precv = &((zend_op_array*)fptr)->opcodes[offset*2 + 1];
-               if (precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
+               zend_op *precv = _get_recv_op((zend_op_array*)fptr, offset);
+               if (precv && precv->opcode == ZEND_RECV_INIT && precv->op2.op_type != IS_UNUSED) {
                        zval *zv, zv_copy;
                        int use_copy;
                        string_write(str, " = ", sizeof(" = ")-1);
@@ -1798,8 +1816,8 @@ ZEND_METHOD(reflection_parameter, isDefaultValueAvailable)
        if (param->offset < param->required) {
                RETURN_FALSE;
        }
-       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
-       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+       precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
+       if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
                RETURN_FALSE;
        }
        RETURN_TRUE;
@@ -1827,8 +1845,8 @@ ZEND_METHOD(reflection_parameter, getDefaultValue)
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Parameter is not optional"); 
                return;
        }
-       precv = &((zend_op_array*)param->fptr)->opcodes[param->offset*2 + 1];
-       if (precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
+       precv = _get_recv_op((zend_op_array*)param->fptr, param->offset);
+       if (!precv || precv->opcode != ZEND_RECV_INIT || precv->op2.op_type == IS_UNUSED) {
                zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Internal error"); 
                return;
        }
diff --git a/ext/reflection/tests/bug33312.phpt b/ext/reflection/tests/bug33312.phpt
new file mode 100755 (executable)
index 0000000..0c38304
--- /dev/null
@@ -0,0 +1,20 @@
+--TEST--
+Bug #33312 (ReflectionParameter methods do not work correctly)
+--FILE--
+<?php
+class Foo {
+    public function bar(Foo $foo, $bar = 'bar') {
+    }
+}
+
+$class = new ReflectionClass('Foo');
+$method = $class->getMethod('bar');
+
+foreach ($method->getParameters() as $parameter) {
+    if ($parameter->isDefaultValueAvailable()) {
+        print $parameter->getDefaultValue()."\n";
+    }
+}
+?>
+--EXPECT--
+bar