From b7039f2e8ba16e7792084ecece81733c0ba04b72 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 26 Apr 2026 20:46:48 -0400 Subject: [PATCH] ext/gettext: return false from textdomain() and bindtextdomain() on NULL Both functions can return NULL on libintl-internal allocation failure. The PHP wrappers passed the result directly to RETURN_STRING, which calls strlen(NULL) and segfaults. Mirrors 0221ceeccd4, which closed the same gap for bindtextdomain($domain, NULL). textdomain()'s return type widens from string to string|false. --- Zend/Optimizer/zend_func_infos.h | 2 +- ext/gettext/gettext.c | 6 ++++++ ext/gettext/gettext.stub.php | 2 +- ext/gettext/gettext_arginfo.h | 4 ++-- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Zend/Optimizer/zend_func_infos.h b/Zend/Optimizer/zend_func_infos.h index df175ea0a5fb..870702b82e25 100644 --- a/Zend/Optimizer/zend_func_infos.h +++ b/Zend/Optimizer/zend_func_infos.h @@ -145,7 +145,7 @@ static const func_info_t func_infos[] = { F1("imageaffinematrixget", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_DOUBLE|MAY_BE_FALSE), F1("imageaffinematrixconcat", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_DOUBLE|MAY_BE_FALSE), F1("imageresolution", MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_LONG|MAY_BE_ARRAY_OF_LONG|MAY_BE_TRUE), - F1("textdomain", MAY_BE_STRING), + F1("textdomain", MAY_BE_STRING|MAY_BE_FALSE), F1("gettext", MAY_BE_STRING), F1("dgettext", MAY_BE_STRING), F1("dcgettext", MAY_BE_STRING), diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index 27f0dfa26da7..e55ae4e497b4 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -99,6 +99,9 @@ PHP_FUNCTION(textdomain) } retval = textdomain(domain_name); + if (retval == NULL) { + RETURN_FALSE; + } RETURN_STRING(retval); } @@ -212,6 +215,9 @@ PHP_FUNCTION(bindtextdomain) } retval = bindtextdomain(ZSTR_VAL(domain), dir_name); + if (retval == NULL) { + RETURN_FALSE; + } RETURN_STRING(retval); } diff --git a/ext/gettext/gettext.stub.php b/ext/gettext/gettext.stub.php index 3e9a50177a59..3ffa16deca6c 100644 --- a/ext/gettext/gettext.stub.php +++ b/ext/gettext/gettext.stub.php @@ -3,7 +3,7 @@ /** @generate-class-entries */ /** @refcount 1 */ -function textdomain(?string $domain = null): string {} +function textdomain(?string $domain = null): string|false {} /** @refcount 1 */ function gettext(string $message): string {} diff --git a/ext/gettext/gettext_arginfo.h b/ext/gettext/gettext_arginfo.h index 265f6cd900ed..41731e9fd481 100644 --- a/ext/gettext/gettext_arginfo.h +++ b/ext/gettext/gettext_arginfo.h @@ -1,7 +1,7 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: c675dc9492943bbac106c5906b75c31436964423 */ + * Stub hash: b1c7a312db33df1f8b09c58284dfa4ba5892df68 */ -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_textdomain, 0, 0, IS_STRING, 0) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_textdomain, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, domain, IS_STRING, 1, "null") ZEND_END_ARG_INFO()