Skip to content

Fix GH-18823: setlocale's 2nd and 3rd argument ignores strict_types #18828

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

nielsdos
Copy link
Member

No description provided.

@nielsdos nielsdos requested a review from bukka as a code owner June 10, 2025 18:15
@nielsdos nielsdos linked an issue Jun 10, 2025 that may be closed by this pull request
@divinity76
Copy link
Contributor

divinity76 commented Jun 10, 2025

Nitpick, don't use u32, use size_t.
Using u32 leads to bugs like https://bugs.php.net/bug.php?id=80523 (where 64bit php would choke on source code above 4GB)

@nielsdos
Copy link
Member Author

The argument count is 32-bits.

@divinity76
Copy link
Contributor

Reminds me of a famous quote attributed to Bill Gates,

4.2 billion arguments ought to be enough for anybody!

Ok nevermind.

Code LGTM!

@divinity76

This comment was marked as outdated.

@nielsdos
Copy link
Member Author

I believe promotion rules turn it into an unsigned number, but indeed should be unsigned. I'll change it

Copy link
Member

@DanielEScherzer DanielEScherzer left a comment

Choose a reason for hiding this comment

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

My reading of https://www.php.net/manual/en/function.setlocale.php is that you can either use

  • setlocale(int $category, string $locales, string ...$rest) where argument 2, 3, etc. are strings
  • setlocale(int $category, array $locale_array) where argument 2 is an array and there is no argument 3

and so I would expect error for the third argument to just say string, not array|string.

But, looking at the code it appears that any of the subsequent parameters can be an array - is that correct, and the documentation is wrong? Or is that unintended?

Should the types of the values in the array also be checked?

@nielsdos
Copy link
Member Author

nielsdos commented Jun 11, 2025

Any arg can be an array here so the docs are simply wrong. We should change the docs to match the C sources because we consider the C sources as the source of truth.
Coercion inside arrays is the de facto norm, but no strong feelings there.

Copy link
Member

@Girgias Girgias left a comment

Choose a reason for hiding this comment

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

This doesn't cover all cases.

For some other references:

Comment on lines 4936 to 4943
if (ZEND_ARG_USES_STRICT_TYPES()) {
for (uint32_t i = 0; i < num_args; i++) {
if (UNEXPECTED(Z_TYPE(args[i]) != IS_ARRAY && Z_TYPE(args[i]) != IS_STRING)) {
zend_wrong_parameter_type_error(i + 2, Z_EXPECTED_ARRAY_OR_STRING, &args[i]);
RETURN_THROWS();
}
}
}
Copy link
Member

@Girgias Girgias Jun 12, 2025

Choose a reason for hiding this comment

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

This doesn't cover the case where a non-stringable object is passed as argument, nor a resource, or null. (in weak mode)

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 first was confused by your comment, but you mean the coercions in weak mode are not done a priori and thus there is also no proper error handling of that.
I suppose we can call zend_parse_arg_str ourselves and do the coercions upfront instead of in try_setlocale_zval.

Copy link
Member

Choose a reason for hiding this comment

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

That and also types that should be rejected by our normal semantics were not :)

@nielsdos
Copy link
Member Author

nielsdos commented Jun 12, 2025

Test fails on arm, probably because of weak mode coercion changes, probably due to the deprecation now being emitted and the diff algorithm also seems confused as usual.
EDIT: that was indeed the reason

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

setlocale's 2nd and 3rd argument ignores strict_types
4 participants