1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Merge branch 'PHP-8.2' into PHP-8.3

* PHP-8.2:
  Added validation of `\n` in $additional_headers of mail()
This commit is contained in:
Saki Takamachi
2024-03-04 21:30:27 +09:00
4 changed files with 105 additions and 9 deletions

View File

@@ -57,7 +57,7 @@
extern zend_long php_getuid(void);
static bool php_mail_build_headers_check_field_value(zval *val)
static php_mail_header_value_error_type php_mail_build_headers_check_field_value(zval *val)
{
size_t len = 0;
zend_string *value = Z_STR_P(val);
@@ -66,20 +66,39 @@ static bool php_mail_build_headers_check_field_value(zval *val)
/* https://tools.ietf.org/html/rfc2822#section-2.2.3 */
while (len < value->len) {
if (*(value->val+len) == '\r') {
if (*(value->val+len+1) != '\n') {
return CONTAINS_CR_ONLY;
}
if (value->len - len >= 3
&& *(value->val+len+1) == '\n'
&& (*(value->val+len+2) == ' ' || *(value->val+len+2) == '\t')) {
len += 3;
continue;
}
return FAILURE;
return CONTAINS_CRLF;
}
/**
* The RFC does not allow using LF alone for folding. However, LF is
* often treated similarly to CRLF, and there are likely many user
* environments that use LF for folding.
* Therefore, considering such an environment, folding with LF alone
* is allowed.
*/
if (*(value->val+len) == '\n') {
if (value->len - len >= 2
&& (*(value->val+len+1) == ' ' || *(value->val+len+1) == '\t')) {
len += 2;
continue;
}
return CONTAINS_LF_ONLY;
}
if (*(value->val+len) == '\0') {
return FAILURE;
return CONTAINS_NULL;
}
len++;
}
return SUCCESS;
return NO_HEADER_ERROR;
}
@@ -108,9 +127,27 @@ static void php_mail_build_headers_elem(smart_str *s, zend_string *key, zval *va
zend_value_error("Header name \"%s\" contains invalid characters", ZSTR_VAL(key));
return;
}
if (php_mail_build_headers_check_field_value(val) != SUCCESS) {
zend_value_error("Header \"%s\" has invalid format, or contains invalid characters", ZSTR_VAL(key));
return;
php_mail_header_value_error_type error_type = php_mail_build_headers_check_field_value(val);
switch (error_type) {
case NO_HEADER_ERROR:
break;
case CONTAINS_LF_ONLY:
zend_value_error("Header \"%s\" contains LF character that is not allowed in the header", ZSTR_VAL(key));
return;
case CONTAINS_CR_ONLY:
zend_value_error("Header \"%s\" contains CR character that is not allowed in the header", ZSTR_VAL(key));
return;
case CONTAINS_CRLF:
zend_value_error("Header \"%s\" contains CRLF characters that are used as a line separator and are not allowed in the header", ZSTR_VAL(key));
return;
case CONTAINS_NULL:
zend_value_error("Header \"%s\" contains NULL character that is not allowed in the header", ZSTR_VAL(key));
return;
default:
// fallback
zend_value_error("Header \"%s\" has invalid format, or contains invalid characters", ZSTR_VAL(key));
return;
}
smart_str_append(s, key);
smart_str_appendl(s, ": ", 2);

View File

@@ -49,5 +49,12 @@ do { \
} \
} while(0)
typedef enum {
NO_HEADER_ERROR,
CONTAINS_LF_ONLY,
CONTAINS_CR_ONLY,
CONTAINS_CRLF,
CONTAINS_NULL
} php_mail_header_value_error_type;
#endif /* PHP_MAIL_H */

View File

@@ -0,0 +1,52 @@
--TEST--
GH-13415 (Added validation of line breaks \n in $additional_headers of mail())
--INI--
sendmail_path={MAIL:gh13415.out}
--FILE--
<?php
echo "LF only:\n";
try {
mail('to@example.com', 'Test Subject', 'A Message', ['Reply-To' => "foo@example.com \nCc: hacker@example.com"]);
} catch (Throwable $e) {
echo $e->getMessage()."\n\n";
}
echo "CR only:\n";
try {
mail('to@example.com', 'Test Subject', 'A Message', ['Reply-To' => "foo@example.com \rCc: hacker@example.com"]);
} catch (Throwable $e) {
echo $e->getMessage()."\n\n";
}
echo "CRLF:\n";
try {
mail('to@example.com', 'Test Subject', 'A Message', ['Reply-To' => "foo@example.com \r\nCc: hacker@example.com"]);
} catch (Throwable $e) {
echo $e->getMessage()."\n\n";
}
echo "NULL:\n";
try {
mail('to@example.com', 'Test Subject', 'A Message', ['Reply-To' => "foo@example.com \0Cc: hacker@example.com"]);
} catch (Throwable $e) {
echo $e->getMessage()."\n\n";
}
?>
--CLEAN--
<?php
if (file_exists('gh13415.out')) {
unlink('gh13415.out');
}
?>
--EXPECTF--
LF only:
Header "Reply-To" contains LF character that is not allowed in the header
CR only:
Header "Reply-To" contains CR character that is not allowed in the header
CRLF:
Header "Reply-To" contains CRLF characters that are used as a line separator and are not allowed in the header
NULL:
Header "Reply-To" contains NULL character that is not allowed in the header

View File

@@ -258,4 +258,4 @@ Subject: Test Subject
foo9: %&$#!
A Message
ValueError: Header "foo10" has invalid format, or contains invalid characters
ValueError: Header "foo10" contains NULL character that is not allowed in the header