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
This commit is contained in:
George Peter Banyard 2020-05-03 00:35:13 +02:00
parent b63eff17ff
commit 038502b92a
4 changed files with 30 additions and 24 deletions

View File

@ -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, &parameter) == 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();
}
/* }}} */

View File

@ -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 {}

View File

@ -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

View File

@ -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"