Skip to content
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

Finer-grained return values from bind_textdomain_codeset() #17163

Open
orlitzky opened this issue Dec 15, 2024 · 3 comments
Open

Finer-grained return values from bind_textdomain_codeset() #17163

orlitzky opened this issue Dec 15, 2024 · 3 comments

Comments

@orlitzky
Copy link
Contributor

Description

As mentioned in php/doc-en#4311, the bind_textdomain_codeset() function returns false in some "success" cases because it is only looking at the NULL returned from the C function. But that NULL is not necessarily an error, it just means that the codeset has not changed from the default. In particular, you'll get a NULL from glibc if you query a codeset that hasn't been set yet, and you'll always get NULL on musl.

According to https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/bind_textdomain_codeset.html, the value of errno may be a better indicator:

If bind_textdomain_codeset() fails, a null pointer shall be returned and errno shall be set to indicate the error.

@cmb69
Copy link
Member

cmb69 commented Dec 15, 2024

POSIX is pretty clear here:

If domainname is a null pointer, textdomain() shall return a pointer to the string containing the current text domain.

and

If domainname is a null pointer or an empty string, bindtextdomain() shall make no changes and return a null pointer without changing errno.

If musl (or any other implementation) return NULL here, they are not conforming to the specification. And that errno is unchanged, is to be expected. What is PHP supposed to do? Just say "yeah, the call was successful" would be wrong.

@orlitzky
Copy link
Contributor Author

POSIX is pretty clear here:

I'm only talking about bind_textdomain_codeset here, not bindtextdomain or textdomain. The two relevant paragraphs are,

If codeset is a null pointer and domainname is a non-empty string, bind_textdomain_codeset() shall return the current codeset for the named domain, or a null pointer if a codeset has not yet been set.

and

If bind_textdomain_codeset() fails, a null pointer shall be returned and errno shall be set to indicate the error.

musl is still a little bit weird in that it returns NULL rather than "UTF-8" on successive calls, but if you are handling the case where the codeset has not yet been set (which affects glibc, too), then you'll do the right thing on musl too.

@cmb69
Copy link
Member

cmb69 commented Dec 15, 2024

Well, seems that #6631 had been done without much thinking; should have returned null (or maybe true) in this case.

orlitzky added a commit to orlitzky/php-src that referenced this issue Dec 15, 2024
…musl

The musl implementation of bind_textdomain_codeset() always returns
NULL. The POSIX-correctness of this is debatable, but it is roughly
equivalent to correct, because musl only support UTF-8, so the NULL
value indicating that the codeset is unchanged from the locale's
codeset (UTF-8) is accurate.

PHP's bind_textdomain_codeset() function however treats NULL as
failure, unconditionally:

  * php/doc-en#4311
  * php#17163

This unfortunately causes false to be returned consistently on musl --
even when nothing unexpected has happened -- and naturally this is
affecting several tests. For now we change two tests to accept "false"
in addition to "UTF-8" so that they may pass on musl. If PHP's
bind_textdomain_codeset() is updated to differentiate between NULL and
NULL-with-errno-set, these tests can also be updated once again to
reject the NULL-with-errno result.

This partially addresses GH php#13696
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants