Browse Source

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
pull/18926/head
Jesse Hathaway 6 months ago
committed by Jakub Zelenka
parent
commit
c5e7490963
No known key found for this signature in database GPG Key ID: 1C0779DC5C0A9DE4
  1. 32
      ext/standard/mail.c
  2. 22
      ext/standard/tests/mail/mail_variation3.phpt
  3. 22
      ext/standard/tests/mail/mail_variation4.phpt
  4. 22
      ext/standard/tests/mail/mail_variation5.phpt

32
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 <sys/wait.h>
#endif
#ifdef HAVE_SYSEXITS_H
# include <sysexits.h>
#endif
@ -562,6 +566,7 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
}
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);
@ -582,24 +587,41 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c
fprintf(sendmail, "%s%s", hdr, line_sep);
}
fprintf(sendmail, "%s%s%s", line_sep, message, line_sep);
int ret = pclose(sendmail);
#ifdef PHP_WIN32
ret = pclose(sendmail);
#if PHP_SIGCHILD
if (sig_handler) {
signal(SIGCHLD, sig_handler);
}
#endif
#ifdef PHP_WIN32
if (ret == -1)
#else
int 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(false);
} else if (WIFSIGNALED(wstatus)) {
MAIL_RET(false);
} else {
if (WIFEXITED(wstatus)) {
ret = WEXITSTATUS(wstatus);
} else {
MAIL_RET(false);
}
}
#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(false);

22
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--
<?php
if (substr(PHP_OS, 0, 3) == "WIN")
die("skip Won't run on Windows");
?>
--FILE--
<?php
echo "*** Testing mail() : variation ***\n";
// Initialise all required variables
$to = 'user@example.com';
$subject = 'Test Subject';
$message = 'A Message';
var_dump(mail($to, $subject, $message));
?>
--EXPECT--
*** Testing mail() : variation ***
bool(true)

22
ext/standard/tests/mail/mail_variation4.phpt

@ -0,0 +1,22 @@
--TEST--
Test mail() function : variation sigterm
--INI--
sendmail_path="kill \$\$"
--SKIPIF--
<?php
if (substr(PHP_OS, 0, 3) == "WIN")
die("skip Won't run on Windows");
?>
--FILE--
<?php
echo "*** Testing mail() : variation ***\n";
// Initialise all required variables
$to = 'user@example.com';
$subject = 'Test Subject';
$message = 'A Message';
var_dump(mail($to, $subject, $message));
?>
--EXPECT--
*** Testing mail() : variation ***
bool(false)

22
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--
<?php
if (substr(PHP_OS, 0, 3) == "WIN")
die("skip Won't run on Windows");
?>
--FILE--
<?php
echo "*** Testing mail() : variation ***\n";
// Initialise all required variables
$to = 'user@example.com';
$subject = 'Test Subject';
$message = 'A Message';
var_dump(mail($to, $subject, $message));
?>
--EXPECT--
*** Testing mail() : variation ***
bool(false)
Loading…
Cancel
Save