From 16704249bd183140ca61a52ae750b275543911a2 Mon Sep 17 00:00:00 2001 From: Ben Ramsey Date: Wed, 11 Oct 2023 20:37:54 -0400 Subject: [PATCH] feat: validate default_locale INI value upon setting it --- src/php/ecma_intl.c | 39 +++++++++++++++++++++++++- tests/phpt/ini-default_locale-005.phpt | 2 ++ tests/phpt/ini-default_locale-006.phpt | 14 +++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 tests/phpt/ini-default_locale-006.phpt diff --git a/src/php/ecma_intl.c b/src/php/ecma_intl.c index 8dd3faa..a57b42b 100644 --- a/src/php/ecma_intl.c +++ b/src/php/ecma_intl.c @@ -31,8 +31,10 @@ #include #include +static ZEND_INI_MH(onUpdateLocale); + PHP_INI_BEGIN() -PHP_INI_ENTRY(PHP_ECMA_INI_DEFAULT_LOCALE, "", PHP_INI_ALL, NULL) +PHP_INI_ENTRY(PHP_ECMA_INI_DEFAULT_LOCALE, "", PHP_INI_ALL, onUpdateLocale) PHP_INI_END() zend_module_entry ecma_intl_module_entry = {STANDARD_MODULE_HEADER, @@ -108,3 +110,38 @@ PHP_MINFO_FUNCTION(ecma_intl) DISPLAY_INI_ENTRIES(); } + +static ZEND_INI_MH(onUpdateLocale) +{ + zend_result result = FAILURE; + + if (!new_value || (new_value && !ZSTR_VAL(new_value)[0])) { + return result; + } + + char **available, *bestAvailable, *canonicalized; + size_t total, length; + ecma402_errorStatus *status; + + available = (char **)malloc(sizeof(char *) * uloc_countAvailable()); + bestAvailable = (char *)malloc(sizeof(char) * ULOC_FULLNAME_CAPACITY); + total = ecma402_intlAvailableLocales(available); + + if (ecma402_bestAvailableLocale(available, total, ZSTR_VAL(new_value), bestAvailable, false) > 0) { + status = ecma402_initErrorStatus(); + canonicalized = (char *)malloc(sizeof(char) * ULOC_FULLNAME_CAPACITY); + length = ecma402_canonicalizeUnicodeLocaleId(bestAvailable, canonicalized, status); + + if (!ecma402_hasError(status) && length > 0) { + result = SUCCESS; + } + + free(canonicalized); + ecma402_freeErrorStatus(status); + } + + free(bestAvailable); + free(available); + + return result; +} diff --git a/tests/phpt/ini-default_locale-005.phpt b/tests/phpt/ini-default_locale-005.phpt index c7c971d..c0638dd 100644 --- a/tests/phpt/ini-default_locale-005.phpt +++ b/tests/phpt/ini-default_locale-005.phpt @@ -10,6 +10,7 @@ declare(strict_types=1); var_dump(ini_set('ecma_intl.default_locale', 'en-US')); var_dump(ini_set('ecma_intl.default_locale', 'en_US')); +var_dump(ini_set('ecma_intl.default_locale', 'foobar')); var_dump(ini_set('ecma_intl.default_locale', 'en-Latn-US')); var_dump(ini_set('ecma_intl.default_locale', 'en-US-POSIX')); var_dump(ini_set('ecma_intl.default_locale', 'en_US_POSIX')); @@ -19,6 +20,7 @@ var_dump(ini_get('ecma_intl.default_locale')); --EXPECT-- string(0) "" string(5) "en-US" +bool(false) string(5) "en_US" string(10) "en-Latn-US" string(11) "en-US-POSIX" diff --git a/tests/phpt/ini-default_locale-006.phpt b/tests/phpt/ini-default_locale-006.phpt new file mode 100644 index 0000000..2a14e3e --- /dev/null +++ b/tests/phpt/ini-default_locale-006.phpt @@ -0,0 +1,14 @@ +--TEST-- +ecma_intl.default_locale has an empty string when set to an invalid value +--EXTENSIONS-- +ecma_intl +--INI-- +ecma_intl.default_locale=foobar +--FILE-- +