From 73e43b6e19720112f0d10bd988d840e7537055a4 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 12 Oct 2020 14:04:18 +0200 Subject: [PATCH] Fix #80216: imap_mail_compose() does not validate types/encodings We need to check whether the given `type`s and `encoding`s are within bounds to avoid segfaults and out-of-bound reads. Closes GH-6323. --- NEWS | 2 ++ ext/imap/php_imap.c | 27 ++++++++++++++++++--------- ext/imap/tests/bug80216.phpt | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 ext/imap/tests/bug80216.phpt diff --git a/NEWS b/NEWS index 368199ed74..6e1a2f7857 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,8 @@ PHP NEWS . Fixed bug #80220 (imap_mail_compose() may leak memory). (cmb) . Fixed bug #80223 (imap_mail_compose() leaks envelope on malformed bodies). (cmb) + . Fixed bug #80216 (imap_mail_compose() does not validate types/encodings). + (cmb) - MySQLnd: . Fixed bug #80115 (mysqlnd.debug doesn't recognize absolute paths with diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c index 63b5464808..5f05a0c359 100644 --- a/ext/imap/php_imap.c +++ b/ext/imap/php_imap.c @@ -3631,10 +3631,16 @@ PHP_FUNCTION(imap_mail_compose) topbod = bod; if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type", sizeof("type") - 1)) != NULL) { - bod->type = (short) zval_get_long(pvalue); + zend_long type = zval_get_long(pvalue); + if (type >= 0 && type <= TYPEMAX && body_types[type] != NULL) { + bod->type = (short) type; + } } if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "encoding", sizeof("encoding") - 1)) != NULL) { - bod->encoding = (short) zval_get_long(pvalue); + zend_long encoding = zval_get_long(pvalue); + if (encoding >= 0 && encoding <= ENCMAX && body_encodings[encoding] != NULL) { + bod->encoding = (short) encoding; + } } if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) { convert_to_string_ex(pvalue); @@ -3716,10 +3722,13 @@ PHP_FUNCTION(imap_mail_compose) bod->md5 = cpystr(Z_STRVAL_P(pvalue)); } } else if (Z_TYPE_P(data) == IS_ARRAY && topbod->type == TYPEMULTIPART) { - short type = -1; + short type = 0; SEPARATE_ARRAY(data); if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type", sizeof("type") - 1)) != NULL) { - type = (short) zval_get_long(pvalue); + zend_long tmp_type = zval_get_long(pvalue); + if (tmp_type >= 0 && tmp_type <= TYPEMAX && tmp_type != TYPEMULTIPART && body_types[tmp_type] != NULL) { + type = (short) tmp_type; + } } if (!toppart) { @@ -3732,13 +3741,13 @@ PHP_FUNCTION(imap_mail_compose) } bod = &mypart->body; - - if (type != TYPEMULTIPART) { - bod->type = type; - } + bod->type = type; if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "encoding", sizeof("encoding") - 1)) != NULL) { - bod->encoding = (short) zval_get_long(pvalue); + zend_long encoding = zval_get_long(pvalue); + if (encoding >= 0 && encoding <= ENCMAX && body_encodings[encoding] != NULL) { + bod->encoding = (short) encoding; + } } if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) { convert_to_string_ex(pvalue); diff --git a/ext/imap/tests/bug80216.phpt b/ext/imap/tests/bug80216.phpt new file mode 100644 index 0000000000..ccaf1e1e39 --- /dev/null +++ b/ext/imap/tests/bug80216.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #80216 (imap_mail_compose() does not validate types/encodings) +--SKIPIF-- + +--FILE-- + TYPEMULTIPART], []]); +imap_mail_compose([], [['type' => 12]]); +imap_mail_compose([], [['type' => TYPEMULTIPART], ['type' => 12]]); +imap_mail_compose([], [['encoding' => 8]]); +imap_mail_compose([], [['type' => TYPEMULTIPART], ['encoding' => 8]]); +echo "done\n"; +?> +--EXPECT-- +done -- 2.40.0