]> granicus.if.org Git - php/commitdiff
Also forbid null bytes in mail()
authorNikita Popov <nikita.ppv@gmail.com>
Fri, 11 Sep 2020 13:27:54 +0000 (15:27 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Fri, 11 Sep 2020 13:28:51 +0000 (15:28 +0200)
I've adjusted mb_send_mail() already, but of course the handling
in mail() should be the same.

ext/standard/mail.c
ext/standard/tests/mail/mail_null_bytes.phpt [new file with mode: 0644]

index e1ae2a65bc685e449996cc1901f2975b34f7e1bd..af7d5f114bcbd9299c74a28e0ccf3b74be877cbe 100644 (file)
                continue;                                                                                                                                                                               \
        }                                                                                                                                                                                                       \
 
-#define MAIL_ASCIIZ_CHECK(str, len)                            \
-       p = str;                                                                        \
-       e = p + len;                                                            \
-       while ((p = memchr(p, '\0', (e - p)))) {        \
-               *p = ' ';                                                               \
-       }                                                                                       \
-
 extern zend_long php_getuid(void);
 
 static zend_bool php_mail_build_headers_check_field_value(zval *val)
@@ -260,32 +253,26 @@ PHP_FUNCTION(mail)
        size_t subject_len, i;
        char *force_extra_parameters = INI_STR("mail.force_extra_parameters");
        char *to_r, *subject_r;
-       char *p, *e;
 
        ZEND_PARSE_PARAMETERS_START(3, 5)
-               Z_PARAM_STRING(to, to_len)
-               Z_PARAM_STRING(subject, subject_len)
-               Z_PARAM_STRING(message, message_len)
+               Z_PARAM_PATH(to, to_len)
+               Z_PARAM_PATH(subject, subject_len)
+               Z_PARAM_PATH(message, message_len)
                Z_PARAM_OPTIONAL
                Z_PARAM_ARRAY_HT_OR_STR(headers_ht, headers_str)
-               Z_PARAM_STR(extra_cmd)
+               Z_PARAM_PATH_STR(extra_cmd)
        ZEND_PARSE_PARAMETERS_END();
 
-       /* ASCIIZ check */
-       MAIL_ASCIIZ_CHECK(to, to_len);
-       MAIL_ASCIIZ_CHECK(subject, subject_len);
-       MAIL_ASCIIZ_CHECK(message, message_len);
        if (headers_str) {
-               MAIL_ASCIIZ_CHECK(ZSTR_VAL(headers_str), ZSTR_LEN(headers_str));
+               if (strlen(ZSTR_VAL(headers_str)) != ZSTR_LEN(headers_str)) {
+                       zend_argument_value_error(4, "must not contain any null bytes");
+                       RETURN_THROWS();
+               }
                headers_str = php_trim(headers_str, NULL, 0, 2);
        } else if (headers_ht) {
                headers_str = php_mail_build_headers(headers_ht);
        }
 
-       if (extra_cmd) {
-               MAIL_ASCIIZ_CHECK(ZSTR_VAL(extra_cmd), ZSTR_LEN(extra_cmd));
-       }
-
        if (to_len > 0) {
                to_r = estrndup(to, to_len);
                for (; to_len; to_len--) {
diff --git a/ext/standard/tests/mail/mail_null_bytes.phpt b/ext/standard/tests/mail/mail_null_bytes.phpt
new file mode 100644 (file)
index 0000000..d25757c
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+mail() with null bytes in arguments
+--FILE--
+<?php
+
+try {
+    mail("foo\0bar", "x", "y");
+} catch (ValueError $e) {
+    echo $e->getMessage(), "\n";
+}
+try {
+    mail("x", "foo\0bar", "y");
+} catch (ValueError $e) {
+    echo $e->getMessage(), "\n";
+}
+try {
+    mail("x", "y", "foo\0bar");
+} catch (ValueError $e) {
+    echo $e->getMessage(), "\n";
+}
+try {
+    mail("x", "y", "z", "foo\0bar");
+} catch (ValueError $e) {
+    echo $e->getMessage(), "\n";
+}
+try {
+    mail("x", "y", "z", "q", "foo\0bar");
+} catch (ValueError $e) {
+    echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+mail(): Argument #1 ($to) must not contain any null bytes
+mail(): Argument #2 ($subject) must not contain any null bytes
+mail(): Argument #3 ($message) must not contain any null bytes
+mail(): Argument #4 ($additional_headers) must not contain any null bytes
+mail(): Argument #5 ($additional_parameters) must not contain any null bytes