Skip to content

Add more accurate types to stubs again #6068

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 35 additions & 2 deletions Zend/zend_API.h
Original file line number Diff line number Diff line change
Expand Up @@ -1221,8 +1221,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv)
_(Z_EXPECTED_DOUBLE_OR_NULL, "of type ?float") \
_(Z_EXPECTED_NUMBER, "of type int|float") \
_(Z_EXPECTED_NUMBER_OR_NULL, "of type int|float|null") \
_(Z_EXPECTED_STRING_OR_ARRAY, "of type string|array") \
_(Z_EXPECTED_STRING_OR_ARRAY_OR_NULL, "of type string|array|null") \
_(Z_EXPECTED_STRING_OR_ARRAY, "of type array|string") \
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that we use the canonical form. I'll carve out these changes to a separate commit.

_(Z_EXPECTED_STRING_OR_ARRAY_OR_NULL, "of type array|string|null") \
_(Z_EXPECTED_STRING_OR_LONG, "of type string|int") \
_(Z_EXPECTED_STRING_OR_LONG_OR_NULL, "of type string|int|null") \
_(Z_EXPECTED_CLASS_NAME_OR_OBJECT, "a valid class name or object") \
Expand Down Expand Up @@ -1511,6 +1511,9 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
#define Z_PARAM_ARRAY_HT(dest) \
Z_PARAM_ARRAY_HT_EX(dest, 0, 0)

#define Z_PARAM_ARRAY_HT_OR_NULL(dest) \
Z_PARAM_ARRAY_HT_EX(dest, 1, 0)

/* old "H" */
#define Z_PARAM_ARRAY_OR_OBJECT_HT_EX2(dest, check_null, deref, separate) \
Z_PARAM_PROLOGUE(deref, separate); \
Expand Down Expand Up @@ -1577,6 +1580,23 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char *
#define Z_PARAM_OBJECT_OR_NULL(dest) \
Z_PARAM_OBJECT_EX(dest, 1, 0)

#define Z_PARAM_OBJ_EX2(dest, check_null, deref, separate) \
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a Z_PARAM_OBJ which uses the zend_object type, rather than zval. If it was a bad idea, I can revert it, but I felt that it would help the previous efforts to migrate our APIs from zvals to zend_object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment above it, so it's obvious what the difference is?

Z_PARAM_PROLOGUE(deref, separate); \
if (UNEXPECTED(!zend_parse_arg_obj(_arg, &dest, NULL, check_null))) { \
_expected_type = check_null ? Z_EXPECTED_OBJECT_OR_NULL : Z_EXPECTED_OBJECT; \
_error_code = ZPP_ERROR_WRONG_ARG; \
break; \
}

#define Z_PARAM_OBJ_EX(dest, check_null, separate) \
Z_PARAM_OBJ_EX2(dest, check_null, separate, separate)

#define Z_PARAM_OBJ(dest) \
Z_PARAM_OBJ_EX(dest, 0, 0)

#define Z_PARAM_OBJ_OR_NULL(dest) \
Z_PARAM_OBJ_EX(dest, 1, 0)

/* old "O" */
#define Z_PARAM_OBJECT_OF_CLASS_EX2(dest, _ce, check_null, deref, separate) \
Z_PARAM_PROLOGUE(deref, separate); \
Expand Down Expand Up @@ -1952,6 +1972,19 @@ static zend_always_inline bool zend_parse_arg_object(zval *arg, zval **dest, zen
return 1;
}

static zend_always_inline bool zend_parse_arg_obj(zval *arg, zend_object **dest, zend_class_entry *ce, bool check_null)
{
if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) &&
(!ce || EXPECTED(instanceof_function(Z_OBJCE_P(arg), ce) != 0))) {
*dest = Z_OBJ_P(arg);
} else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
*dest = NULL;
} else {
return 0;
}
return 1;
}

static zend_always_inline bool zend_parse_arg_resource(zval *arg, zval **dest, bool check_null)
{
if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) {
Expand Down
3 changes: 1 addition & 2 deletions ext/intl/formatter/formatter.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ public function formatCurrency(float $value, string $currency) {}
public function parseCurrency(string $value, &$currency, &$position = null) {}

/**
* @param int|float $value
* @return bool
* @alias numfmt_set_attribute
*/
public function setAttribute(int $attr, $value) {}
public function setAttribute(int $attr, int|float $value) {}

/**
* @return int|float|false
Expand Down
4 changes: 2 additions & 2 deletions ext/intl/formatter/formatter_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 041569278b83b65f67fb4848d00d5423e6728165 */
* Stub hash: 60a05cccb434edadeec01cb7d43f919c276ce24d */

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter___construct, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 0)
Expand Down Expand Up @@ -33,7 +33,7 @@ ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter_setAttribute, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, attr, IS_LONG, 0)
ZEND_ARG_INFO(0, value)
ZEND_ARG_TYPE_MASK(0, value, MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumberFormatter_getAttribute, 0, 0, 1)
Expand Down
2 changes: 1 addition & 1 deletion ext/intl/formatter/formatter_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ PHP_FUNCTION( numfmt_set_attribute )
FORMATTER_METHOD_INIT_VARS;

/* Parse parameters. */
if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Olz",
if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Oln",
&object, NumberFormatter_ce_ptr, &attribute, &value ) == FAILURE)
{
RETURN_THROWS();
Expand Down
3 changes: 1 addition & 2 deletions ext/intl/php_intl.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,7 @@ function numfmt_format_currency(NumberFormatter $fmt, float $value, string $curr
*/
function numfmt_parse_currency(NumberFormatter $fmt, string $value, &$currency, &$position = null): float|false {}

/** @param int|float $value */
function numfmt_set_attribute(NumberFormatter $fmt, int $attr, $value): bool {}
function numfmt_set_attribute(NumberFormatter $fmt, int $attr, int|float $value): bool {}

function numfmt_get_attribute(NumberFormatter $fmt, int $attr): int|float|false {}

Expand Down
4 changes: 2 additions & 2 deletions ext/intl/php_intl_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 9284fbafde8c7430a30a8fff5537bf9e6d9c6125 */
* Stub hash: fdc7c500ddc5bc560ec54b7ce12d5961a4697a63 */

ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1)
ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timeZone, "null")
Expand Down Expand Up @@ -402,7 +402,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_numfmt_set_attribute, 0, 3, _IS_BOOL, 0)
ZEND_ARG_OBJ_INFO(0, fmt, NumberFormatter, 0)
ZEND_ARG_TYPE_INFO(0, attr, IS_LONG, 0)
ZEND_ARG_INFO(0, value)
ZEND_ARG_TYPE_MASK(0, value, MAY_BE_LONG|MAY_BE_DOUBLE, NULL)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_numfmt_get_attribute, 0, 2, MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_FALSE)
Expand Down
66 changes: 35 additions & 31 deletions ext/ldap/ldap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1423,7 +1423,9 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, in
/* {{{ php_ldap_do_search */
static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
{
zval *link, *base_dn, *filter, *attrs = NULL, *attr, *serverctrls = NULL;
zval *link, *attrs = NULL, *attr, *serverctrls = NULL;
zend_string *base_dn_str, *filter_str;
HashTable *base_dn_ht, *filter_ht;
zend_long attrsonly, sizelimit, timelimit, deref;
zend_string *ldap_filter = NULL, *ldap_base_dn = NULL;
char **ldap_attrs = NULL;
Expand All @@ -1434,10 +1436,18 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
int num_attribs = 0, ret = 1, i, errno, argcount = ZEND_NUM_ARGS();

if (zend_parse_parameters(argcount, "zzz|a/lllla/", &link, &base_dn, &filter, &attrs, &attrsonly,
&sizelimit, &timelimit, &deref, &serverctrls) == FAILURE) {
RETURN_THROWS();
}
ZEND_PARSE_PARAMETERS_START(3, 9)
Z_PARAM_ZVAL(link)
Z_PARAM_STR_OR_ARRAY_HT(base_dn_str, base_dn_ht)
Z_PARAM_STR_OR_ARRAY_HT(filter_str, filter_ht)
Z_PARAM_OPTIONAL
Z_PARAM_ARRAY_EX(attrs, 0, 1)
Z_PARAM_LONG(attrsonly)
Z_PARAM_LONG(sizelimit)
Z_PARAM_LONG(timelimit)
Z_PARAM_LONG(deref)
Z_PARAM_ARRAY_EX(serverctrls, 0, 1)
ZEND_PARSE_PARAMETERS_END();

/* Reverse -> fall through */
switch (argcount) {
Expand Down Expand Up @@ -1486,38 +1496,34 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
goto cleanup;
}

if (Z_TYPE_P(base_dn) == IS_ARRAY) {
nbases = zend_hash_num_elements(Z_ARRVAL_P(base_dn));
if (base_dn_ht) {
nbases = zend_hash_num_elements(base_dn_ht);
if (nbases != nlinks) {
php_error_docref(NULL, E_WARNING, "Base must either be a string, or an array with the same number of elements as the links array");
ret = 0;
goto cleanup;
}
zend_hash_internal_pointer_reset(Z_ARRVAL_P(base_dn));
zend_hash_internal_pointer_reset(base_dn_ht);
} else {
nbases = 0; /* this means string, not array */
ldap_base_dn = zval_get_string(base_dn);
ldap_base_dn = zend_string_copy(base_dn_str);
if (EG(exception)) {
ret = 0;
goto cleanup;
}
}

if (Z_TYPE_P(filter) == IS_ARRAY) {
nfilters = zend_hash_num_elements(Z_ARRVAL_P(filter));
if (filter_ht) {
nfilters = zend_hash_num_elements(filter_ht);
if (nfilters != nlinks) {
php_error_docref(NULL, E_WARNING, "Filter must either be a string, or an array with the same number of elements as the links array");
ret = 0;
goto cleanup;
}
zend_hash_internal_pointer_reset(Z_ARRVAL_P(filter));
zend_hash_internal_pointer_reset(filter_ht);
} else {
nfilters = 0; /* this means string, not array */
ldap_filter = zval_get_string(filter);
if (EG(exception)) {
ret = 0;
goto cleanup;
}
ldap_filter = zend_string_copy(filter_str);
}

lds = safe_emalloc(nlinks, sizeof(ldap_linkdata), 0);
Expand All @@ -1533,17 +1539,17 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
goto cleanup_parallel;
}
if (nbases != 0) { /* base_dn an array? */
entry = zend_hash_get_current_data(Z_ARRVAL_P(base_dn));
zend_hash_move_forward(Z_ARRVAL_P(base_dn));
entry = zend_hash_get_current_data(base_dn_ht);
zend_hash_move_forward(base_dn_ht);
ldap_base_dn = zval_get_string(entry);
if (EG(exception)) {
ret = 0;
goto cleanup_parallel;
}
}
if (nfilters != 0) { /* filter an array? */
entry = zend_hash_get_current_data(Z_ARRVAL_P(filter));
zend_hash_move_forward(Z_ARRVAL_P(filter));
entry = zend_hash_get_current_data(filter_ht);
zend_hash_move_forward(filter_ht);
ldap_filter = zval_get_string(entry);
if (EG(exception)) {
ret = 0;
Expand Down Expand Up @@ -1588,23 +1594,21 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
efree(lds);
efree(rcs);
} else {
ldap_filter = zval_get_string(filter);
if (EG(exception)) {
ld = (ldap_linkdata *) zend_fetch_resource_ex(link, "ldap link", le_link);
if (ld == NULL) {
ret = 0;
goto cleanup;
}

ldap_base_dn = zval_get_string(base_dn);
if (EG(exception)) {
ret = 0;
goto cleanup;
if (!base_dn_str) {
zend_argument_type_error(2, "must be of type string when argument #1 ($link_identifier) is a resource");
}
ldap_base_dn = zend_string_copy(base_dn_str);

ld = (ldap_linkdata *) zend_fetch_resource_ex(link, "ldap link", le_link);
if (ld == NULL) {
ret = 0;
goto cleanup;
if (!filter_str) {
zend_argument_type_error(3, "must be of type string when argument #1 ($link_identifier) is a resource");
}
ldap_filter = zend_string_copy(filter_str);

if (argcount > 8) {
lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls);
Expand Down
12 changes: 3 additions & 9 deletions ext/ldap/ldap.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,21 @@ function ldap_sasl_bind($link, string $binddn = UNKNOWN, string $password = UNKN

/**
* @param resource|array $link_identifier
* @param string|array $base_dn
* @param string|array $filter
* @return resource|false
*/
function ldap_read($link_identifier, $base_dn, $filter, array $attributes = [], int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $servercontrols = []) {}
function ldap_read($link_identifier, array|string $base_dn, array|string $filter, array $attributes = [], int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $servercontrols = []) {}

/**
* @param resource|array $link_identifier
* @param string|array $base_dn
* @param string|array $filter
* @return resource|false
*/
function ldap_list($link_identifier, $base_dn, $filter, array $attributes = [], int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $servercontrols = []) {}
function ldap_list($link_identifier, array|string $base_dn, array|string $filter, array $attributes = [], int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $servercontrols = []) {}

/**
* @param resource|array $link_identifier
* @param string|array $base_dn
* @param string|array $filter
* @return resource|false
*/
function ldap_search($link_identifier, $base_dn, $filter, array $attributes = [], int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $servercontrols = []) {}
function ldap_search($link_identifier, array|string $base_dn, array|string $filter, array $attributes = [], int $attrsonly = 0, int $sizelimit = -1, int $timelimit = -1, int $deref = LDAP_DEREF_NEVER, array $servercontrols = []) {}

/** @param resource $link_identifier */
function ldap_free_result($link_identifier): bool {}
Expand Down
6 changes: 3 additions & 3 deletions ext/ldap/ldap_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 6b5e8ddfbdc436fab3a263d6922146ca7c2f3845 */
* Stub hash: c247d438a69d40353a629b09c5200d33ed8218ee */

#if defined(HAVE_ORALDAP)
ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0)
Expand Down Expand Up @@ -52,8 +52,8 @@ ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3)
ZEND_ARG_INFO(0, link_identifier)
ZEND_ARG_INFO(0, base_dn)
ZEND_ARG_INFO(0, filter)
ZEND_ARG_TYPE_MASK(0, base_dn, MAY_BE_ARRAY|MAY_BE_STRING, NULL)
ZEND_ARG_TYPE_MASK(0, filter, MAY_BE_ARRAY|MAY_BE_STRING, NULL)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, attributes, IS_ARRAY, 0, "[]")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, attrsonly, IS_LONG, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, sizelimit, IS_LONG, 0, "-1")
Expand Down
2 changes: 1 addition & 1 deletion ext/pcre/tests/preg_replace_error1.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,4 @@ string(1) "a"

Arg value is /[a-zA-Z]/
string(1) "1"
preg_replace(): Argument #1 ($regex) must be of type string|array, stdClass given
preg_replace(): Argument #1 ($regex) must be of type array|string, stdClass given
2 changes: 1 addition & 1 deletion ext/pcre/tests/preg_replace_error2.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ string(64) "this is a stringthis is a stringthis is a stringthis is a string"

Arg value is: Array
preg_replace(): Argument #1 ($regex) must be of type array when argument #2 ($replace) is an array, string given
preg_replace(): Argument #2 ($replace) must be of type string|array, stdClass given
preg_replace(): Argument #2 ($replace) must be of type array|string, stdClass given
Done
2 changes: 1 addition & 1 deletion ext/phar/tests/phar_extract.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ string(2) "hi"
string(3) "hi3"
string(3) "hi2"
bool(false)
Phar::extractTo(): Argument #2 ($files) must be of type string|array|null, stdClass given
Phar::extractTo(): Argument #2 ($files) must be of type array|string|null, stdClass given
Phar::extractTo(): Argument #1 ($pathto) must be a valid path, array given
Invalid argument, extraction path must be non-zero length
Unable to use path "%soops" for extraction, it is a file, must be a directory
Expand Down
23 changes: 10 additions & 13 deletions ext/reflection/php_reflection.c
Original file line number Diff line number Diff line change
Expand Up @@ -3684,38 +3684,35 @@ ZEND_METHOD(ReflectionClassConstant, getAttributes)
/* {{{ reflection_class_object_ctor */
static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_object)
{
zval *argument;
zval *object;
zend_string *arg_class = NULL;
zend_object *arg_obj;
reflection_object *intern;
zend_class_entry *ce;

if (is_object) {
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_OBJECT(argument)
Z_PARAM_OBJ(arg_obj)
ZEND_PARSE_PARAMETERS_END();
} else {
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(argument)
Z_PARAM_STR_OR_OBJ(arg_class, arg_obj)
ZEND_PARSE_PARAMETERS_END();
}

object = ZEND_THIS;
intern = Z_REFLECTION_P(object);

if (Z_TYPE_P(argument) == IS_OBJECT) {
ZVAL_STR_COPY(reflection_prop_name(object), Z_OBJCE_P(argument)->name);
intern->ptr = Z_OBJCE_P(argument);
if (arg_obj) {
ZVAL_STR_COPY(reflection_prop_name(object), arg_obj->ce->name);
intern->ptr = arg_obj->ce;
if (is_object) {
ZVAL_COPY(&intern->obj, argument);
ZVAL_OBJ_COPY(&intern->obj, arg_obj);
}
} else {
if (!try_convert_to_string(argument)) {
RETURN_THROWS();
}

if ((ce = zend_lookup_class(Z_STR_P(argument))) == NULL) {
if ((ce = zend_lookup_class(arg_class)) == NULL) {
if (!EG(exception)) {
zend_throw_exception_ex(reflection_exception_ptr, -1, "Class \"%s\" does not exist", Z_STRVAL_P(argument));
zend_throw_exception_ex(reflection_exception_ptr, -1, "Class \"%s\" does not exist", ZSTR_VAL(arg_class));
}
RETURN_THROWS();
}
Expand Down
3 changes: 1 addition & 2 deletions ext/reflection/php_reflection.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,7 @@ class ReflectionClass implements Reflector
{
final private function __clone() {}

/** @param object|string $objectOrClass */
public function __construct($objectOrClass) {}
public function __construct(object|string $objectOrClass) {}

public function __toString(): string {}

Expand Down
Loading