Skip to content

Commit 03816fb

Browse files
committed
Fix GH-7902: mb_send_mail may delimit headers with LF only
Email headers are supposed to be separated with CRLF. Period. We introduce a `CRLF` macro for better comprehensibility right away. Closes GH-7907.
1 parent 93a3c71 commit 03816fb

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ PHP NEWS
1414
- FPM:
1515
. Fixed memory leak on invalid port. (David Carlier)
1616

17+
- MBString:
18+
. Fixed bug GH-7902 (mb_send_mail may delimit headers with LF only). (cmb)
19+
1720
- Sockets:
1821
. Fixed ext/sockets build on Haiku. (David Carlier)
1922

ext/mbstring/mbstring.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3270,6 +3270,8 @@ PHP_FUNCTION(mb_decode_numericentity)
32703270
continue; \
32713271
}
32723272

3273+
#define CRLF "\r\n"
3274+
32733275
static int _php_mbstr_parse_mail_headers(HashTable *ht, const char *str, size_t str_len)
32743276
{
32753277
const char *ps;
@@ -3601,7 +3603,7 @@ PHP_FUNCTION(mb_send_mail)
36013603
|| orig_str.encoding->no_encoding == mbfl_no_encoding_pass) {
36023604
orig_str.encoding = mbfl_identify_encoding(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection));
36033605
}
3604-
pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\n", sizeof("Subject: [PHP-jp nnnnnnnn]"));
3606+
pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, CRLF, sizeof("Subject: [PHP-jp nnnnnnnn]" CRLF) - 1);
36053607
if (pstr != NULL) {
36063608
subject_buf = subject = (char *)pstr->val;
36073609
}
@@ -3640,14 +3642,14 @@ PHP_FUNCTION(mb_send_mail)
36403642
n = ZSTR_LEN(str_headers);
36413643
mbfl_memory_device_strncat(&device, p, n);
36423644
if (n > 0 && p[n - 1] != '\n') {
3643-
mbfl_memory_device_strncat(&device, "\n", 1);
3645+
mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1);
36443646
}
36453647
zend_string_release_ex(str_headers, 0);
36463648
}
36473649

36483650
if (!zend_hash_str_exists(&ht_headers, "MIME-VERSION", sizeof("MIME-VERSION") - 1)) {
36493651
mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER1, sizeof(PHP_MBSTR_MAIL_MIME_HEADER1) - 1);
3650-
mbfl_memory_device_strncat(&device, "\n", 1);
3652+
mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1);
36513653
}
36523654

36533655
if (!suppressed_hdrs.cnt_type) {
@@ -3658,7 +3660,7 @@ PHP_FUNCTION(mb_send_mail)
36583660
mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER3, sizeof(PHP_MBSTR_MAIL_MIME_HEADER3) - 1);
36593661
mbfl_memory_device_strcat(&device, p);
36603662
}
3661-
mbfl_memory_device_strncat(&device, "\n", 1);
3663+
mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1);
36623664
}
36633665
if (!suppressed_hdrs.cnt_trans_enc) {
36643666
mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER4, sizeof(PHP_MBSTR_MAIL_MIME_HEADER4) - 1);
@@ -3667,9 +3669,10 @@ PHP_FUNCTION(mb_send_mail)
36673669
p = "7bit";
36683670
}
36693671
mbfl_memory_device_strcat(&device, p);
3670-
mbfl_memory_device_strncat(&device, "\n", 1);
3672+
mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1);
36713673
}
36723674

3675+
mbfl_memory_device_unput(&device);
36733676
mbfl_memory_device_unput(&device);
36743677
mbfl_memory_device_output('\0', &device);
36753678
str_headers = zend_string_init((char *)device.buffer, strlen((char *)device.buffer), 0);
@@ -3707,6 +3710,7 @@ PHP_FUNCTION(mb_send_mail)
37073710
}
37083711

37093712
#undef SKIP_LONG_HEADER_SEP_MBSTRING
3713+
#undef CRLF
37103714
#undef MAIL_ASCIIZ_CHECK_MBSTRING
37113715
#undef PHP_MBSTR_MAIL_MIME_HEADER1
37123716
#undef PHP_MBSTR_MAIL_MIME_HEADER2

ext/mbstring/tests/gh7902.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-7902 (mb_send_mail may delimit headers with LF only)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("mbstring")) die("skip mbstring extension not available");
6+
?>
7+
--INI--
8+
sendmail_path={MAIL:{PWD}/gh7902.eml}
9+
--FILE--
10+
<?php
11+
mb_internal_encoding("UTF-8");
12+
mb_language("uni");
13+
$to = "omittedvalidaddress@example.com";
14+
$subject = "test mail";
15+
$message = "body of testing php mail";
16+
$header["Mime-Version"] = "1.0";
17+
$header["Content-Type"] = "text/html; charset=UTF-8";
18+
$header["From"] = "omittedvalidaddress2@example.com";
19+
$header["X-Mailer"] = "PHP/" . phpversion();
20+
mb_send_mail($to, $subject, $message, $header);
21+
22+
$stream = fopen(__DIR__ . "/gh7902.eml", "rb");
23+
$eml = stream_get_contents($stream);
24+
fclose($stream);
25+
var_dump(preg_match_all('/(?<!\r)\n/', $eml));
26+
?>
27+
--CLEAN--
28+
<?php
29+
@unlink(__DIR__ . "/gh7902.eml");
30+
?>
31+
--EXPECT--
32+
int(0)

0 commit comments

Comments
 (0)