From a6d6b5c4b647b69d9521662df8584a7d2749a915 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 3 Mar 2024 11:53:49 +0000 Subject: [PATCH 1/3] ext/gettext: update arguments handling. using zend_string whenever relevant too. --- ext/gettext/gettext.c | 133 +++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 55 deletions(-) diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index 8518a80520b55..93af9ecaca030 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -81,12 +81,13 @@ PHP_MINFO_FUNCTION(php_gettext) /* {{{ Set the textdomain to "domain". Returns the current domain */ PHP_FUNCTION(textdomain) { - char *domain_name = NULL, *retval; + char *retval = NULL, *domain_name = NULL; zend_string *domain = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "S!", &domain) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(domain) + ZEND_PARSE_PARAMETERS_END(); if (domain != NULL) { PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) @@ -105,7 +106,7 @@ PHP_FUNCTION(textdomain) /* {{{ Return the translation of msgid for the current domain, or msgid unaltered if a translation does not exist */ PHP_FUNCTION(gettext) { - char *msgstr; + char *msgstr = NULL; zend_string *msgid; ZEND_PARSE_PARAMETERS_START(1, 1) @@ -126,12 +127,13 @@ PHP_FUNCTION(gettext) /* {{{ Return the translation of msgid for domain_name, or msgid unaltered if a translation does not exist */ PHP_FUNCTION(dgettext) { - char *msgstr; + char *msgstr = NULL; zend_string *domain, *msgid; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &domain, &msgid) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_STR(domain) + Z_PARAM_STR(msgid) + ZEND_PARSE_PARAMETERS_END(); PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid)) @@ -149,13 +151,15 @@ PHP_FUNCTION(dgettext) /* {{{ Return the translation of msgid for domain_name and category, or msgid unaltered if a translation does not exist */ PHP_FUNCTION(dcgettext) { - char *msgstr; + char *msgstr = NULL; zend_string *domain, *msgid; zend_long category; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSl", &domain, &msgid, &category) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(domain) + Z_PARAM_STR(msgid) + Z_PARAM_LONG(category) + ZEND_PARSE_PARAMETERS_END(); PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid)) @@ -174,19 +178,24 @@ PHP_FUNCTION(dcgettext) /* {{{ Bind to the text domain domain_name, looking for translations in dir. Returns the current domain */ PHP_FUNCTION(bindtextdomain) { - char *domain; - size_t domain_len; - zend_string *dir = NULL; + zend_string *domain, *dir = NULL; char *retval, dir_name[MAXPATHLEN]; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sS!", &domain, &domain_len, &dir) == FAILURE) { + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(domain) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(dir) + ZEND_PARSE_PARAMETERS_END(); + + PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) + + if (!ZSTR_LEN(domain)) { + zend_argument_value_error(1, "cannot be empty"); RETURN_THROWS(); } - PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len) - if (dir == NULL) { - RETURN_STRING(bindtextdomain(domain, NULL)); + RETURN_STRING(bindtextdomain(ZSTR_VAL(domain), NULL)); } if (ZSTR_LEN(dir) != 0 && !zend_string_equals_literal(dir, "0")) { @@ -197,7 +206,7 @@ PHP_FUNCTION(bindtextdomain) RETURN_FALSE; } - retval = bindtextdomain(domain, dir_name); + retval = bindtextdomain(ZSTR_VAL(domain), dir_name); RETURN_STRING(retval); } @@ -207,18 +216,20 @@ PHP_FUNCTION(bindtextdomain) /* {{{ Plural version of gettext() */ PHP_FUNCTION(ngettext) { - char *msgid1, *msgid2, *msgstr; - size_t msgid1_len, msgid2_len; + char *msgstr = NULL; + zend_string *msgid1, *msgid2; zend_long count; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssl", &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_STR(msgid1) + Z_PARAM_STR(msgid2) + Z_PARAM_LONG(count) + ZEND_PARSE_PARAMETERS_END(); - PHP_GETTEXT_LENGTH_CHECK(1, msgid1_len) - PHP_GETTEXT_LENGTH_CHECK(2, msgid2_len) + PHP_GETTEXT_LENGTH_CHECK(1, ZSTR_LEN(msgid1)) + PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid2)) - msgstr = ngettext(msgid1, msgid2, count); + msgstr = ngettext(ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count); ZEND_ASSERT(msgstr); RETURN_STRING(msgstr); @@ -230,20 +241,22 @@ PHP_FUNCTION(ngettext) /* {{{ Plural version of dgettext() */ PHP_FUNCTION(dngettext) { - char *domain, *msgid1, *msgid2, *msgstr = NULL; - size_t domain_len, msgid1_len, msgid2_len; + char *msgstr = NULL; + zend_string *domain, *msgid1, *msgid2; zend_long count; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssl", &domain, &domain_len, - &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(4, 4) + Z_PARAM_STR(domain) + Z_PARAM_STR(msgid1) + Z_PARAM_STR(msgid2) + Z_PARAM_LONG(count) + ZEND_PARSE_PARAMETERS_END(); - PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len) - PHP_GETTEXT_LENGTH_CHECK(2, msgid1_len) - PHP_GETTEXT_LENGTH_CHECK(3, msgid2_len) + PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) + PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid1)) + PHP_GETTEXT_LENGTH_CHECK(3, ZSTR_LEN(msgid2)) - msgstr = dngettext(domain, msgid1, msgid2, count); + msgstr = dngettext(ZSTR_VAL(domain), ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count); ZEND_ASSERT(msgstr); RETURN_STRING(msgstr); @@ -255,23 +268,26 @@ PHP_FUNCTION(dngettext) /* {{{ Plural version of dcgettext() */ PHP_FUNCTION(dcngettext) { - char *domain, *msgid1, *msgid2, *msgstr = NULL; - size_t domain_len, msgid1_len, msgid2_len; + char *msgstr = NULL; + zend_string *domain, *msgid1, *msgid2; zend_long count, category; RETVAL_FALSE; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssll", &domain, &domain_len, - &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count, &category) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(5, 5) + Z_PARAM_STR(domain) + Z_PARAM_STR(msgid1) + Z_PARAM_STR(msgid2) + Z_PARAM_LONG(count) + Z_PARAM_LONG(category) + ZEND_PARSE_PARAMETERS_END(); - PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len) - PHP_GETTEXT_LENGTH_CHECK(2, msgid1_len) - PHP_GETTEXT_LENGTH_CHECK(3, msgid2_len) + PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) + PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid1)) + PHP_GETTEXT_LENGTH_CHECK(3, ZSTR_LEN(msgid2)) PHP_DCGETTEXT_CATEGORY_CHECK(5, category) - msgstr = dcngettext(domain, msgid1, msgid2, count, category); + msgstr = dcngettext(ZSTR_VAL(domain), ZSTR_VAL(msgid1), ZSTR_VAL(msgid2), count, category); ZEND_ASSERT(msgstr); RETURN_STRING(msgstr); @@ -284,16 +300,23 @@ PHP_FUNCTION(dcngettext) /* {{{ Specify the character encoding in which the messages from the DOMAIN message catalog will be returned. */ PHP_FUNCTION(bind_textdomain_codeset) { - char *domain, *codeset = NULL, *retval = NULL; - size_t domain_len, codeset_len; + char *retval = NULL; + zend_string *domain, *codeset = NULL; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(domain) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(codeset) + ZEND_PARSE_PARAMETERS_END(); + + PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) - if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss!", &domain, &domain_len, &codeset, &codeset_len) == FAILURE) { + if (!ZSTR_LEN(domain)) { + zend_argument_value_error(1, "cannot be empty"); RETURN_THROWS(); } - PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len) - - retval = bind_textdomain_codeset(domain, codeset); + retval = bind_textdomain_codeset(ZSTR_VAL(domain), codeset ? ZSTR_VAL(codeset) : NULL); if (!retval) { RETURN_FALSE; From 1d4d9274105e14a74f7506f2172540e80e590181 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 3 Mar 2024 13:52:44 +0000 Subject: [PATCH 2/3] fix signatures --- ext/gettext/gettext.stub.php | 6 +++--- ext/gettext/gettext_arginfo.h | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/gettext/gettext.stub.php b/ext/gettext/gettext.stub.php index ec6b197c0d77a..3e9a50177a592 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): string {} +function textdomain(?string $domain = null): string {} /** @refcount 1 */ function gettext(string $message): string {} @@ -18,7 +18,7 @@ function dgettext(string $domain, string $message): string {} function dcgettext(string $domain, string $message, int $category): string {} /** @refcount 1 */ -function bindtextdomain(string $domain, ?string $directory): string|false {} +function bindtextdomain(string $domain, ?string $directory = null): string|false {} #ifdef HAVE_NGETTEXT /** @refcount 1 */ @@ -37,5 +37,5 @@ function dcngettext(string $domain, string $singular, string $plural, int $count #ifdef HAVE_BIND_TEXTDOMAIN_CODESET /** @refcount 1 */ -function bind_textdomain_codeset(string $domain, ?string $codeset): string|false {} +function bind_textdomain_codeset(string $domain, ?string $codeset = null): string|false {} #endif diff --git a/ext/gettext/gettext_arginfo.h b/ext/gettext/gettext_arginfo.h index 8b2d7712dc87e..265f6cd900edc 100644 --- a/ext/gettext/gettext_arginfo.h +++ b/ext/gettext/gettext_arginfo.h @@ -1,8 +1,8 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 864b3389d4f99b0d7302ae399544e6fb9fb80b7e */ + * Stub hash: c675dc9492943bbac106c5906b75c31436964423 */ -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_textdomain, 0, 1, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 1) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_textdomain, 0, 0, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, domain, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gettext, 0, 1, IS_STRING, 0) @@ -22,9 +22,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dcgettext, 0, 3, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, category, IS_LONG, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bindtextdomain, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bindtextdomain, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, directory, IS_STRING, 1) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, directory, IS_STRING, 1, "null") ZEND_END_ARG_INFO() #if defined(HAVE_NGETTEXT) @@ -55,9 +55,9 @@ ZEND_END_ARG_INFO() #endif #if defined(HAVE_BIND_TEXTDOMAIN_CODESET) -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bind_textdomain_codeset, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_bind_textdomain_codeset, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, codeset, IS_STRING, 1) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, codeset, IS_STRING, 1, "null") ZEND_END_ARG_INFO() #endif From b0aaf4ce00a67ab3df8c38844022d5a82aa31198 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 28 Apr 2024 21:59:57 +0100 Subject: [PATCH 3/3] changes from feedback --- ext/gettext/gettext.c | 9 +++++---- ext/gettext/tests/gettext_textdomain-retval.phpt | 7 +++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index 93af9ecaca030..a921070197020 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -81,7 +81,7 @@ PHP_MINFO_FUNCTION(php_gettext) /* {{{ Set the textdomain to "domain". Returns the current domain */ PHP_FUNCTION(textdomain) { - char *retval = NULL, *domain_name = NULL; + char *domain_name = NULL, *retval = NULL; zend_string *domain = NULL; ZEND_PARSE_PARAMETERS_START(0, 1) @@ -91,9 +91,10 @@ PHP_FUNCTION(textdomain) if (domain != NULL) { PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain)) - } - - if (domain != NULL && !zend_string_equals_literal(domain, "0")) { + if (zend_string_equals_literal(domain, "0")) { + zend_argument_value_error(1, "cannot be zero"); + RETURN_THROWS(); + } domain_name = ZSTR_VAL(domain); } diff --git a/ext/gettext/tests/gettext_textdomain-retval.phpt b/ext/gettext/tests/gettext_textdomain-retval.phpt index 172a0069afc7f..96b29c7bf946c 100644 --- a/ext/gettext/tests/gettext_textdomain-retval.phpt +++ b/ext/gettext/tests/gettext_textdomain-retval.phpt @@ -19,6 +19,12 @@ echo textdomain('test'), "\n"; echo textdomain(null), "\n"; echo textdomain('foo'), "\n"; +try { + textdomain('0'); +} catch (\ValueError $e) { + echo $e->getMessage() . PHP_EOL; +} + try { textdomain(''); } catch (\ValueError $e) { @@ -29,6 +35,7 @@ try { test test foo +textdomain(): Argument #1 ($domain) cannot be zero textdomain(): Argument #1 ($domain) cannot be empty --CREDITS-- Christian Weiske, cweiske@php.net