From 2da3c87114c3334f97452696065eb93febf4170d Mon Sep 17 00:00:00 2001 From: Jesse Hathaway Date: Tue, 3 Jun 2025 10:03:10 -0500 Subject: [PATCH] mail: fix exit code handling of sendmail cmd Prior to this commit the return code of the pclose function was assumed to be the exit code of the process. However, the returned value as specified in wait(2) is a bit packed integer and must be interpreted with the provided macros. This has no effect in success cases as the integer is still zero, but in failure cases the wrong value is used, since the 8 least significant bits contain the status code. After this commit we use the macros to obtain the status code, which fixes the EX_TEMPFAIL conditional. For WIN32 the TSRM popen_ex and pclose function are used. The return value of TSRM's pclose is not bit packed so we only check if the return value is non-zero, which should solve, #43327, https://bugs.php.net/bug.php?id=43327 --- ext/standard/mail.c | 30 +++++++++++++++++--- ext/standard/tests/mail/mail_variation3.phpt | 22 ++++++++++++++ ext/standard/tests/mail/mail_variation4.phpt | 22 ++++++++++++++ ext/standard/tests/mail/mail_variation5.phpt | 22 ++++++++++++++ 4 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 ext/standard/tests/mail/mail_variation3.phpt create mode 100644 ext/standard/tests/mail/mail_variation4.phpt create mode 100644 ext/standard/tests/mail/mail_variation5.phpt diff --git a/ext/standard/mail.c b/ext/standard/mail.c index d886e893309d9..15395ef32ac57 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -25,6 +25,10 @@ #include "ext/date/php_date.h" #include "zend_smart_str.h" +#ifdef HAVE_SYS_WAIT_H +#include +#endif + #ifdef HAVE_SYSEXITS_H # include #endif @@ -417,6 +421,7 @@ PHPAPI int php_mail(const char *to, const char *subject, const char *message, co #endif FILE *sendmail; int ret; + int wstatus; char *sendmail_path = INI_STR("sendmail_path"); char *sendmail_cmd = NULL; char *mail_log = INI_STR("mail.log"); @@ -557,6 +562,7 @@ PHPAPI int php_mail(const char *to, const char *subject, const char *message, co fprintf(sendmail, "%s%s", hdr, line_sep); } fprintf(sendmail, "%s%s%s", line_sep, message, line_sep); +#ifdef PHP_WIN32 ret = pclose(sendmail); #if PHP_SIGCHILD @@ -564,17 +570,33 @@ PHPAPI int php_mail(const char *to, const char *subject, const char *message, co signal(SIGCHLD, sig_handler); } #endif - -#ifdef PHP_WIN32 - if (ret == -1) #else + wstatus = pclose(sendmail); +#if PHP_SIGCHILD + if (sig_handler) { + signal(SIGCHLD, sig_handler); + } +#endif + /* Determine the wait(2) exit status */ + if (wstatus == -1) { + MAIL_RET(0); + } else if (WIFSIGNALED(wstatus)) { + MAIL_RET(0); + } else { + if (WIFEXITED(wstatus)) { + ret = WEXITSTATUS(wstatus); + } else { + MAIL_RET(0); + } + } +#endif + #if defined(EX_TEMPFAIL) if ((ret != EX_OK)&&(ret != EX_TEMPFAIL)) #elif defined(EX_OK) if (ret != EX_OK) #else if (ret != 0) -#endif #endif { MAIL_RET(0); diff --git a/ext/standard/tests/mail/mail_variation3.phpt b/ext/standard/tests/mail/mail_variation3.phpt new file mode 100644 index 0000000000000..03908242d88e9 --- /dev/null +++ b/ext/standard/tests/mail/mail_variation3.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test mail() function : variation sendmail temp fail +--INI-- +sendmail_path=exit 75 +--SKIPIF-- + +--FILE-- + +--EXPECT-- +*** Testing mail() : variation *** +bool(true) diff --git a/ext/standard/tests/mail/mail_variation4.phpt b/ext/standard/tests/mail/mail_variation4.phpt new file mode 100644 index 0000000000000..8b3b301ac0be4 --- /dev/null +++ b/ext/standard/tests/mail/mail_variation4.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test mail() function : variation sigterm +--INI-- +sendmail_path="kill \$\$" +--SKIPIF-- + +--FILE-- + +--EXPECT-- +*** Testing mail() : variation *** +bool(false) diff --git a/ext/standard/tests/mail/mail_variation5.phpt b/ext/standard/tests/mail/mail_variation5.phpt new file mode 100644 index 0000000000000..a6c25feba5e1d --- /dev/null +++ b/ext/standard/tests/mail/mail_variation5.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test mail() function : variation non-zero exit +--INI-- +sendmail_path="exit 123" +--SKIPIF-- + +--FILE-- + +--EXPECT-- +*** Testing mail() : variation *** +bool(false)