From: Lars Strojny Date: Thu, 30 Oct 2008 14:22:21 +0000 (+0000) Subject: The real fix for the gettext overflow bug X-Git-Tag: BEFORE_HEAD_NS_CHANGE~129 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6d2dfa4eb047d9a2463ee3873ecea06f6e94fa94;p=php The real fix for the gettext overflow bug - The overflow issue was not limited to domains, but also present for msgids - [DOC] msgids are now limited to 4096 chars, domains to 1024 --- diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index bc957bfa53..67687bd1af 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -136,12 +136,35 @@ ZEND_GET_MODULE(php_gettext) #endif #define PHP_GETTEXT_MAX_DOMAIN_LENGTH 1024 +#define PHP_GETTEXT_MAX_MSGID_LENGTH 4096 + #define PHP_GETTEXT_DOMAIN_LENGTH_CHECK \ if (domain_len > PHP_GETTEXT_MAX_DOMAIN_LENGTH) { \ php_error_docref(NULL TSRMLS_CC, E_WARNING, "domain passed too long"); \ RETURN_FALSE; \ } +#define PHP_GETTEXT_MSGID_LENGTH_CHECK \ + char *check_name = "msgid"; \ + int check_len = msgid_len; \ + PHP_GETTEXT_LENGTH_CHECK + +#define PHP_GETTEXT_LENGTH_CHECK \ + if (check_len > PHP_GETTEXT_MAX_MSGID_LENGTH) { \ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s passed too long", check_name); \ + RETURN_FALSE; \ + } + +#define PHP_GETTEXT_MULTI_MSGID_LENGTH_CHECK \ + int check_len; \ + char *check_name; \ + check_name = "msgid1"; \ + check_len = msgid_len1; \ + PHP_GETTEXT_LENGTH_CHECK \ + check_name = "msgid2"; \ + check_len = msgid_len2; \ + PHP_GETTEXT_LENGTH_CHECK + PHP_MINFO_FUNCTION(php_gettext) { php_info_print_table_start(); @@ -184,10 +207,13 @@ PHP_NAMED_FUNCTION(zif_gettext) { char *msgid_str; int msgid_len; - + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &msgid_str, &msgid_len, UG(ascii_conv))) { return; } + + PHP_GETTEXT_MSGID_LENGTH_CHECK + RETURN_STRING(gettext(msgid_str), ZSTR_DUPLICATE); } /* }}} */ @@ -204,6 +230,7 @@ PHP_NAMED_FUNCTION(zif_dgettext) } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MSGID_LENGTH_CHECK RETURN_STRING(dgettext(domain_str, msgid_str), ZSTR_DUPLICATE); } @@ -222,6 +249,7 @@ PHP_NAMED_FUNCTION(zif_dcgettext) } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MSGID_LENGTH_CHECK RETURN_STRING(dcgettext(domain_str, msgid_str, category), ZSTR_DUPLICATE); } @@ -263,11 +291,13 @@ PHP_NAMED_FUNCTION(zif_ngettext) char *msgid_str1, *msgid_str2, *msgstr; int msgid_len1, msgid_len2; long count; - + if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&s&l", &msgid_str1, &msgid_len1, UG(ascii_conv), &msgid_str2, &msgid_len2, UG(ascii_conv), &count)) { RETURN_FALSE; } - + + PHP_GETTEXT_MULTI_MSGID_LENGTH_CHECK + if ((msgstr = ngettext(msgid_str1, msgid_str2, count))) { RETURN_STRING(msgstr, ZSTR_DUPLICATE); } else { @@ -291,6 +321,7 @@ PHP_NAMED_FUNCTION(zif_dngettext) } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MULTI_MSGID_LENGTH_CHECK if ((msgstr = dngettext(domain_str, msgid_str1, msgid_str2, count))) { RETURN_STRING(msgstr, ZSTR_DUPLICATE); @@ -315,6 +346,7 @@ PHP_NAMED_FUNCTION(zif_dcngettext) } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MULTI_MSGID_LENGTH_CHECK if ((msgstr = dcngettext(domain_str, msgid_str1, msgid_str2, count, category))) { RETURN_STRING(msgstr, ZSTR_DUPLICATE); diff --git a/ext/gettext/tests/44938.phpt b/ext/gettext/tests/44938.phpt new file mode 100644 index 0000000000..f2d594aa5c --- /dev/null +++ b/ext/gettext/tests/44938.phpt @@ -0,0 +1,85 @@ +--TEST-- +#44938: gettext functions crash with overlong strings +--SKIPIF-- + +==DONE== +--EXPECTF-- + +Warning: bindtextdomain(): domain passed too long in %s on line %d +bool(false) + +Warning: dngettext(): domain passed too long in %s on line %d +bool(false) + +Warning: dngettext(): msgid1 passed too long in %s on line %d +bool(false) + +Warning: dngettext(): msgid2 passed too long in %s on line %d +bool(false) + +Warning: gettext(): msgid passed too long in %s on line %d +bool(false) + +Warning: ngettext(): msgid1 passed too long in %s on line %d +bool(false) + +Warning: ngettext(): msgid2 passed too long in %s on line %d +bool(false) + +Warning: dcgettext(): domain passed too long in %s on line %d +bool(false) + +Warning: dcgettext(): msgid passed too long in %s on line %d +bool(false) + +Warning: dcngettext(): domain passed too long in %s on line %d +bool(false) + +Warning: dcngettext(): msgid1 passed too long in %s on line %d +bool(false) + +Warning: dcngettext(): msgid2 passed too long in %s on line %d +bool(false) + +Warning: dgettext(): domain passed too long in %s on line %d +bool(false) + +Warning: dgettext(): msgid passed too long in %s on line %d +bool(false) + +Warning: textdomain(): domain passed too long in %s on line %d +bool(false) +==DONE==