From aae3fef56b0850352e715a7e860a69b33c34fe5d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Wed, 9 Nov 2016 18:12:33 +0100 Subject: PHP 5.5.38 with minor security fix from 5.6.28 --- bug73356.patch | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 353 insertions(+) create mode 100644 bug73356.patch (limited to 'bug73356.patch') diff --git a/bug73356.patch b/bug73356.patch new file mode 100644 index 0000000..5bf0b64 --- /dev/null +++ b/bug73356.patch @@ -0,0 +1,353 @@ +Backported from 5.6.28 by Remi. + + +From 18fef10644d865f9d25e49ed501f4f739efe44fc Mon Sep 17 00:00:00 2001 +From: Stanislav Malyshev +Date: Thu, 3 Nov 2016 20:36:52 -0700 +Subject: [PATCH] More string length checks & fixes + +--- + ext/bz2/bz2.c | 2 +- + ext/iconv/iconv.c | 2 +- + ext/imap/php_imap.c | 2 +- + ext/intl/breakiterator/breakiterator_iterators.cpp | 2 +- + ext/intl/intl_convert.c | 2 +- + ext/intl/locale/locale_methods.c | 9 ++++++++- + ext/intl/msgformat/msgformat_data.c | 4 ++-- + ext/standard/exec.c | 10 +++++----- + ext/standard/php_smart_str.h | 3 ++- + ext/xmlrpc/libxmlrpc/base64.c | 22 +++++++++++++--------- + ext/xmlrpc/libxmlrpc/simplestring.c | 3 ++- + ext/zip/php_zip.c | 6 +++--- + ext/zlib/zlib.c | 2 +- + 13 files changed, 41 insertions(+), 28 deletions(-) + +diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c +index 79ec3ec..2e39f4a 100644 +--- a/ext/bz2/bz2.c ++++ b/ext/bz2/bz2.c +@@ -512,7 +512,7 @@ static PHP_FUNCTION(bzcompress) + dest_len = (unsigned int) (source_len + (0.01 * source_len) + 600); + + /* Allocate the destination buffer */ +- dest = emalloc(dest_len + 1); ++ dest = safe_emalloc(dest_len, 1, 1); + + /* Handle the optional arguments */ + if (argc > 1) { +diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c +index fc45f41..69dd8c1 100644 +--- a/ext/iconv/iconv.c ++++ b/ext/iconv/iconv.c +@@ -2426,7 +2426,7 @@ PHP_NAMED_FUNCTION(php_if_iconv) + &out_buffer, &out_len, out_charset, in_charset); + _php_iconv_show_error(err, out_charset, in_charset TSRMLS_CC); + if (err == PHP_ICONV_ERR_SUCCESS && out_buffer != NULL) { +- RETVAL_STRINGL(out_buffer, out_len, 0); ++ RETVAL_STRINGL_CHECK(out_buffer, out_len, 0); + } else { + if (out_buffer != NULL) { + efree(out_buffer); +diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c +index 6c392fb..00eae89 100644 +--- a/ext/imap/php_imap.c ++++ b/ext/imap/php_imap.c +@@ -3910,7 +3910,7 @@ int _php_imap_mail(char *to, char *subject, char *message, char *headers, char * + #define PHP_IMAP_CLEAN if (bufferTo) efree(bufferTo); if (bufferCc) efree(bufferCc); if (bufferBcc) efree(bufferBcc); if (bufferHeader) efree(bufferHeader); + #define PHP_IMAP_BAD_DEST PHP_IMAP_CLEAN; efree(tempMailTo); return (BAD_MSG_DESTINATION); + +- bufferHeader = (char *)emalloc(bufferLen + 1); ++ bufferHeader = (char *)safe_emalloc(bufferLen, 1, 1); + memset(bufferHeader, 0, bufferLen); + if (to && *to) { + strlcat(bufferHeader, "To: ", bufferLen + 1); +diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp +index 3748991..7065ec6 100644 +--- a/ext/intl/breakiterator/breakiterator_iterators.cpp ++++ b/ext/intl/breakiterator/breakiterator_iterators.cpp +@@ -182,7 +182,7 @@ static void _breakiterator_parts_move_forward(zend_object_iterator *iter TSRMLS_ + } + assert(next <= slen && next >= cur); + len = next - cur; +- res = static_cast(emalloc(len + 1)); ++ res = static_cast(safe_emalloc(len, 1, 1)); + + memcpy(res, &s[cur], len); + res[len] = '\0'; +diff --git a/ext/intl/intl_convert.c b/ext/intl/intl_convert.c +index 92cdc4c..2dde6ad 100644 +--- a/ext/intl/intl_convert.c ++++ b/ext/intl/intl_convert.c +@@ -49,7 +49,7 @@ void intl_convert_utf8_to_utf16( + UErrorCode* status ) + { + UChar* dst_buf = NULL; +- int32_t dst_len = 0; ++ uint32_t dst_len = 0; + + /* If *target is NULL determine required destination buffer size (pre-flighting). + * Otherwise, attempt to convert source string; if *target buffer is not large enough +diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c +index 862b9f5..39d80d5 100644 +--- a/ext/intl/locale/locale_methods.c ++++ b/ext/intl/locale/locale_methods.c +@@ -263,6 +263,9 @@ static char* get_icu_value_internal( const char* loc_name , char* tag_name, int* + int32_t buflen = 512; + UErrorCode status = U_ZERO_ERROR; + ++ if (strlen(loc_name) > INTL_MAX_LOCALE_LEN) { ++ return NULL; ++ } + + if( strcmp(tag_name, LOC_CANONICALIZE_TAG) != 0 ){ + /* Handle grandfathered languages */ +@@ -395,7 +398,7 @@ static void get_icu_value_src_php( char* tag_name, INTERNAL_FUNCTION_PARAMETERS) + if(loc_name_len == 0) { + loc_name = intl_locale_get_default(TSRMLS_C); + } +- ++ + INTL_CHECK_LOCALE_LEN(strlen(loc_name)); + + /* Call ICU get */ +@@ -702,6 +705,8 @@ PHP_FUNCTION( locale_get_keywords ) + RETURN_FALSE; + } + ++ INTL_CHECK_LOCALE_LEN(strlen(loc_name)); ++ + if(loc_name_len == 0) { + loc_name = intl_locale_get_default(TSRMLS_C); + } +@@ -1109,6 +1114,8 @@ PHP_FUNCTION(locale_parse) + RETURN_FALSE; + } + ++ INTL_CHECK_LOCALE_LEN(strlen(loc_name)); ++ + if(loc_name_len == 0) { + loc_name = intl_locale_get_default(TSRMLS_C); + } +diff --git a/ext/intl/msgformat/msgformat_data.c b/ext/intl/msgformat/msgformat_data.c +index 5d49054..9e967da 100644 +--- a/ext/intl/msgformat/msgformat_data.c ++++ b/ext/intl/msgformat/msgformat_data.c +@@ -80,10 +80,10 @@ msgformat_data* msgformat_data_create( TSRMLS_D ) + /* }}} */ + + #ifdef MSG_FORMAT_QUOTE_APOS +-int msgformat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec) ++int msgformat_fix_quotes(UChar **spattern, uint32_t *spattern_len, UErrorCode *ec) + { + if(*spattern && *spattern_len && u_strchr(*spattern, (UChar)'\'')) { +- UChar *npattern = emalloc(sizeof(UChar)*(2*(*spattern_len)+1)); ++ UChar *npattern = safe_emalloc(sizeof(UChar)*2, *spattern_len, sizeof(UChar)); + uint32_t npattern_len; + npattern_len = umsg_autoQuoteApostrophe(*spattern, *spattern_len, npattern, 2*(*spattern_len)+1, ec); + efree(*spattern); +diff --git a/ext/standard/exec.c b/ext/standard/exec.c +index e0ca914..88a6b4a 100644 +--- a/ext/standard/exec.c ++++ b/ext/standard/exec.c +@@ -133,7 +133,7 @@ PHPAPI int php_exec(int type, char *cmd, zval *array, zval *return_value TSRMLS_ + + if (type != 3) { + b = buf; +- ++ + while (php_stream_get_line(stream, b, EXEC_INPUT_BUF, &bufl)) { + /* no new line found, let's read some more */ + if (b[bufl - 1] != '\n' && !php_stream_eof(stream)) { +@@ -330,7 +330,7 @@ PHPAPI char *php_escape_shell_cmd(char *str) + cmd[y++] = str[x]; + break; + #else +- /* % is Windows specific for enviromental variables, ^%PATH% will ++ /* % is Windows specific for enviromental variables, ^%PATH% will + output PATH while ^%PATH^% will not. escapeshellcmd will escape all % and !. + */ + case '%': +@@ -492,7 +492,7 @@ PHP_FUNCTION(escapeshellcmd) + return; + } + cmd = php_escape_shell_cmd(command); +- RETVAL_STRING(cmd, 0); ++ RETVAL_STRINGL_CHECK(cmd, strlen(cmd), 0); + } else { + RETVAL_EMPTY_STRING(); + } +@@ -517,7 +517,7 @@ PHP_FUNCTION(escapeshellarg) + return; + } + cmd = php_escape_shell_arg(argument); +- RETVAL_STRING(cmd, 0); ++ RETVAL_STRINGL_CHECK(cmd, strlen(cmd), 0); + } + } + /* }}} */ +@@ -551,7 +551,7 @@ PHP_FUNCTION(shell_exec) + php_stream_close(stream); + + if (total_readbytes > 0) { +- RETVAL_STRINGL(ret, total_readbytes, 0); ++ RETVAL_STRINGL_CHECK(ret, total_readbytes, 0); + } + } + /* }}} */ +diff --git a/ext/standard/php_smart_str.h b/ext/standard/php_smart_str.h +index edd9d3a..6baa49f 100644 +--- a/ext/standard/php_smart_str.h ++++ b/ext/standard/php_smart_str.h +@@ -57,7 +57,8 @@ + newlen = (n); \ + (d)->a = newlen < SMART_STR_START_SIZE \ + ? SMART_STR_START_SIZE \ +- : newlen + SMART_STR_PREALLOC; \ ++ : (newlen >= (INT_MAX - SMART_STR_PREALLOC)? newlen \ ++ : (newlen + SMART_STR_PREALLOC)); \ + SMART_STR_DO_REALLOC(d, what); \ + } else { \ + newlen = (d)->len + (n); \ +diff --git a/ext/xmlrpc/libxmlrpc/base64.c b/ext/xmlrpc/libxmlrpc/base64.c +index d020bd6..5ebdf31 100644 +--- a/ext/xmlrpc/libxmlrpc/base64.c ++++ b/ext/xmlrpc/libxmlrpc/base64.c +@@ -15,6 +15,7 @@ static const char rcsid[] = "#(@) $Id$"; + /* ENCODE -- Encode binary file into base64. */ + #include + #include ++#include + + #include "base64.h" + +@@ -31,6 +32,9 @@ void buffer_new(struct buffer_st *b) + + void buffer_add(struct buffer_st *b, char c) + { ++ if ((INT_MAX - b->length) <= 512) { ++ return; ++ } + *(b->ptr++) = c; + b->offset++; + if (b->offset == b->length) { +@@ -54,13 +58,13 @@ void base64_encode_xmlrpc(struct buffer_st *b, const char *source, int length) + int i, hiteof = 0; + int offset = 0; + int olen; +- ++ + olen = 0; +- ++ + buffer_new(b); +- ++ + /* Fill dtable with character encodings. */ +- ++ + for (i = 0; i < 26; i++) { + dtable[i] = 'A' + i; + dtable[26 + i] = 'a' + i; +@@ -70,16 +74,16 @@ void base64_encode_xmlrpc(struct buffer_st *b, const char *source, int length) + } + dtable[62] = '+'; + dtable[63] = '/'; +- ++ + while (!hiteof) { + unsigned char igroup[3], ogroup[4]; + int c, n; +- ++ + igroup[0] = igroup[1] = igroup[2] = 0; + for (n = 0; n < 3; n++) { + c = *(source++); + offset++; +- if (offset > length) { ++ if (offset > length || offset <= 0) { + hiteof = 1; + break; + } +@@ -90,11 +94,11 @@ void base64_encode_xmlrpc(struct buffer_st *b, const char *source, int length) + ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)]; + ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)]; + ogroup[3] = dtable[igroup[2] & 0x3F]; +- ++ + /* Replace characters in output stream with "=" pad + characters if fewer than three characters were + read from the end of the input stream. */ +- ++ + if (n < 3) { + ogroup[3] = '='; + if (n < 2) { +diff --git a/ext/xmlrpc/libxmlrpc/simplestring.c b/ext/xmlrpc/libxmlrpc/simplestring.c +index c88754f..98b5c81 100644 +--- a/ext/xmlrpc/libxmlrpc/simplestring.c ++++ b/ext/xmlrpc/libxmlrpc/simplestring.c +@@ -80,6 +80,7 @@ static const char rcsid[] = "#(@) $Id$"; + + #include + #include ++#include + #include "simplestring.h" + + #define my_free(thing) if(thing) {free(thing); thing = 0;} +@@ -200,7 +201,7 @@ void simplestring_addn(simplestring* target, const char* source, size_t add_len) + simplestring_init_str(target); + } + +- if((SIZE_MAX - add_len) < target->len || (SIZE_MAX - add_len - 1) < target->len) { ++ if((INT_MAX - add_len) < target->len || (INT_MAX - add_len - 1) < target->len) { + /* check for overflows, if there's a potential overflow do nothing */ + return; + } + +From f14da6f0b01e329c3809de93c1b928ad4b4fa6fa Mon Sep 17 00:00:00 2001 +From: Stanislav Malyshev +Date: Thu, 3 Nov 2016 22:10:22 -0700 +Subject: [PATCH] Add length check for bzcompress too - fix for bug #73356 + +--- + ext/bz2/bz2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c +index 2e39f4a..13b9f38 100644 +--- a/ext/bz2/bz2.c ++++ b/ext/bz2/bz2.c +@@ -532,7 +532,7 @@ static PHP_FUNCTION(bzcompress) + so we erealloc() the buffer to the proper size */ + dest = erealloc(dest, dest_len + 1); + dest[dest_len] = 0; +- RETURN_STRINGL(dest, dest_len, 0); ++ RETURN_STRINGL_CHECK(dest, dest_len, 0); + } + } + /* }}} */ +From e43b3bff6a6f5358712ff18961ffa650224dcdcb Mon Sep 17 00:00:00 2001 +From: Anatol Belski +Date: Sun, 6 Nov 2016 17:51:25 +0100 +Subject: [PATCH] add missing RETURN_STRINGL_CHECK + +As RETVAL_STRINGL_CHECK is already there, this one is needed for +completion. One place in ext/bz2 is missing that, so it will likely +be useful for other possible fixes. +--- + Zend/zend_API.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/Zend/zend_API.h b/Zend/zend_API.h +index dadeaf5..41aa65f 100644 +--- a/Zend/zend_API.h ++++ b/Zend/zend_API.h +@@ -654,7 +654,7 @@ + } \ + RETVAL_STRINGL((s), (int)__len, (dup)); \ + } while (0) +- ++#define RETURN_STRINGL_CHECK(s, len, dup) { RETVAL_STRINGL_CHECK(s, len, dup); return; } + + + #define SET_VAR_STRING(n, v) { \ -- cgit