Merge branch 'PHP-8.3' into PHP-8.4

* PHP-8.3:
  NEWS for GH-17168
  ext/gettext/config.m4: symlink en_US.UTF-8 test bits to en_US for musl
  ext/gettext/tests: fix libintl return values under musl
  ext/gettext/gettext.c: handle NULLs from bindtextdomain()
This commit is contained in:
Arnaud Le Blanc
2024-12-19 18:35:48 +01:00
6 changed files with 59 additions and 13 deletions

3
.gitignore vendored
View File

@ -177,6 +177,9 @@ php
/ext/*/configure.ac
/ext/*/run-tests.php
# Generated by ./configure if libc might be musl
/ext/gettext/tests/locale/en_US
# ------------------------------------------------------------------------------
# Generated by Windows build system
# ------------------------------------------------------------------------------

4
NEWS
View File

@ -44,6 +44,10 @@ PHP NEWS
. Fixed bug GH-16255 (Unexpected nan value in ext/gd/libgd/gd_filter.c).
(nielsdos, cmb)
- Gettext:
. Fixed bug GH-17202 (Segmentation fault ext/gettext/gettext.c
bindtextdomain()). (Michael Orlitzky)
- Iconv:
. Fixed bug GH-17047 (UAF on iconv filter failure). (nielsdos)

View File

@ -23,6 +23,18 @@ if test "$PHP_GETTEXT" != "no"; then
[AC_CHECK_LIB([c], [bindtextdomain], [
GETTEXT_LIBS=
GETTEXT_CHECK_IN_LIB=c
dnl If libintl.h is provided by libc, it's possible that libc is musl.
dnl The gettext family of functions under musl ignores the codeset
dnl suffix on directories like "en_US.UTF-8"; instead they look only
dnl in "en_US". To accomodate that, we symlink some test data from one
dnl to the other.
AC_MSG_NOTICE([symlinking en_US.UTF-8 messages to en_US in case you are on musl])
_linkdest="${srcdir%/}"/ext/gettext/tests/locale/en_US
AS_IF([test ! -e "${_linkdest}"],[
ln -s en_US.UTF-8 "${_linkdest}"
])
],
[AC_MSG_FAILURE([Unable to find required intl library for gettext.])])])

View File

@ -180,7 +180,7 @@ PHP_FUNCTION(dcgettext)
PHP_FUNCTION(bindtextdomain)
{
zend_string *domain, *dir = NULL;
char *retval, dir_name[MAXPATHLEN];
char *retval, dir_name[MAXPATHLEN], *btd_result;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_STR(domain)
@ -191,7 +191,16 @@ PHP_FUNCTION(bindtextdomain)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
if (dir == NULL) {
RETURN_STRING(bindtextdomain(ZSTR_VAL(domain), NULL));
btd_result = bindtextdomain(ZSTR_VAL(domain), NULL);
if (btd_result == NULL) {
/* POSIX-compliant implementations can return
* NULL if an error occured. On musl you will
* also get NULL if the domain is not yet
* bound, because musl has no default directory
* to return in that case. */
RETURN_FALSE;
}
RETURN_STRING(btd_result);
}
if (ZSTR_LEN(dir) != 0 && !zend_string_equals_literal(dir, "0")) {

View File

@ -8,18 +8,28 @@ if (getenv('SKIP_REPEAT')) die('skip gettext leaks global state across requests'
?>
--FILE--
<?php
var_dump(is_string(bindtextdomain('foo', null)));
$results[] = is_string(bindtextdomain('foo', null));
$dir = bindtextdomain('foo', '.');
var_dump(bindtextdomain('foo', null) === $dir);
$results[] = bindtextdomain('foo', null) === $dir;
$results[] = bind_textdomain_codeset('foo', null);
$results[] = bind_textdomain_codeset('foo', 'UTF-8');
$results[] = bind_textdomain_codeset('foo', null);
var_dump(bind_textdomain_codeset('foo', null));
var_dump(bind_textdomain_codeset('foo', 'UTF-8'));
var_dump(bind_textdomain_codeset('foo', null));
$expected = [true, true, false, "UTF-8", "UTF-8"];
// musl's bindtextdomain() has no default directory to return when
// "foo" is unbound, so in the first call, you will get false instead
// of a string.
//
// bind_textdomain_codeset() always returns false on musl
// because musl only supports UTF-8. For more information:
//
// * https://github.com/php/doc-en/issues/4311,
// * https://github.com/php/php-src/issues/17163
//
$expected_musl = [false, true, false, false, false];
var_dump($results === $expected || $results === $expected_musl);
?>
--EXPECT--
bool(true)
bool(true)
bool(false)
string(5) "UTF-8"
string(5) "UTF-8"

View File

@ -15,14 +15,22 @@ gettext
} catch (ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
var_dump(bind_textdomain_codeset('messages', "UTF-8"));
// bind_textdomain_codeset() always returns false on musl
// because musl only supports UTF-8. For more information:
//
// * https://github.com/php/doc-en/issues/4311,
// * https://github.com/php/php-src/issues/17163
//
$result = bind_textdomain_codeset('messages', "UTF-8");
var_dump($result === false || $result === "UTF-8");
echo "Done\n";
?>
--EXPECT--
bind_textdomain_codeset(): Argument #1 ($domain) must not be empty
bind_textdomain_codeset(): Argument #1 ($domain) must not be empty
string(5) "UTF-8"
bool(true)
Done
--CREDITS--
Florian Holzhauer fh-pt@fholzhauer.de