From 1753055ea966d2dcc66f7ccf363ede4f20861179 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 24 Dec 2025 19:01:18 +0100 Subject: [PATCH 1/7] ext/standard/mail: use zend_string* for message param of php_mail() This prevents some strlen() recomputation --- ext/mbstring/mbstring.c | 7 +++---- ext/standard/basic_functions.c | 2 +- ext/standard/mail.c | 23 ++++++++++++----------- ext/standard/php_mail.h | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index c5331ef017af..f88ddaf3a9db 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -4633,9 +4633,8 @@ PHP_FUNCTION(mb_send_mail) unsigned int num_errors = 0; zend_string *tmpstr = mb_fast_convert((unsigned char*)message, message_len, msg_enc, tran_cs, '?', MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR, &num_errors); - zend_string *conv = mb_fast_convert((unsigned char*)ZSTR_VAL(tmpstr), ZSTR_LEN(tmpstr), &mbfl_encoding_8bit, body_enc, '?', MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR, &num_errors); + zend_string *converted_message = mb_fast_convert((unsigned char*)ZSTR_VAL(tmpstr), ZSTR_LEN(tmpstr), &mbfl_encoding_8bit, body_enc, '?', MBFL_OUTPUTFILTER_ILLEGAL_MODE_CHAR, &num_errors); zend_string_free(tmpstr); - message = ZSTR_VAL(conv); /* other headers */ #define PHP_MBSTR_MAIL_MIME_HEADER1 "MIME-Version: 1.0" @@ -4703,7 +4702,7 @@ PHP_FUNCTION(mb_send_mail) extra_cmd = php_escape_shell_cmd(extra_cmd); } - RETVAL_BOOL(php_mail(to_r, ZSTR_VAL(subject), message, ZSTR_VAL(str_headers), extra_cmd)); + RETVAL_BOOL(php_mail(to_r, ZSTR_VAL(subject), converted_message, ZSTR_VAL(str_headers), extra_cmd)); if (extra_cmd) { zend_string_release_ex(extra_cmd, 0); @@ -4712,7 +4711,7 @@ PHP_FUNCTION(mb_send_mail) efree(to_r); } zend_string_release(subject); - zend_string_free(conv); + zend_string_free(converted_message); zend_hash_destroy(&ht_headers); if (str_headers) { zend_string_release_ex(str_headers, 0); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index c108900103cc..07405a70a94c 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1353,7 +1353,7 @@ PHPAPI zend_result _php_error_log(int opt_err, const zend_string *message, const switch (opt_err) { case 1: /*send an email */ - if (!php_mail(ZSTR_VAL(opt), "PHP error_log message", ZSTR_VAL(message), ZSTR_VAL(headers), NULL)) { + if (!php_mail(ZSTR_VAL(opt), "PHP error_log message", message, ZSTR_VAL(headers), NULL)) { return FAILURE; } break; diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 395c7bb81d4f..29206b285c88 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -265,19 +265,20 @@ PHPAPI zend_string *php_mail_build_headers(const HashTable *headers) /* {{{ Send an email message */ PHP_FUNCTION(mail) { - char *to=NULL, *message=NULL; + char *to=NULL; char *subject=NULL; + zend_string *message; zend_string *extra_cmd=NULL; zend_string *headers_str = NULL; HashTable *headers_ht = NULL; - size_t to_len, message_len; + size_t to_len; size_t subject_len, i; char *to_r, *subject_r; ZEND_PARSE_PARAMETERS_START(3, 5) Z_PARAM_PATH(to, to_len) Z_PARAM_PATH(subject, subject_len) - Z_PARAM_PATH(message, message_len) + Z_PARAM_PATH_STR(message) Z_PARAM_OPTIONAL Z_PARAM_ARRAY_HT_OR_STR(headers_ht, headers_str) Z_PARAM_PATH_STR(extra_cmd) @@ -434,7 +435,7 @@ static int php_mail_detect_multiple_crlf(const char *hdr) { /* {{{ php_mail */ -PHPAPI bool php_mail(const char *to, const char *subject, const char *message, const char *headers, const zend_string *extra_cmd) +PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *message, const char *headers, const zend_string *extra_cmd) { FILE *sendmail; char *sendmail_path = INI_STR("sendmail_path"); @@ -536,7 +537,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c char *tsm_errmsg = NULL; /* handle old style win smtp sending */ - if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, message) == FAILURE) { + if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, ZSTR_VAL(message)) == FAILURE) { if (tsm_errmsg) { php_error_docref(NULL, E_WARNING, "%s", tsm_errmsg); efree(tsm_errmsg); @@ -605,27 +606,27 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c if (cr_lf_mode && zend_string_equals_literal(cr_lf_mode, "lf")) { char *converted_message = NULL; - size_t msg_len = strlen(message); + size_t msg_len = ZSTR_LEN(message); size_t new_len = 0; if (msg_len > 0) { for (size_t i = 0; i < msg_len - 1; ++i) { - if (message[i] == '\r' && message[i + 1] == '\n') { + if (ZSTR_VAL(message)[i] == '\r' && ZSTR_VAL(message)[i + 1] == '\n') { ++new_len; } } if (new_len == 0) { - fprintf(sendmail, "%s", message); + fprintf(sendmail, "%s", ZSTR_VAL(message)); } else { converted_message = emalloc(msg_len - new_len + 1); size_t j = 0; for (size_t i = 0; i < msg_len; ++i) { - if (i < msg_len - 1 && message[i] == '\r' && message[i + 1] == '\n') { + if (i < msg_len - 1 && ZSTR_VAL(message)[i] == '\r' && ZSTR_VAL(message)[i + 1] == '\n') { converted_message[j++] = '\n'; ++i; /* skip LF part */ } else { - converted_message[j++] = message[i]; + converted_message[j++] = ZSTR_VAL(message)[i]; } } @@ -635,7 +636,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c } } } else { - fprintf(sendmail, "%s", message); + fprintf(sendmail, "%s", ZSTR_VAL(message)); } fprintf(sendmail, "%s", line_sep); diff --git a/ext/standard/php_mail.h b/ext/standard/php_mail.h index bebb526699d0..0453db111f53 100644 --- a/ext/standard/php_mail.h +++ b/ext/standard/php_mail.h @@ -20,6 +20,6 @@ PHP_MINFO_FUNCTION(mail); PHPAPI zend_string *php_mail_build_headers(const HashTable *headers); -PHPAPI extern bool php_mail(const char *to, const char *subject, const char *message, const char *headers, const zend_string *extra_cmd); +PHPAPI extern bool php_mail(const char *to, const char *subject, const zend_string *message, const char *headers, const zend_string *extra_cmd); #endif /* PHP_MAIL_H */ From 46c581435a237804f700251afa326acf6870726c Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 24 Dec 2025 19:08:14 +0100 Subject: [PATCH 2/7] ext/standard/mail: use zend_string* for headers param of php_mail() In preparation for future refactorings --- ext/mbstring/mbstring.c | 2 +- ext/standard/basic_functions.c | 2 +- ext/standard/mail.c | 10 +++++----- ext/standard/php_mail.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index f88ddaf3a9db..805c4084352d 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -4702,7 +4702,7 @@ PHP_FUNCTION(mb_send_mail) extra_cmd = php_escape_shell_cmd(extra_cmd); } - RETVAL_BOOL(php_mail(to_r, ZSTR_VAL(subject), converted_message, ZSTR_VAL(str_headers), extra_cmd)); + RETVAL_BOOL(php_mail(to_r, ZSTR_VAL(subject), converted_message, str_headers, extra_cmd)); if (extra_cmd) { zend_string_release_ex(extra_cmd, 0); diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 07405a70a94c..4d9e1dc82bc7 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -1353,7 +1353,7 @@ PHPAPI zend_result _php_error_log(int opt_err, const zend_string *message, const switch (opt_err) { case 1: /*send an email */ - if (!php_mail(ZSTR_VAL(opt), "PHP error_log message", message, ZSTR_VAL(headers), NULL)) { + if (!php_mail(ZSTR_VAL(opt), "PHP error_log message", message, headers, NULL)) { return FAILURE; } break; diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 29206b285c88..122f4a254740 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -344,7 +344,7 @@ PHP_FUNCTION(mail) extra_cmd = php_escape_shell_cmd(extra_cmd); } - if (php_mail(to_r, subject_r, message, headers_str && ZSTR_LEN(headers_str) ? ZSTR_VAL(headers_str) : NULL, extra_cmd)) { + if (php_mail(to_r, subject_r, message, headers_str, extra_cmd)) { RETVAL_TRUE; } else { RETVAL_FALSE; @@ -435,13 +435,13 @@ static int php_mail_detect_multiple_crlf(const char *hdr) { /* {{{ php_mail */ -PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *message, const char *headers, const zend_string *extra_cmd) +PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *message, const zend_string *headers, const zend_string *extra_cmd) { FILE *sendmail; char *sendmail_path = INI_STR("sendmail_path"); char *sendmail_cmd = NULL; const zend_string *mail_log = zend_ini_str(ZEND_STRL("mail.log"), false); - const char *hdr = headers; + const char *hdr = headers && ZSTR_LEN(headers) ? ZSTR_VAL(headers) : NULL; char *ahdr = NULL; #if PHP_SIGCHILD void (*sig_handler)(int) = NULL; @@ -517,8 +517,8 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes f = php_basename(tmp, strlen(tmp), NULL, 0); - if (headers != NULL && *headers) { - spprintf(&ahdr, 0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s%s%s", php_getuid(), ZSTR_VAL(f), line_sep, headers); + if (headers != NULL && ZSTR_LEN(headers)) { + spprintf(&ahdr, 0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s%s%s", php_getuid(), ZSTR_VAL(f), line_sep, ZSTR_VAL(headers)); } else { spprintf(&ahdr, 0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s", php_getuid(), ZSTR_VAL(f)); } diff --git a/ext/standard/php_mail.h b/ext/standard/php_mail.h index 0453db111f53..ade6a4124401 100644 --- a/ext/standard/php_mail.h +++ b/ext/standard/php_mail.h @@ -20,6 +20,6 @@ PHP_MINFO_FUNCTION(mail); PHPAPI zend_string *php_mail_build_headers(const HashTable *headers); -PHPAPI extern bool php_mail(const char *to, const char *subject, const zend_string *message, const char *headers, const zend_string *extra_cmd); +PHPAPI extern bool php_mail(const char *to, const char *subject, const zend_string *message, const zend_string *headers, const zend_string *extra_cmd); #endif /* PHP_MAIL_H */ From e0874e14dea467b7f341c3fcef00a5d114643f14 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 25 Dec 2025 20:11:00 +0100 Subject: [PATCH 3/7] ext/standard/mail: use zend_string* for headers inside php_mail() This prevents a strlen() reconputation --- ext/standard/mail.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 122f4a254740..2deb62181b36 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -397,13 +397,14 @@ static void php_mail_log_to_file(const zend_string *filename, const char *messag } -static int php_mail_detect_multiple_crlf(const char *hdr) { +static int php_mail_detect_multiple_crlf(const zend_string *headers) { /* This function detects multiple/malformed multiple newlines. */ - if (!hdr || !strlen(hdr)) { + if (!headers || !ZSTR_LEN(headers)) { return 0; } + const char *hdr = ZSTR_VAL(headers); /* Should not have any newlines at the beginning. */ /* RFC 2822 2.2. Header Fields */ if (*hdr < 33 || *hdr > 126 || *hdr == ':') { @@ -441,24 +442,24 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes char *sendmail_path = INI_STR("sendmail_path"); char *sendmail_cmd = NULL; const zend_string *mail_log = zend_ini_str(ZEND_STRL("mail.log"), false); - const char *hdr = headers && ZSTR_LEN(headers) ? ZSTR_VAL(headers) : NULL; - char *ahdr = NULL; #if PHP_SIGCHILD void (*sig_handler)(int) = NULL; #endif #define MAIL_RET(val) \ - if (ahdr != NULL) { \ - efree(ahdr); \ - } \ - return val; \ + if (headers_with_x_php_header != NULL) { \ + zend_string_release_ex(headers_with_x_php_header, false); \ + } \ + return val; \ if (mail_log && ZSTR_LEN(mail_log)) { char *logline; + const char *hdr = headers ? ZSTR_VAL(headers) : ""; - spprintf(&logline, 0, "mail() on [%s:%d]: To: %s -- Headers: %s -- Subject: %s", zend_get_executed_filename(), zend_get_executed_lineno(), to, hdr ? hdr : "", subject); + spprintf(&logline, 0, "mail() on [%s:%d]: To: %s -- Headers: %s -- Subject: %s", + zend_get_executed_filename(), zend_get_executed_lineno(), to, hdr, subject); - if (hdr) { + if (headers && ZSTR_LEN(headers)) { php_mail_log_crlf_to_spaces(logline); } @@ -486,7 +487,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes } if (EG(exception)) { - MAIL_RET(false); + return false; } const char *line_sep; @@ -511,6 +512,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes line_sep = PG(mail_mixed_lf_and_crlf) ? "\n" : "\r\n"; } + zend_string *headers_with_x_php_header = NULL; if (PG(mail_x_header)) { const char *tmp = zend_get_executed_filename(); zend_string *f; @@ -518,15 +520,17 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes f = php_basename(tmp, strlen(tmp), NULL, 0); if (headers != NULL && ZSTR_LEN(headers)) { - spprintf(&ahdr, 0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s%s%s", php_getuid(), ZSTR_VAL(f), line_sep, ZSTR_VAL(headers)); + headers_with_x_php_header = strpprintf(0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s%s%s", + php_getuid(), ZSTR_VAL(f), line_sep, ZSTR_VAL(headers)); } else { - spprintf(&ahdr, 0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s", php_getuid(), ZSTR_VAL(f)); + headers_with_x_php_header = strpprintf(0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s", + php_getuid(), ZSTR_VAL(f)); } - hdr = ahdr; zend_string_release_ex(f, 0); + headers = headers_with_x_php_header; } - if (hdr && php_mail_detect_multiple_crlf(hdr)) { + if (php_mail_detect_multiple_crlf(headers)) { php_error_docref(NULL, E_WARNING, "Multiple or malformed newlines found in additional_header"); MAIL_RET(false); } @@ -537,7 +541,8 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes char *tsm_errmsg = NULL; /* handle old style win smtp sending */ - if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, ZSTR_VAL(message)) == FAILURE) { + int status = TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, headers ? ZSTR_VAL(headers) : NULL, subject, to, ZSTR_VAL(message)); + if (status == FAILURE) { if (tsm_errmsg) { php_error_docref(NULL, E_WARNING, "%s", tsm_errmsg); efree(tsm_errmsg); @@ -598,8 +603,8 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes #endif fprintf(sendmail, "To: %s%s", to, line_sep); fprintf(sendmail, "Subject: %s%s", subject, line_sep); - if (hdr != NULL) { - fprintf(sendmail, "%s%s", hdr, line_sep); + if (headers && ZSTR_LEN(headers)) { + fprintf(sendmail, "%s%s", ZSTR_VAL(headers), line_sep); } fprintf(sendmail, "%s", line_sep); From d85b4f61a59311b664eac486943114cb22ce1f8e Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 25 Dec 2025 20:28:51 +0100 Subject: [PATCH 4/7] ext/standard/mail: refactor php_mail_detect_multiple_crlf() --- ext/standard/mail.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 2deb62181b36..49c9e40f948e 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -397,32 +397,33 @@ static void php_mail_log_to_file(const zend_string *filename, const char *messag } -static int php_mail_detect_multiple_crlf(const zend_string *headers) { +static bool php_mail_detect_multiple_crlf(const zend_string *headers) { /* This function detects multiple/malformed multiple newlines. */ if (!headers || !ZSTR_LEN(headers)) { - return 0; + return false; } + const char *end = ZSTR_VAL(headers) + ZSTR_LEN(headers); const char *hdr = ZSTR_VAL(headers); /* Should not have any newlines at the beginning. */ /* RFC 2822 2.2. Header Fields */ if (*hdr < 33 || *hdr > 126 || *hdr == ':') { - return 1; + return true; } - while(*hdr) { + while (hdr < end) { if (*hdr == '\r') { if (*(hdr+1) == '\0' || *(hdr+1) == '\r' || (*(hdr+1) == '\n' && (*(hdr+2) == '\0' || *(hdr+2) == '\n' || *(hdr+2) == '\r'))) { /* Malformed or multiple newlines. */ - return 1; + return true; } else { hdr += 2; } } else if (*hdr == '\n') { if (*(hdr+1) == '\0' || *(hdr+1) == '\r' || *(hdr+1) == '\n') { /* Malformed or multiple newlines. */ - return 1; + return true; } else { hdr += 2; } @@ -431,7 +432,7 @@ static int php_mail_detect_multiple_crlf(const zend_string *headers) { } } - return 0; + return false; } From 876fb363707617d765273c6e4e0d0182f5e2f604 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 28 Dec 2025 00:54:15 +0100 Subject: [PATCH 5/7] ext/standard/mail.c: use guard pattern to reduce nesting --- ext/standard/mail.c | 173 ++++++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 87 deletions(-) diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 49c9e40f948e..f8eb6e387429 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -586,122 +586,121 @@ PHPAPI bool php_mail(const char *to, const char *subject, const zend_string *mes efree (sendmail_cmd); } - if (sendmail) { - int ret; -#ifndef PHP_WIN32 - if (EACCES == errno) { - php_error_docref(NULL, E_WARNING, "Permission denied: unable to execute shell to run mail delivery binary '%s'", sendmail_path); - pclose(sendmail); + if (UNEXPECTED(!sendmail)) { + php_error_docref(NULL, E_WARNING, "Could not execute mail delivery program '%s'", sendmail_path); #if PHP_SIGCHILD - /* Restore handler in case of error on Windows - Not sure if this applicable on Win but just in case. */ - if (sig_handler) { - signal(SIGCHLD, sig_handler); - } -#endif - MAIL_RET(false); + if (sig_handler) { + signal(SIGCHLD, sig_handler); } #endif - fprintf(sendmail, "To: %s%s", to, line_sep); - fprintf(sendmail, "Subject: %s%s", subject, line_sep); - if (headers && ZSTR_LEN(headers)) { - fprintf(sendmail, "%s%s", ZSTR_VAL(headers), line_sep); + MAIL_RET(false); + } + +#ifndef PHP_WIN32 + if (EACCES == errno) { + php_error_docref(NULL, E_WARNING, "Permission denied: unable to execute shell to run mail delivery binary '%s'", sendmail_path); + pclose(sendmail); +#if PHP_SIGCHILD + /* Restore handler in case of error on Windows + Not sure if this applicable on Win but just in case. */ + if (sig_handler) { + signal(SIGCHLD, sig_handler); } +#endif + MAIL_RET(false); + } +#endif + fprintf(sendmail, "To: %s%s", to, line_sep); + fprintf(sendmail, "Subject: %s%s", subject, line_sep); + if (headers && ZSTR_LEN(headers)) { + fprintf(sendmail, "%s%s", ZSTR_VAL(headers), line_sep); + } - fprintf(sendmail, "%s", line_sep); - - if (cr_lf_mode && zend_string_equals_literal(cr_lf_mode, "lf")) { - char *converted_message = NULL; - size_t msg_len = ZSTR_LEN(message); - size_t new_len = 0; - - if (msg_len > 0) { - for (size_t i = 0; i < msg_len - 1; ++i) { - if (ZSTR_VAL(message)[i] == '\r' && ZSTR_VAL(message)[i + 1] == '\n') { - ++new_len; - } + fprintf(sendmail, "%s", line_sep); + + if (cr_lf_mode && zend_string_equals_literal(cr_lf_mode, "lf")) { + char *converted_message = NULL; + size_t msg_len = ZSTR_LEN(message); + size_t new_len = 0; + + if (msg_len > 0) { + for (size_t i = 0; i < msg_len - 1; ++i) { + if (ZSTR_VAL(message)[i] == '\r' && ZSTR_VAL(message)[i + 1] == '\n') { + ++new_len; } + } - if (new_len == 0) { - fprintf(sendmail, "%s", ZSTR_VAL(message)); - } else { - converted_message = emalloc(msg_len - new_len + 1); - size_t j = 0; - for (size_t i = 0; i < msg_len; ++i) { - if (i < msg_len - 1 && ZSTR_VAL(message)[i] == '\r' && ZSTR_VAL(message)[i + 1] == '\n') { - converted_message[j++] = '\n'; - ++i; /* skip LF part */ - } else { - converted_message[j++] = ZSTR_VAL(message)[i]; - } + if (new_len == 0) { + fprintf(sendmail, "%s", ZSTR_VAL(message)); + } else { + converted_message = emalloc(msg_len - new_len + 1); + size_t j = 0; + for (size_t i = 0; i < msg_len; ++i) { + if (i < msg_len - 1 && ZSTR_VAL(message)[i] == '\r' && ZSTR_VAL(message)[i + 1] == '\n') { + converted_message[j++] = '\n'; + ++i; /* skip LF part */ + } else { + converted_message[j++] = ZSTR_VAL(message)[i]; } - - converted_message[j] = '\0'; - fprintf(sendmail, "%s", converted_message); - efree(converted_message); } + + converted_message[j] = '\0'; + fprintf(sendmail, "%s", converted_message); + efree(converted_message); } - } else { - fprintf(sendmail, "%s", ZSTR_VAL(message)); } + } else { + fprintf(sendmail, "%s", ZSTR_VAL(message)); + } + + fprintf(sendmail, "%s", line_sep); - fprintf(sendmail, "%s", line_sep); + int ret; #ifdef PHP_WIN32 - ret = pclose(sendmail); + ret = pclose(sendmail); #if PHP_SIGCHILD - if (sig_handler) { - signal(SIGCHLD, sig_handler); - } + if (sig_handler) { + signal(SIGCHLD, sig_handler); + } #endif #else - int wstatus = pclose(sendmail); + int wstatus = pclose(sendmail); #if PHP_SIGCHILD - if (sig_handler) { - signal(SIGCHLD, sig_handler); - } + if (sig_handler) { + signal(SIGCHLD, sig_handler); + } #endif - /* Determine the wait(2) exit status */ - if (wstatus == -1) { - php_error_docref(NULL, E_WARNING, "Sendmail pclose failed %d (%s)", errno, strerror(errno)); - MAIL_RET(false); - } else if (WIFSIGNALED(wstatus)) { - php_error_docref(NULL, E_WARNING, "Sendmail killed by signal %d (%s)", WTERMSIG(wstatus), strsignal(WTERMSIG(wstatus))); - MAIL_RET(false); + /* Determine the wait(2) exit status */ + if (wstatus == -1) { + php_error_docref(NULL, E_WARNING, "Sendmail pclose failed %d (%s)", errno, strerror(errno)); + MAIL_RET(false); + } else if (WIFSIGNALED(wstatus)) { + php_error_docref(NULL, E_WARNING, "Sendmail killed by signal %d (%s)", WTERMSIG(wstatus), strsignal(WTERMSIG(wstatus))); + MAIL_RET(false); + } else { + if (WIFEXITED(wstatus)) { + ret = WEXITSTATUS(wstatus); } else { - if (WIFEXITED(wstatus)) { - ret = WEXITSTATUS(wstatus); - } else { - php_error_docref(NULL, E_WARNING, "Sendmail did not exit"); - MAIL_RET(false); - } + php_error_docref(NULL, E_WARNING, "Sendmail did not exit"); + MAIL_RET(false); } + } #endif #if defined(EX_TEMPFAIL) - if ((ret != EX_OK)&&(ret != EX_TEMPFAIL)) + if ((ret != EX_OK)&&(ret != EX_TEMPFAIL)) #elif defined(EX_OK) - if (ret != EX_OK) + if (ret != EX_OK) #else - if (ret != 0) -#endif - { - php_error_docref(NULL, E_WARNING, "Sendmail exited with non-zero exit code %d", ret); - MAIL_RET(false); - } else { - MAIL_RET(true); - } - } else { - php_error_docref(NULL, E_WARNING, "Could not execute mail delivery program '%s'", sendmail_path); -#if PHP_SIGCHILD - if (sig_handler) { - signal(SIGCHLD, sig_handler); - } + if (ret != 0) #endif + { + php_error_docref(NULL, E_WARNING, "Sendmail exited with non-zero exit code %d", ret); MAIL_RET(false); + } else { + MAIL_RET(true); } - - MAIL_RET(true); /* never reached */ } /* }}} */ From 49a04cfd96ae7afcce088fd5c3b2fb087b382f8b Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 28 Dec 2025 00:56:55 +0100 Subject: [PATCH 6/7] ext/standard/mail.c: remove useless default case All other values of the enum are checked --- ext/standard/mail.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ext/standard/mail.c b/ext/standard/mail.c index f8eb6e387429..ea09ca14bbb0 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -154,10 +154,6 @@ static void php_mail_build_headers_elem(smart_str *s, const zend_string *key, zv 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); From f4a47fd5a4cb89913c04604fab01e18dfd017b9b Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sun, 28 Dec 2025 01:00:22 +0100 Subject: [PATCH 7/7] ext/standard/mail.c: remove unused include --- ext/standard/mail.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/standard/mail.c b/ext/standard/mail.c index ea09ca14bbb0..c185afa2937a 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -21,7 +21,6 @@ #include "php.h" #include "ext/standard/info.h" #include "ext/standard/php_string.h" -#include "ext/standard/basic_functions.h" #include "ext/date/php_date.h" #include "zend_smart_str.h"