Skip to content

Commit

Permalink
Promote warnings to exceptions in ext/gettext, ext/sysvmsg and ext/xml
Browse files Browse the repository at this point in the history
Closes GH-5926
  • Loading branch information
kocsismate committed Aug 3, 2020
1 parent 0c238ed commit 4c89ed6
Show file tree
Hide file tree
Showing 16 changed files with 218 additions and 160 deletions.
48 changes: 24 additions & 24 deletions ext/gettext/gettext.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,16 @@ ZEND_GET_MODULE(php_gettext)
#define PHP_GETTEXT_MAX_DOMAIN_LENGTH 1024
#define PHP_GETTEXT_MAX_MSGID_LENGTH 4096

#define PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len) \
#define PHP_GETTEXT_DOMAIN_LENGTH_CHECK(_arg_num, domain_len) \
if (UNEXPECTED(domain_len > PHP_GETTEXT_MAX_DOMAIN_LENGTH)) { \
php_error_docref(NULL, E_WARNING, "Domain passed too long"); \
RETURN_FALSE; \
zend_argument_value_error(_arg_num, "is too long"); \
RETURN_THROWS(); \
}

#define PHP_GETTEXT_LENGTH_CHECK(check_name, check_len) \
#define PHP_GETTEXT_LENGTH_CHECK(_arg_num, check_len) \
if (UNEXPECTED(check_len > PHP_GETTEXT_MAX_MSGID_LENGTH)) { \
php_error_docref(NULL, E_WARNING, "%s passed too long", check_name); \
RETURN_FALSE; \
zend_argument_value_error(_arg_num, "is too long"); \
RETURN_THROWS(); \
}

PHP_MINFO_FUNCTION(php_gettext)
Expand All @@ -78,7 +78,7 @@ PHP_FUNCTION(textdomain)
RETURN_THROWS();
}

PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)

if (domain != NULL && strcmp(domain, "") && strcmp(domain, "0")) {
domain_name = domain;
Expand All @@ -102,7 +102,7 @@ PHP_FUNCTION(gettext)
Z_PARAM_STR(msgid)
ZEND_PARSE_PARAMETERS_END();

PHP_GETTEXT_LENGTH_CHECK("msgid", ZSTR_LEN(msgid))
PHP_GETTEXT_LENGTH_CHECK(1, ZSTR_LEN(msgid))
msgstr = gettext(ZSTR_VAL(msgid));

if (msgstr != ZSTR_VAL(msgid)) {
Expand All @@ -123,8 +123,8 @@ PHP_FUNCTION(dgettext)
RETURN_THROWS();
}

PHP_GETTEXT_DOMAIN_LENGTH_CHECK(ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK("msgid", ZSTR_LEN(msgid))
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid))

msgstr = dgettext(ZSTR_VAL(domain), ZSTR_VAL(msgid));

Expand All @@ -147,8 +147,8 @@ PHP_FUNCTION(dcgettext)
RETURN_THROWS();
}

PHP_GETTEXT_DOMAIN_LENGTH_CHECK(ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK("msgid", ZSTR_LEN(msgid))
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, ZSTR_LEN(domain))
PHP_GETTEXT_LENGTH_CHECK(2, ZSTR_LEN(msgid))

msgstr = dcgettext(ZSTR_VAL(domain), ZSTR_VAL(msgid), category);

Expand All @@ -171,11 +171,11 @@ PHP_FUNCTION(bindtextdomain)
RETURN_THROWS();
}

PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)

if (domain[0] == '\0') {
php_error(E_WARNING, "The first parameter of bindtextdomain must not be empty");
RETURN_FALSE;
zend_argument_value_error(1, "cannot be empty");
RETURN_THROWS();
}

if (dir[0] != '\0' && strcmp(dir, "0")) {
Expand Down Expand Up @@ -204,8 +204,8 @@ PHP_FUNCTION(ngettext)
RETURN_THROWS();
}

PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
PHP_GETTEXT_LENGTH_CHECK(1, msgid1_len)
PHP_GETTEXT_LENGTH_CHECK(2, msgid2_len)

msgstr = ngettext(msgid1, msgid2, count);

Expand All @@ -228,9 +228,9 @@ PHP_FUNCTION(dngettext)
RETURN_THROWS();
}

PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)
PHP_GETTEXT_LENGTH_CHECK(2, msgid1_len)
PHP_GETTEXT_LENGTH_CHECK(3, msgid2_len)

msgstr = dngettext(domain, msgid1, msgid2, count);

Expand All @@ -255,9 +255,9 @@ PHP_FUNCTION(dcngettext)
RETURN_THROWS();
}

PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
PHP_GETTEXT_LENGTH_CHECK("msgid1", msgid1_len)
PHP_GETTEXT_LENGTH_CHECK("msgid2", msgid2_len)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)
PHP_GETTEXT_LENGTH_CHECK(2, msgid1_len)
PHP_GETTEXT_LENGTH_CHECK(3, msgid2_len)

msgstr = dcngettext(domain, msgid1, msgid2, count, category);

Expand All @@ -279,7 +279,7 @@ PHP_FUNCTION(bind_textdomain_codeset)
RETURN_THROWS();
}

PHP_GETTEXT_DOMAIN_LENGTH_CHECK(domain_len)
PHP_GETTEXT_DOMAIN_LENGTH_CHECK(1, domain_len)

retval = bind_textdomain_codeset(domain, codeset);

Expand Down
18 changes: 9 additions & 9 deletions ext/gettext/gettext.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@

/** @generate-function-entries */

function textdomain(?string $domain): string|false {}
function textdomain(?string $domain): string {}

function gettext(string $msgid): string|false {}
function gettext(string $msgid): string {}

/** @alias gettext */
function _(string $msgid): string|false {}
function _(string $msgid): string {}

function dgettext(string $domain_name, string $msgid): string|false {}
function dgettext(string $domain, string $msgid): string {}

function dcgettext(string $domain_name, string $msgid, int $category): string|false {}
function dcgettext(string $domain, string $msgid, int $category): string {}

function bindtextdomain(string $domain_name, string $dir): string|false {}
function bindtextdomain(string $domain, string $dir): string|false {}

#ifdef HAVE_NGETTEXT
function ngettext(string $msgid1, string $msgid2, int $n): string|false {}
function ngettext(string $msgid1, string $msgid2, int $n): string {}
#endif

#ifdef HAVE_DNGETTEXT
function dngettext(string $domain, string $msgid1, string $msgid2, int $count): string|false {}
function dngettext(string $domain, string $msgid1, string $msgid2, int $count): string {}
#endif

#ifdef HAVE_DCNGETTEXT
function dcngettext(string $domain, string $msgid1, string $msgid2, int $count, int $category): string|false {}
function dcngettext(string $domain, string $msgid1, string $msgid2, int $count, int $category): string {}
#endif

#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
Expand Down
22 changes: 11 additions & 11 deletions ext/gettext/gettext_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 29c84ba2a2aa940baec3bd32503fc7c8e67885fe */
* Stub hash: a8b64ae24724f0552a62cd4146f6cfb3cd75fa19 */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_textdomain, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
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_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_gettext, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gettext, 0, 1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid, IS_STRING, 0)
ZEND_END_ARG_INFO()

#define arginfo__ arginfo_gettext

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_dgettext, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, domain_name, IS_STRING, 0)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dgettext, 0, 2, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid, IS_STRING, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_dcgettext, 0, 3, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, domain_name, IS_STRING, 0)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dcgettext, 0, 3, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid, 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_ARG_TYPE_INFO(0, domain_name, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, dir, IS_STRING, 0)
ZEND_END_ARG_INFO()

#if defined(HAVE_NGETTEXT)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ngettext, 0, 3, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ngettext, 0, 3, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid2, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, n, IS_LONG, 0)
ZEND_END_ARG_INFO()
#endif

#if defined(HAVE_DNGETTEXT)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_dngettext, 0, 4, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dngettext, 0, 4, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid2, IS_STRING, 0)
Expand All @@ -45,7 +45,7 @@ ZEND_END_ARG_INFO()
#endif

#if defined(HAVE_DCNGETTEXT)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_dcngettext, 0, 5, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_dcngettext, 0, 5, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, domain, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid1, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, msgid2, IS_STRING, 0)
Expand Down
145 changes: 92 additions & 53 deletions ext/gettext/tests/44938.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -12,71 +12,110 @@ $msgid = "msgid";
$domain = "domain";
$category = "cat";

var_dump(bindtextdomain($overflown, 'path'));

var_dump(dngettext($overflown, $msgid, $msgid, 1));
var_dump(dngettext($domain, $overflown, $msgid, 1));
var_dump(dngettext($domain, $msgid, $overflown, 1));

var_dump(gettext($overflown));

var_dump(ngettext($overflown, $msgid, -1));
var_dump(ngettext($msgid, $overflown, -1));

var_dump(dcgettext($overflown, $msgid, -1));
var_dump(dcgettext($domain, $overflown, -1));

var_dump(dcngettext($overflown, $msgid, $msgid, -1, -1));
var_dump(dcngettext($domain, $overflown, $msgid, -1, -1));
var_dump(dcngettext($domain, $msgid, $overflown, -1, -1));

var_dump(dgettext($overflown, $msgid));
var_dump(dgettext($domain, $overflown));
try {
bindtextdomain($overflown, 'path');
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

var_dump(textdomain($overflown));
?>
--EXPECTF--
Warning: bindtextdomain(): Domain passed too long in %s on line %d
bool(false)
try {
dngettext($overflown, $msgid, $msgid, 1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dngettext(): Domain passed too long in %s on line %d
bool(false)
try {
dngettext($domain, $overflown, $msgid, 1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dngettext(): msgid1 passed too long in %s on line %d
bool(false)
try {
dngettext($domain, $msgid, $overflown, 1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dngettext(): msgid2 passed too long in %s on line %d
bool(false)
try {
gettext($overflown);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: gettext(): msgid passed too long in %s on line %d
bool(false)
try {
ngettext($overflown, $msgid, -1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: ngettext(): msgid1 passed too long in %s on line %d
bool(false)
try {
ngettext($msgid, $overflown, -1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: ngettext(): msgid2 passed too long in %s on line %d
bool(false)
try {
dcgettext($overflown, $msgid, -1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dcgettext(): Domain passed too long in %s on line %d
bool(false)
try {
dcgettext($domain, $overflown, -1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dcgettext(): msgid passed too long in %s on line %d
bool(false)
try {
dcngettext($overflown, $msgid, $msgid, -1, -1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dcngettext(): Domain passed too long in %s on line %d
bool(false)
try {
dcngettext($domain, $overflown, $msgid, -1, -1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dcngettext(): msgid1 passed too long in %s on line %d
bool(false)
try {
dcngettext($domain, $msgid, $overflown, -1, -1);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dcngettext(): msgid2 passed too long in %s on line %d
bool(false)
try {
dgettext($overflown, $msgid);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dgettext(): Domain passed too long in %s on line %d
bool(false)
try {
dgettext($domain, $overflown);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: dgettext(): msgid passed too long in %s on line %d
bool(false)
try {
textdomain($overflown);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}

Warning: textdomain(): Domain passed too long in %s on line %d
bool(false)
?>
--EXPECT--
bindtextdomain(): Argument #1 ($domain) is too long
dngettext(): Argument #1 ($domain) is too long
dngettext(): Argument #2 ($msgid1) is too long
dngettext(): Argument #3 ($msgid2) is too long
gettext(): Argument #1 ($msgid) is too long
ngettext(): Argument #1 ($msgid1) is too long
ngettext(): Argument #2 ($msgid2) is too long
dcgettext(): Argument #1 ($domain) is too long
dcgettext(): Argument #2 ($msgid) is too long
dcngettext(): Argument #1 ($domain) is too long
dcngettext(): Argument #2 ($msgid1) is too long
dcngettext(): Argument #3 ($msgid2) is too long
dgettext(): Argument #1 ($domain) is too long
dgettext(): Argument #2 ($msgid) is too long
textdomain(): Argument #1 ($domain) is too long

0 comments on commit 4c89ed6

Please sign in to comment.