Skip to content

Commit 4b1c3cf

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: 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()
2 parents 6a01549 + 73857e6 commit 4b1c3cf

File tree

5 files changed

+55
-13
lines changed

5 files changed

+55
-13
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ php
177177
/ext/*/configure.ac
178178
/ext/*/run-tests.php
179179

180+
# Generated by ./configure if libc might be musl
181+
/ext/gettext/tests/locale/en_US
182+
180183
# ------------------------------------------------------------------------------
181184
# Generated by Windows build system
182185
# ------------------------------------------------------------------------------

ext/gettext/config.m4

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

ext/gettext/gettext.c

+11-2
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ PHP_FUNCTION(dcgettext)
180180
PHP_FUNCTION(bindtextdomain)
181181
{
182182
zend_string *domain, *dir = NULL;
183-
char *retval, dir_name[MAXPATHLEN];
183+
char *retval, dir_name[MAXPATHLEN], *btd_result;
184184

185185
ZEND_PARSE_PARAMETERS_START(1, 2)
186186
Z_PARAM_STR(domain)
@@ -191,7 +191,16 @@ PHP_FUNCTION(bindtextdomain)
191191
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
192192

193193
if (dir == NULL) {
194-
RETURN_STRING(bindtextdomain(ZSTR_VAL(domain), NULL));
194+
btd_result = bindtextdomain(ZSTR_VAL(domain), NULL);
195+
if (btd_result == NULL) {
196+
/* POSIX-compliant implementations can return
197+
* NULL if an error occured. On musl you will
198+
* also get NULL if the domain is not yet
199+
* bound, because musl has no default directory
200+
* to return in that case. */
201+
RETURN_FALSE;
202+
}
203+
RETURN_STRING(btd_result);
195204
}
196205

197206
if (ZSTR_LEN(dir) != 0 && !zend_string_equals_literal(dir, "0")) {

ext/gettext/tests/bug53251.phpt

+19-9
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,28 @@ if (getenv('SKIP_REPEAT')) die('skip gettext leaks global state across requests'
88
?>
99
--FILE--
1010
<?php
11-
var_dump(is_string(bindtextdomain('foo', null)));
11+
$results[] = is_string(bindtextdomain('foo', null));
1212
$dir = bindtextdomain('foo', '.');
13-
var_dump(bindtextdomain('foo', null) === $dir);
13+
$results[] = bindtextdomain('foo', null) === $dir;
14+
$results[] = bind_textdomain_codeset('foo', null);
15+
$results[] = bind_textdomain_codeset('foo', 'UTF-8');
16+
$results[] = bind_textdomain_codeset('foo', null);
1417

15-
var_dump(bind_textdomain_codeset('foo', null));
16-
var_dump(bind_textdomain_codeset('foo', 'UTF-8'));
17-
var_dump(bind_textdomain_codeset('foo', null));
18+
$expected = [true, true, false, "UTF-8", "UTF-8"];
1819

20+
// musl's bindtextdomain() has no default directory to return when
21+
// "foo" is unbound, so in the first call, you will get false instead
22+
// of a string.
23+
//
24+
// bind_textdomain_codeset() always returns false on musl
25+
// because musl only supports UTF-8. For more information:
26+
//
27+
// * https://github.com/php/doc-en/issues/4311,
28+
// * https://github.com/php/php-src/issues/17163
29+
//
30+
$expected_musl = [false, true, false, false, false];
31+
32+
var_dump($results === $expected || $results === $expected_musl);
1933
?>
2034
--EXPECT--
2135
bool(true)
22-
bool(true)
23-
bool(false)
24-
string(5) "UTF-8"
25-
string(5) "UTF-8"

ext/gettext/tests/gettext_bind_textdomain_codeset-retval.phpt

+10-2
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@ gettext
1515
} catch (ValueError $e) {
1616
echo $e->getMessage() . PHP_EOL;
1717
}
18-
var_dump(bind_textdomain_codeset('messages', "UTF-8"));
18+
19+
// bind_textdomain_codeset() always returns false on musl
20+
// because musl only supports UTF-8. For more information:
21+
//
22+
// * https://github.com/php/doc-en/issues/4311,
23+
// * https://github.com/php/php-src/issues/17163
24+
//
25+
$result = bind_textdomain_codeset('messages', "UTF-8");
26+
var_dump($result === false || $result === "UTF-8");
1927

2028
echo "Done\n";
2129
?>
2230
--EXPECT--
2331
bind_textdomain_codeset(): Argument #1 ($domain) must not be empty
2432
bind_textdomain_codeset(): Argument #1 ($domain) must not be empty
25-
string(5) "UTF-8"
33+
bool(true)
2634
Done
2735
--CREDITS--
2836
Florian Holzhauer [email protected]

0 commit comments

Comments
 (0)