From 930fad7381719397beec566f283b2395bc685ac9 Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Thu, 30 Oct 2008 14:23:03 +0000 Subject: [PATCH] MFH: #44938 --- ext/gettext/gettext.c | 36 +++++++++++++-- ext/gettext/tests/44938.phpt | 85 ++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 ext/gettext/tests/44938.phpt diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index f10b0f3b4f..217eae0a1c 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -145,12 +145,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 = msgid1_len; \ + PHP_GETTEXT_LENGTH_CHECK \ + check_name = "msgid2"; \ + check_len = msgid2_len; \ + PHP_GETTEXT_LENGTH_CHECK + PHP_MINFO_FUNCTION(php_gettext) { php_info_print_table_start(); @@ -194,6 +217,7 @@ PHP_NAMED_FUNCTION(zif_gettext) return; } + PHP_GETTEXT_MSGID_LENGTH_CHECK msgstr = gettext(msgid); RETURN_STRING(msgstr, 1); @@ -212,6 +236,7 @@ PHP_NAMED_FUNCTION(zif_dgettext) } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MSGID_LENGTH_CHECK msgstr = dgettext(domain, msgid); @@ -232,6 +257,7 @@ PHP_NAMED_FUNCTION(zif_dcgettext) } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MSGID_LENGTH_CHECK msgstr = dcgettext(domain, msgid, category); @@ -257,7 +283,7 @@ PHP_NAMED_FUNCTION(zif_bindtextdomain) php_error(E_WARNING, "The first parameter of bindtextdomain must not be empty"); RETURN_FALSE; } - + if (dir[0] != '\0' && strcmp(dir, "0")) { if (!VCWD_REALPATH(dir, dir_name)) { RETURN_FALSE; @@ -285,6 +311,8 @@ PHP_NAMED_FUNCTION(zif_ngettext) return; } + PHP_GETTEXT_MULTI_MSGID_LENGTH_CHECK + msgstr = ngettext(msgid1, msgid2, count); if (msgstr) { RETVAL_STRING(msgstr, 1); @@ -301,13 +329,14 @@ PHP_NAMED_FUNCTION(zif_dngettext) char *domain, *msgid1, *msgid2, *msgstr = NULL; int domain_len, msgid1_len, msgid2_len; long count; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", &domain, &domain_len, &msgid1, &msgid1_len, &msgid2, &msgid2_len, &count) == FAILURE) { return; } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MULTI_MSGID_LENGTH_CHECK msgstr = dngettext(domain, msgid1, msgid2, count); if (msgstr) { @@ -319,7 +348,7 @@ PHP_NAMED_FUNCTION(zif_dngettext) #if HAVE_DCNGETTEXT /* {{{ proto string dcngettext (string domain, string msgid1, string msgid2, int n, int category) - Plural version of dcgettext() */ + Plural version of dcgettext() */ PHP_NAMED_FUNCTION(zif_dcngettext) { char *domain, *msgid1, *msgid2, *msgstr = NULL; @@ -334,6 +363,7 @@ PHP_NAMED_FUNCTION(zif_dcngettext) } PHP_GETTEXT_DOMAIN_LENGTH_CHECK + PHP_GETTEXT_MULTI_MSGID_LENGTH_CHECK msgstr = dcngettext(domain, msgid1, msgid2, count, category); 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== -- 2.40.0