#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();
{
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);
}
/* }}} */
}
PHP_GETTEXT_DOMAIN_LENGTH_CHECK
+ PHP_GETTEXT_MSGID_LENGTH_CHECK
RETURN_STRING(dgettext(domain_str, msgid_str), ZSTR_DUPLICATE);
}
}
PHP_GETTEXT_DOMAIN_LENGTH_CHECK
+ PHP_GETTEXT_MSGID_LENGTH_CHECK
RETURN_STRING(dcgettext(domain_str, msgid_str, category), ZSTR_DUPLICATE);
}
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 {
}
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);
}
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);
--- /dev/null
+--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==