]> granicus.if.org Git - php/commitdiff
MFH: #44938
authorLars Strojny <lstrojny@php.net>
Thu, 30 Oct 2008 14:23:03 +0000 (14:23 +0000)
committerLars Strojny <lstrojny@php.net>
Thu, 30 Oct 2008 14:23:03 +0000 (14:23 +0000)
ext/gettext/gettext.c
ext/gettext/tests/44938.phpt [new file with mode: 0644]

index f10b0f3b4f2a23892ff20c29a117142bcf1e3bd0..217eae0a1c1455429326986291403060b1c0381b 100644 (file)
@@ -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 (file)
index 0000000..f2d594a
--- /dev/null
@@ -0,0 +1,85 @@
+--TEST--
+#44938: gettext functions crash with overlong strings
+--SKIPIF--
+<?php
+if (!extension_loaded("gettext")) {
+       die("skip\n");
+}
+--FILE--
+<?php
+$overflown = str_repeat('C', 8476509);
+$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));
+
+var_dump(textdomain($overflown));
+?>
+==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==