From aa3afd6ef4518756c51779155ea668d0fa5dd2c4 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 22 Oct 2025 07:18:23 +0100 Subject: [PATCH 1/2] Fix GH-20257: heap overflow on empty message in `lf` mode. close GH-20268 --- ext/standard/mail.c | 42 +++++++++++++++------------- ext/standard/tests/mail/gh20257.phpt | 15 ++++++++++ 2 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 ext/standard/tests/mail/gh20257.phpt diff --git a/ext/standard/mail.c b/ext/standard/mail.c index f6161782bdd76..8c8b4e6717e0b 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -614,34 +614,36 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c size_t msg_len = strlen(message); size_t new_len = 0; - for (size_t i = 0; i < msg_len - 1; ++i) { - if (message[i] == '\r' && message[i + 1] == '\n') { - ++new_len; + if (msg_len > 0) { + for (size_t i = 0; i < msg_len - 1; ++i) { + if (message[i] == '\r' && message[i + 1] == '\n') { + ++new_len; + } } - } - if (new_len == 0) { - fprintf(sendmail, "%s", 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') { - converted_message[j++] = '\n'; - ++i; /* skip LF part */ - } else { - converted_message[j++] = message[i]; + if (new_len == 0) { + fprintf(sendmail, "%s", 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') { + converted_message[j++] = '\n'; + ++i; /* skip LF part */ + } else { + converted_message[j++] = 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", message); } - + fprintf(sendmail, "%s", line_sep); #ifdef PHP_WIN32 ret = pclose(sendmail); diff --git a/ext/standard/tests/mail/gh20257.phpt b/ext/standard/tests/mail/gh20257.phpt new file mode 100644 index 0000000000000..5f5c50e4cb725 --- /dev/null +++ b/ext/standard/tests/mail/gh20257.phpt @@ -0,0 +1,15 @@ +--TEST-- +GH-20257: heap overflow with empty message and mail.cr_lf_mode=lf set +--INI-- +sendmail_path="exit 0" +mail.cr_lf_mode=lf +--CREDITS-- +YuanchengJiang +--FILE-- + +--EXPECT-- +bool(true) From de52e44a190e8fd3a4916bd9bcfbe0f9206baa6d Mon Sep 17 00:00:00 2001 From: David Carlier Date: Wed, 22 Oct 2025 09:57:47 +0100 Subject: [PATCH 2/2] fix test --- ext/standard/tests/mail/gh20257.phpt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ext/standard/tests/mail/gh20257.phpt b/ext/standard/tests/mail/gh20257.phpt index 5f5c50e4cb725..68374173413fc 100644 --- a/ext/standard/tests/mail/gh20257.phpt +++ b/ext/standard/tests/mail/gh20257.phpt @@ -1,7 +1,7 @@ --TEST-- GH-20257: heap overflow with empty message and mail.cr_lf_mode=lf set --INI-- -sendmail_path="exit 0" +sendmail_path="exit 1" mail.cr_lf_mode=lf --CREDITS-- YuanchengJiang @@ -11,5 +11,7 @@ $to = "user@example.com"; $subject = $message = ""; var_dump(mail($to, $subject, $message)); ?> ---EXPECT-- -bool(true) +--EXPECTF-- + +Warning: mail(): Sendmail exited with non-zero exit code 1 in %s on line %d +bool(false)