From 9999a0cb757344974889a6f548727de6f2c3c10d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 28 Feb 2024 22:43:04 +0000 Subject: [PATCH] ext/gettext: dcgettext/dcngettext sigabrt on macOs. the man page states `the locale facet is determined by the category argument, which should be one of the LC_xxx constants defined in the header, excluding LC_ALL`, since the 0.22.5 release, sanity checks had been strenghtened leading to an abort with the Zend/tests/arginfo_zpp_mismatch.phpt test setting the category to 0 which is LC_ALL on macOs. close GH-13555 --- NEWS | 4 ++++ UPGRADING | 4 ++++ ext/gettext/gettext.c | 9 +++++++++ ext/gettext/tests/dcgettext_lcall.phpt | 21 +++++++++++++++++++++ ext/gettext/tests/dcngettext.phpt | 4 ++-- 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 ext/gettext/tests/dcgettext_lcall.phpt diff --git a/NEWS b/NEWS index c7be80af560..2de10b7bc03 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.2.18 +- Gettext: + - Fixed sigabrt raised with dcgettext/dcngettext calls with gettext 0.22.5 + with category set to LC_ALL. (David Carlier) + - MySQLnd: . Fix GH-13452 (Fixed handshake response [mysqlnd]). (Saki Takamachi) diff --git a/UPGRADING b/UPGRADING index efa74cb42cf..de91433d8d2 100644 --- a/UPGRADING +++ b/UPGRADING @@ -218,6 +218,10 @@ PHP 8.2 UPGRADE NOTES dba_fetch(string|array $key, $skip, $dba): string|false is still accepted, but it is recommended to use the new standard variant. +- Gettext: + . dcgettext/dcngettext throw now an exception if the category's argument if set to + `LC_ALL`. + - MBString . mb_check_encoding() now checks input encoding more strictly for certain text encodings, including ISO-2022-JP and UTF-7. diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index 05f41552c63..e7928795b27 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -23,6 +23,7 @@ #ifdef HAVE_LIBINTL #include +#include #include "ext/standard/info.h" #include "php_gettext.h" #include "gettext_arginfo.h" @@ -61,6 +62,12 @@ ZEND_GET_MODULE(php_gettext) RETURN_THROWS(); \ } +#define PHP_DCGETTEXT_CATEGORY_CHECK(_arg_num, category) \ + if (category == LC_ALL) { \ + zend_argument_value_error(_arg_num, "cannot be LC_ALL"); \ + RETURN_THROWS(); \ + } + PHP_MINFO_FUNCTION(php_gettext) { php_info_print_table_start(); @@ -146,6 +153,7 @@ PHP_FUNCTION(dcgettext) PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid)) + PHP_DCGETTEXT_CATEGORY_CHECK(3, category) msgstr = dcgettext(ZSTR_VAL(domain), ZSTR_VAL(msgid), category); @@ -260,6 +268,7 @@ PHP_FUNCTION(dcngettext) PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len) PHP_GETTEXT_LENGTH_CHECK(2, msgid1_len) PHP_GETTEXT_LENGTH_CHECK(3, msgid2_len) + PHP_DCGETTEXT_CATEGORY_CHECK(5, category) msgstr = dcngettext(domain, msgid1, msgid2, count, category); diff --git a/ext/gettext/tests/dcgettext_lcall.phpt b/ext/gettext/tests/dcgettext_lcall.phpt new file mode 100644 index 00000000000..004ae89409e --- /dev/null +++ b/ext/gettext/tests/dcgettext_lcall.phpt @@ -0,0 +1,21 @@ +--TEST-- +dcgettext with LC_ALL is undefined behavior. +--EXTENSIONS-- +gettext +--FILE-- +getMessage() . PHP_EOL; +} + +try { + dcngettext('dngettextTest', 'item', 'item2', 1, LC_ALL); +} catch (ValueError $e) { + echo $e->getMessage(); +} +?> +--EXPECTF-- +dcgettext(): Argument #3 ($category) cannot be LC_ALL +dcngettext(): Argument #5 ($category) cannot be LC_ALL diff --git a/ext/gettext/tests/dcngettext.phpt b/ext/gettext/tests/dcngettext.phpt index 715281ec829..2f356b1cf0c 100644 --- a/ext/gettext/tests/dcngettext.phpt +++ b/ext/gettext/tests/dcngettext.phpt @@ -11,10 +11,10 @@ if (!function_exists("dcngettext")) die("skip dcngettext() doesn't exist"); var_dump(dcngettext(1,1,1,1,1)); var_dump(dcngettext("test","test","test",1,1)); -var_dump(dcngettext("test","test","test",0,0)); +var_dump(dcngettext("test","test","test",0,1)); var_dump(dcngettext("test","test","test",-1,-1)); var_dump(dcngettext("","","",1,1)); -var_dump(dcngettext("","","",0,0)); +var_dump(dcngettext("","","",0,1)); echo "Done\n"; ?>