- Fixed bug #38934 (move_uploaded_file() cannot read uploaded file outside of
open_basedir). (Ilia)
- Fixed bug #38649 (uninit'd optional arg in stream_socket_sendto()). (Sara)
+- Fixed bug #38465 (ReflectionParameter fails if default value is an access to
+ self::). (Johannes)
- Fixed bug #38198 (possible crash when COM reports an exception). (Ilia)
- Fixed bug #37262 (var_export() does not escape \0 character). (Ilia)
- Fixed bug #36515 (Unlinking buckets from non-existant brigades). (Sara)
}
-ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
+ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC)
{
zend_constant *c;
int retval = 1;
if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
/* class constant */
- zend_class_entry **ce = NULL, *scope;
+ zend_class_entry **ce = NULL;
int class_name_len = colon-name;
int const_name_len = name_len - class_name_len - 2;
char *constant_name = colon+2;
zval **ret_constant;
char *class_name;
- if (EG(in_execution)) {
- scope = EG(scope);
- } else {
- scope = CG(active_class_entry);
+ if (!scope) {
+ if (EG(in_execution)) {
+ scope = EG(scope);
+ } else {
+ scope = CG(active_class_entry);
+ }
}
class_name = estrndup(name, class_name_len);
return retval;
}
+ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
+{
+ zend_get_constant_ex(name, name_len, result, NULL TSRMLS_CC);
+}
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
{
void zend_register_standard_constants(TSRMLS_D);
void clean_non_persistent_constants(TSRMLS_D);
ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC);
+ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC);
ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC);
}
ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC);
+ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC);
/* dedicated Zend executor functions - do not use! */
static inline void zend_ptr_stack_clear_multiple(TSRMLS_D)
#include "../TSRM/tsrm_strtok_r.h"
-ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
+ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *scope TSRMLS_DC)
{
zval *p = *pp;
zend_bool inline_change = (zend_bool) (unsigned long) arg;
refcount = p->refcount;
is_ref = p->is_ref;
- if (!zend_get_constant(p->value.str.val, p->value.str.len, &const_value TSRMLS_CC)) {
+ if (!zend_get_constant_ex(p->value.str.val, p->value.str.len, &const_value, scope TSRMLS_CC)) {
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
p->value.str.val,
p->value.str.val);
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
}
- if (!zend_get_constant(str_index, str_index_len-1, &const_value TSRMLS_CC)) {
+ if (!zend_get_constant_ex(str_index, str_index_len-1, &const_value, scope TSRMLS_CC)) {
zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", str_index, str_index);
zend_hash_move_forward(Z_ARRVAL_P(p));
continue;
return 0;
}
+ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
+{
+ zval_update_constant_ex(pp, arg, NULL TSRMLS_CC);
+}
int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC)
{
zv_copy = precv->op2.u.constant;
zv = &zv_copy;
- zval_update_constant(&zv, (void*)0 TSRMLS_CC);
+ zval_update_constant_ex(&zv, (void*)0, param->fptr->common.scope TSRMLS_CC);
RETURN_ZVAL(zv, 1, 1);
}
/* }}} */
--- /dev/null
+--TEST--
+Reflection Bug #38465 (ReflectionParameter fails on access to self::)
+--SKIPIF--
+<?php extension_loaded('reflection') or die('skip'); ?>
+--FILE--
+<?php
+class Baz {
+ const B = 3;
+}
+
+class Foo {
+ const X = 1;
+ public function x($a = self::X, $b = Baz::B, $c = 99) {}
+}
+
+class Bar extends Foo {
+ const Y = 2;
+ public function y($a = self::Y, $b = Baz::B, $c = 99) {}
+}
+
+
+echo "From global scope:\n";
+
+$clazz = new ReflectionClass('Bar');
+foreach ($clazz->getMethods() as $method) {
+ foreach ($method->getParameters() as $param) {
+ if ($param->isDefaultValueAvailable()) {
+ echo $method->getDeclaringClass()->getName(), '::', $method->getName(), '($', $param->getName(), ' = ', $param->getDefaultValue(), ")\n";
+ }
+ }
+}
+
+echo "\nFrom class context:\n";
+
+class Test {
+ function __construct() {
+ $clazz = new ReflectionClass('Bar');
+ foreach ($clazz->getMethods() as $method) {
+ foreach ($method->getParameters() as $param) {
+ if ($param->isDefaultValueAvailable()) {
+ echo $method->getDeclaringClass()->getName(), '::', $method->getName(), '($', $param->getName(), ' = ', $param->getDefaultValue(), ")\n";
+ }
+ }
+ }
+ }
+}
+
+new Test();
+
+?>
+--EXPECT--
+From global scope:
+Bar::y($a = 2)
+Bar::y($b = 3)
+Bar::y($c = 99)
+Foo::x($a = 1)
+Foo::x($b = 3)
+Foo::x($c = 99)
+
+From class context:
+Bar::y($a = 2)
+Bar::y($b = 3)
+Bar::y($c = 99)
+Foo::x($a = 1)
+Foo::x($b = 3)
+Foo::x($c = 99)