57
57
58
58
extern zend_long php_getuid (void );
59
59
60
- static bool php_mail_build_headers_check_field_value (zval * val )
60
+ static php_mail_header_value_error_type php_mail_build_headers_check_field_value (zval * val )
61
61
{
62
62
size_t len = 0 ;
63
63
zend_string * value = Z_STR_P (val );
@@ -66,20 +66,39 @@ static bool php_mail_build_headers_check_field_value(zval *val)
66
66
/* https://tools.ietf.org/html/rfc2822#section-2.2.3 */
67
67
while (len < value -> len ) {
68
68
if (* (value -> val + len ) == '\r' ) {
69
+ if (* (value -> val + len + 1 ) != '\n' ) {
70
+ return CONTAINS_CR_ONLY ;
71
+ }
72
+
69
73
if (value -> len - len >= 3
70
- && * (value -> val + len + 1 ) == '\n'
71
74
&& (* (value -> val + len + 2 ) == ' ' || * (value -> val + len + 2 ) == '\t' )) {
72
75
len += 3 ;
73
76
continue ;
74
77
}
75
- return FAILURE ;
78
+
79
+ return CONTAINS_CRLF ;
80
+ }
81
+ /**
82
+ * The RFC does not allow using LF alone for folding. However, LF is
83
+ * often treated similarly to CRLF, and there are likely many user
84
+ * environments that use LF for folding.
85
+ * Therefore, considering such an environment, folding with LF alone
86
+ * is allowed.
87
+ */
88
+ if (* (value -> val + len ) == '\n' ) {
89
+ if (value -> len - len >= 2
90
+ && (* (value -> val + len + 1 ) == ' ' || * (value -> val + len + 1 ) == '\t' )) {
91
+ len += 2 ;
92
+ continue ;
93
+ }
94
+ return CONTAINS_LF_ONLY ;
76
95
}
77
96
if (* (value -> val + len ) == '\0' ) {
78
- return FAILURE ;
97
+ return CONTAINS_NULL ;
79
98
}
80
99
len ++ ;
81
100
}
82
- return SUCCESS ;
101
+ return NO_HEADER_ERROR ;
83
102
}
84
103
85
104
@@ -108,9 +127,27 @@ static void php_mail_build_headers_elem(smart_str *s, zend_string *key, zval *va
108
127
zend_value_error ("Header name \"%s\" contains invalid characters" , ZSTR_VAL (key ));
109
128
return ;
110
129
}
111
- if (php_mail_build_headers_check_field_value (val ) != SUCCESS ) {
112
- zend_value_error ("Header \"%s\" has invalid format, or contains invalid characters" , ZSTR_VAL (key ));
113
- return ;
130
+
131
+ php_mail_header_value_error_type error_type = php_mail_build_headers_check_field_value (val );
132
+ switch (error_type ) {
133
+ case NO_HEADER_ERROR :
134
+ break ;
135
+ case CONTAINS_LF_ONLY :
136
+ zend_value_error ("Header \"%s\" contains LF character that is not allowed in the header" , ZSTR_VAL (key ));
137
+ return ;
138
+ case CONTAINS_CR_ONLY :
139
+ zend_value_error ("Header \"%s\" contains CR character that is not allowed in the header" , ZSTR_VAL (key ));
140
+ return ;
141
+ case CONTAINS_CRLF :
142
+ 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 ));
143
+ return ;
144
+ case CONTAINS_NULL :
145
+ zend_value_error ("Header \"%s\" contains NULL character that is not allowed in the header" , ZSTR_VAL (key ));
146
+ return ;
147
+ default :
148
+ // fallback
149
+ zend_value_error ("Header \"%s\" has invalid format, or contains invalid characters" , ZSTR_VAL (key ));
150
+ return ;
114
151
}
115
152
smart_str_append (s , key );
116
153
smart_str_appendl (s , ": " , 2 );
0 commit comments