Skip to content

Commit 0a86c7a

Browse files
committed
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
1 parent 9187cae commit 0a86c7a

File tree

4 files changed

+92
-4
lines changed

4 files changed

+92
-4
lines changed

ext/standard/mail.c

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
#include "ext/date/php_date.h"
2626
#include "zend_smart_str.h"
2727

28+
#ifdef HAVE_SYS_WAIT_H
29+
#include <sys/wait.h>
30+
#endif
31+
2832
#ifdef HAVE_SYSEXITS_H
2933
# include <sysexits.h>
3034
#endif
@@ -417,6 +421,7 @@ PHPAPI int php_mail(const char *to, const char *subject, const char *message, co
417421
#endif
418422
FILE *sendmail;
419423
int ret;
424+
int wstatus;
420425
char *sendmail_path = INI_STR("sendmail_path");
421426
char *sendmail_cmd = NULL;
422427
char *mail_log = INI_STR("mail.log");
@@ -557,24 +562,41 @@ PHPAPI int php_mail(const char *to, const char *subject, const char *message, co
557562
fprintf(sendmail, "%s%s", hdr, line_sep);
558563
}
559564
fprintf(sendmail, "%s%s%s", line_sep, message, line_sep);
565+
#ifdef PHP_WIN32
560566
ret = pclose(sendmail);
561567

562568
#if PHP_SIGCHILD
563569
if (sig_handler) {
564570
signal(SIGCHLD, sig_handler);
565571
}
566572
#endif
567-
568-
#ifdef PHP_WIN32
569-
if (ret == -1)
570573
#else
574+
wstatus = pclose(sendmail);
575+
#if PHP_SIGCHILD
576+
if (sig_handler) {
577+
signal(SIGCHLD, sig_handler);
578+
}
579+
#endif
580+
/* Determine the wait(2) exit status */
581+
if (wstatus == -1) {
582+
MAIL_RET(0);
583+
} else if (WIFSIGNALED(wstatus)) {
584+
MAIL_RET(0);
585+
} else {
586+
if (WIFEXITED(wstatus)) {
587+
ret = WEXITSTATUS(wstatus);
588+
} else {
589+
MAIL_RET(0);
590+
}
591+
}
592+
#endif
593+
571594
#if defined(EX_TEMPFAIL)
572595
if ((ret != EX_OK)&&(ret != EX_TEMPFAIL))
573596
#elif defined(EX_OK)
574597
if (ret != EX_OK)
575598
#else
576599
if (ret != 0)
577-
#endif
578600
#endif
579601
{
580602
MAIL_RET(0);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Test mail() function : variation sendmail temp fail
3+
--INI--
4+
sendmail_path=exit 75
5+
--SKIPIF--
6+
<?php
7+
if(substr(PHP_OS, 0, 3) == "WIN")
8+
die("skip Won't run on Windows");
9+
?>
10+
--FILE--
11+
<?php
12+
echo "*** Testing mail() : variation ***\n";
13+
14+
// Initialise all required variables
15+
16+
$subject = 'Test Subject';
17+
$message = 'A Message';
18+
var_dump( mail($to, $subject, $message) );
19+
?>
20+
--EXPECT--
21+
*** Testing mail() : variation ***
22+
bool(true)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Test mail() function : variation sigterm
3+
--INI--
4+
sendmail_path="kill \$\$"
5+
--SKIPIF--
6+
<?php
7+
if(substr(PHP_OS, 0, 3) == "WIN")
8+
die("skip Won't run on Windows");
9+
?>
10+
--FILE--
11+
<?php
12+
echo "*** Testing mail() : variation ***\n";
13+
14+
// Initialise all required variables
15+
16+
$subject = 'Test Subject';
17+
$message = 'A Message';
18+
var_dump( mail($to, $subject, $message) );
19+
?>
20+
--EXPECT--
21+
*** Testing mail() : variation ***
22+
bool(false)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Test mail() function : variation non-zero exit
3+
--INI--
4+
sendmail_path="exit 123"
5+
--SKIPIF--
6+
<?php
7+
if(substr(PHP_OS, 0, 3) == "WIN")
8+
die("skip Won't run on Windows");
9+
?>
10+
--FILE--
11+
<?php
12+
echo "*** Testing mail() : variation ***\n";
13+
14+
// Initialise all required variables
15+
16+
$subject = 'Test Subject';
17+
$message = 'A Message';
18+
var_dump( mail($to, $subject, $message) );
19+
?>
20+
--EXPECT--
21+
*** Testing mail() : variation ***
22+
bool(false)

0 commit comments

Comments
 (0)