From d339fffb562a6f7d993928ddf243ef6cf032b552 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 7 Jan 2022 15:54:03 +0100 Subject: [PATCH 1/3] Regression test --- ext/mbstring/tests/gh7902.phpt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 ext/mbstring/tests/gh7902.phpt diff --git a/ext/mbstring/tests/gh7902.phpt b/ext/mbstring/tests/gh7902.phpt new file mode 100644 index 0000000000000..1f7581696c120 --- /dev/null +++ b/ext/mbstring/tests/gh7902.phpt @@ -0,0 +1,32 @@ +--TEST-- +GH-7902 (mb_send_mail may delimit headers with LF only) +--SKIPIF-- + +--INI-- +sendmail_path={MAIL:{PWD}/gh7902.eml} +--FILE-- + +--CLEAN-- + +--EXPECT-- +int(1) From 42e31b8531ceab4e8d4b307e4b65c1dd6ab14609 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 7 Jan 2022 18:10:01 +0100 Subject: [PATCH 2/3] Fix GH-7902: mb_send_mail may delimit headers with LF only Email headers are supposed to be separated with CRLF. Period. --- ext/mbstring/mbstring.c | 11 ++++++----- ext/mbstring/tests/gh7902.phpt | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index a5284264f3d34..44356a0af445f 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -3601,7 +3601,7 @@ PHP_FUNCTION(mb_send_mail) || orig_str.encoding->no_encoding == mbfl_no_encoding_pass) { orig_str.encoding = mbfl_identify_encoding(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection)); } - pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\n", sizeof("Subject: [PHP-jp nnnnnnnn]")); + pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\r\n", sizeof("Subject: [PHP-jp nnnnnnnn]") + 1); if (pstr != NULL) { subject_buf = subject = (char *)pstr->val; } @@ -3640,14 +3640,14 @@ PHP_FUNCTION(mb_send_mail) n = ZSTR_LEN(str_headers); mbfl_memory_device_strncat(&device, p, n); if (n > 0 && p[n - 1] != '\n') { - mbfl_memory_device_strncat(&device, "\n", 1); + mbfl_memory_device_strncat(&device, "\r\n", 2); } zend_string_release_ex(str_headers, 0); } if (!zend_hash_str_exists(&ht_headers, "MIME-VERSION", sizeof("MIME-VERSION") - 1)) { mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER1, sizeof(PHP_MBSTR_MAIL_MIME_HEADER1) - 1); - mbfl_memory_device_strncat(&device, "\n", 1); + mbfl_memory_device_strncat(&device, "\r\n", 2); } if (!suppressed_hdrs.cnt_type) { @@ -3658,7 +3658,7 @@ PHP_FUNCTION(mb_send_mail) mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER3, sizeof(PHP_MBSTR_MAIL_MIME_HEADER3) - 1); mbfl_memory_device_strcat(&device, p); } - mbfl_memory_device_strncat(&device, "\n", 1); + mbfl_memory_device_strncat(&device, "\r\n", 2); } if (!suppressed_hdrs.cnt_trans_enc) { mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER4, sizeof(PHP_MBSTR_MAIL_MIME_HEADER4) - 1); @@ -3667,9 +3667,10 @@ PHP_FUNCTION(mb_send_mail) p = "7bit"; } mbfl_memory_device_strcat(&device, p); - mbfl_memory_device_strncat(&device, "\n", 1); + mbfl_memory_device_strncat(&device, "\r\n", 2); } + mbfl_memory_device_unput(&device); mbfl_memory_device_unput(&device); mbfl_memory_device_output('\0', &device); str_headers = zend_string_init((char *)device.buffer, strlen((char *)device.buffer), 0); diff --git a/ext/mbstring/tests/gh7902.phpt b/ext/mbstring/tests/gh7902.phpt index 1f7581696c120..d9a0fced7913d 100644 --- a/ext/mbstring/tests/gh7902.phpt +++ b/ext/mbstring/tests/gh7902.phpt @@ -22,11 +22,11 @@ mb_send_mail($to, $subject, $message, $header); $stream = fopen(__DIR__ . "/gh7902.eml", "rb"); $eml = stream_get_contents($stream); fclose($stream); -var_dump(preg_match('/BASE64\r\n/', $eml)); +var_dump(preg_match_all('/(? --CLEAN-- --EXPECT-- -int(1) +int(0) From 4f5df5faccadb4c1fd39531d587bb2ad3901aa66 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 18 Jan 2022 12:01:13 +0100 Subject: [PATCH 3/3] Introduce CRLF macro for better comprehensibility --- ext/mbstring/mbstring.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 44356a0af445f..48f22a682a196 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -3270,6 +3270,8 @@ PHP_FUNCTION(mb_decode_numericentity) continue; \ } +#define CRLF "\r\n" + static int _php_mbstr_parse_mail_headers(HashTable *ht, const char *str, size_t str_len) { const char *ps; @@ -3601,7 +3603,7 @@ PHP_FUNCTION(mb_send_mail) || orig_str.encoding->no_encoding == mbfl_no_encoding_pass) { orig_str.encoding = mbfl_identify_encoding(&orig_str, MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size), MBSTRG(strict_detection)); } - pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, "\r\n", sizeof("Subject: [PHP-jp nnnnnnnn]") + 1); + pstr = mbfl_mime_header_encode(&orig_str, &conv_str, tran_cs, head_enc, CRLF, sizeof("Subject: [PHP-jp nnnnnnnn]" CRLF) - 1); if (pstr != NULL) { subject_buf = subject = (char *)pstr->val; } @@ -3640,14 +3642,14 @@ PHP_FUNCTION(mb_send_mail) n = ZSTR_LEN(str_headers); mbfl_memory_device_strncat(&device, p, n); if (n > 0 && p[n - 1] != '\n') { - mbfl_memory_device_strncat(&device, "\r\n", 2); + mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1); } zend_string_release_ex(str_headers, 0); } if (!zend_hash_str_exists(&ht_headers, "MIME-VERSION", sizeof("MIME-VERSION") - 1)) { mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER1, sizeof(PHP_MBSTR_MAIL_MIME_HEADER1) - 1); - mbfl_memory_device_strncat(&device, "\r\n", 2); + mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1); } if (!suppressed_hdrs.cnt_type) { @@ -3658,7 +3660,7 @@ PHP_FUNCTION(mb_send_mail) mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER3, sizeof(PHP_MBSTR_MAIL_MIME_HEADER3) - 1); mbfl_memory_device_strcat(&device, p); } - mbfl_memory_device_strncat(&device, "\r\n", 2); + mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1); } if (!suppressed_hdrs.cnt_trans_enc) { mbfl_memory_device_strncat(&device, PHP_MBSTR_MAIL_MIME_HEADER4, sizeof(PHP_MBSTR_MAIL_MIME_HEADER4) - 1); @@ -3667,7 +3669,7 @@ PHP_FUNCTION(mb_send_mail) p = "7bit"; } mbfl_memory_device_strcat(&device, p); - mbfl_memory_device_strncat(&device, "\r\n", 2); + mbfl_memory_device_strncat(&device, CRLF, sizeof(CRLF)-1); } mbfl_memory_device_unput(&device); @@ -3708,6 +3710,7 @@ PHP_FUNCTION(mb_send_mail) } #undef SKIP_LONG_HEADER_SEP_MBSTRING +#undef CRLF #undef MAIL_ASCIIZ_CHECK_MBSTRING #undef PHP_MBSTR_MAIL_MIME_HEADER1 #undef PHP_MBSTR_MAIL_MIME_HEADER2