From: George Peter Banyard Date: Sat, 2 May 2020 22:35:13 +0000 (+0200) Subject: Use int|string Fast ZPP macro in Reflection X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=038502b92a1009fa83aa60602b20446e698e7437;p=php Use int|string Fast ZPP macro in Reflection Moreover, throw a more appropriate ValueError in case the integer position provided is less than 0. Closes GH-5513 --- diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 2856e0c6db..1ed057d902 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2112,20 +2112,22 @@ ZEND_METHOD(ReflectionGenerator, getExecutingGenerator) ZEND_METHOD(ReflectionParameter, __construct) { parameter_reference *ref; - zval *reference, *parameter; + zval *reference; + zend_string *arg_name = NULL; + zend_long position; zval *object; zval *prop_name; reflection_object *intern; zend_function *fptr; struct _zend_arg_info *arg_info; - int position; uint32_t num_args; zend_class_entry *ce = NULL; zend_bool is_closure = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &reference, ¶meter) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_ZVAL(reference) + Z_PARAM_STR_OR_LONG(arg_name, position) + ZEND_PARSE_PARAMETERS_END(); object = ZEND_THIS; intern = Z_REFLECTION_P(object); @@ -2223,34 +2225,23 @@ ZEND_METHOD(ReflectionParameter, __construct) if (fptr->common.fn_flags & ZEND_ACC_VARIADIC) { num_args++; } - if (Z_TYPE_P(parameter) == IS_LONG) { - position= (int)Z_LVAL_P(parameter); - if (position < 0 || (uint32_t)position >= num_args) { - _DO_THROW("The parameter specified by its offset could not be found"); - goto failure; - } - } else { + if (arg_name != NULL) { uint32_t i; - position = -1; - if (!try_convert_to_string(parameter)) { - goto failure; - } if (has_internal_arg_info(fptr)) { for (i = 0; i < num_args; i++) { if (arg_info[i].name) { - if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, Z_STRVAL_P(parameter)) == 0) { + if (strcmp(((zend_internal_arg_info*)arg_info)[i].name, ZSTR_VAL(arg_name)) == 0) { position = i; break; } - } } } else { for (i = 0; i < num_args; i++) { if (arg_info[i].name) { - if (strcmp(ZSTR_VAL(arg_info[i].name), Z_STRVAL_P(parameter)) == 0) { + if (zend_string_equals(arg_name, arg_info[i].name)) { position = i; break; } @@ -2261,6 +2252,15 @@ ZEND_METHOD(ReflectionParameter, __construct) _DO_THROW("The parameter specified by its name could not be found"); goto failure; } + } else { + if (position < 0) { + zend_argument_value_error(2, "must be greater than or equal to 0"); + goto failure; + } + if (position >= num_args) { + _DO_THROW("The parameter specified by its offset could not be found"); + goto failure; + } } ref = (parameter_reference*) emalloc(sizeof(parameter_reference)); @@ -2292,6 +2292,7 @@ failure: if (is_closure) { zval_ptr_dtor(reference); } + RETURN_THROWS(); } /* }}} */ diff --git a/ext/reflection/php_reflection.stub.php b/ext/reflection/php_reflection.stub.php index 0adce7921c..1bcd4221cf 100644 --- a/ext/reflection/php_reflection.stub.php +++ b/ext/reflection/php_reflection.stub.php @@ -472,10 +472,9 @@ class ReflectionParameter implements Reflector final private function __clone() {} /** - * @param string|array|object - * @param int|string + * @param $function string|array|object */ - public function __construct($function, $parameter) {} + public function __construct($function, int|string $parameter) {} public function __toString(): string {} diff --git a/ext/reflection/php_reflection_arginfo.h b/ext/reflection/php_reflection_arginfo.h index a7f12dba8c..da896d4150 100644 --- a/ext/reflection/php_reflection_arginfo.h +++ b/ext/reflection/php_reflection_arginfo.h @@ -346,7 +346,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ReflectionParameter___construct, 0, 0, 2) ZEND_ARG_INFO(0, function) - ZEND_ARG_INFO(0, parameter) + ZEND_ARG_TYPE_MASK(0, parameter, MAY_BE_LONG|MAY_BE_STRING, NULL) ZEND_END_ARG_INFO() #define arginfo_class_ReflectionParameter___toString arginfo_class_ReflectionFunction___toString diff --git a/ext/reflection/tests/parameters_001.phpt b/ext/reflection/tests/parameters_001.phpt index 6c57b2c307..8299a63bf9 100644 --- a/ext/reflection/tests/parameters_001.phpt +++ b/ext/reflection/tests/parameters_001.phpt @@ -22,8 +22,13 @@ var_dump($p->isOptional()); try { $p = new ReflectionParameter(array('Test', 'func'), 'z'); var_dump($p->isOptional()); +} catch (Exception $e) { + var_dump($e->getMessage()); } -catch (Exception $e) { +try { + $p = new ReflectionParameter(array('Test', 'func'), -1); + var_dump($p->isOptional()); +} catch (\ValueError $e) { var_dump($e->getMessage()); } @@ -34,3 +39,4 @@ int(1) bool(false) bool(true) string(54) "The parameter specified by its name could not be found" +string(95) "ReflectionParameter::__construct(): Argument #2 ($parameter) must be greater than or equal to 0"