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:
3
.gitignore
vendored
3
.gitignore
vendored
@ -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
4
NEWS
@ -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)
|
||||
|
||||
|
@ -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.])])])
|
||||
|
||||
|
@ -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")) {
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user