From 72dbb7f416160f490c4e9987040989a10ad431c7 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 3 Aug 2016 00:58:55 -0700 Subject: [PATCH 01/49] Fix bug #72674 - check both curl_escape and curl_unescape --- ext/curl/interface.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index be15785cd0e..7069710ece1 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -3517,7 +3517,7 @@ PHP_FUNCTION(curl_reset) PHP_FUNCTION(curl_escape) { char *str = NULL, *res = NULL; - size_t str_len = 0; + size_t str_len = 0; zval *zid; php_curl *ch; @@ -3529,6 +3529,10 @@ PHP_FUNCTION(curl_escape) RETURN_FALSE; } + if (ZEND_SIZE_T_INT_OVFL(str_len)) { + RETURN_FALSE; + } + if ((res = curl_easy_escape(ch->cp, str, str_len))) { RETVAL_STRING(res); curl_free(res); @@ -3556,7 +3560,7 @@ PHP_FUNCTION(curl_unescape) RETURN_FALSE; } - if (str_len > INT_MAX) { + if (ZEND_SIZE_T_INT_OVFL(str_len)) { RETURN_FALSE; } From 4f6a97f5321ef617b98a1f79aac1ad447d13b2b4 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 22:33:18 -0700 Subject: [PATCH 02/49] Fix for bug #72782: mcrypt accepts only ints, so don't pass anything else --- ext/mcrypt/mcrypt.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ext/mcrypt/mcrypt.c b/ext/mcrypt/mcrypt.c index 73acaa29f2d..9865cbb9fcc 100644 --- a/ext/mcrypt/mcrypt.c +++ b/ext/mcrypt/mcrypt.c @@ -633,6 +633,10 @@ PHP_FUNCTION(mcrypt_generic) RETURN_FALSE } + if (data_len > INT_MAX) { + php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX); + RETURN_FALSE; + } /* Check blocksize */ if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ block_size = mcrypt_enc_get_block_size(pm->td); @@ -645,10 +649,6 @@ PHP_FUNCTION(mcrypt_generic) memset(ZSTR_VAL(data_str), 0, data_size); memcpy(ZSTR_VAL(data_str), data, data_len); } else { /* It's not a block algorithm */ - if (data_len > INT_MAX) { - php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX); - RETURN_FALSE; - } data_size = (int)data_len; data_str = zend_string_alloc(data_size, 0); memset(ZSTR_VAL(data_str), 0, data_size); @@ -688,6 +688,10 @@ PHP_FUNCTION(mdecrypt_generic) } /* Check blocksize */ + if (data_len > INT_MAX) { + php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX); + RETURN_FALSE; + } if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */ block_size = mcrypt_enc_get_block_size(pm->td); data_size = ((((int)data_len - 1) / block_size) + 1) * block_size; @@ -699,10 +703,6 @@ PHP_FUNCTION(mdecrypt_generic) memset(data_s, 0, data_size); memcpy(data_s, data, data_len); } else { /* It's not a block algorithm */ - if (data_len > INT_MAX) { - php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX); - RETURN_FALSE; - } data_size = (int)data_len; data_s = emalloc(data_size + 1); memset(data_s, 0, data_size); From 7bf6d985351ad92715b18692ba128842b725f1c0 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 23:46:33 -0700 Subject: [PATCH 03/49] Check for string overflow --- ext/standard/php_smart_string.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ext/standard/php_smart_string.h b/ext/standard/php_smart_string.h index a832376064d..1175d32907a 100644 --- a/ext/standard/php_smart_string.h +++ b/ext/standard/php_smart_string.h @@ -52,19 +52,22 @@ #define SMART_STRING_DO_REALLOC(d, what) \ (d)->c = SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what)) -#define smart_string_alloc4(d, n, what, newlen) do { \ +#define smart_string_alloc4(d, n, what, newlen) do { \ if (!(d)->c) { \ (d)->len = 0; \ newlen = (n); \ - (d)->a = newlen < SMART_STRING_START_SIZE \ - ? SMART_STRING_START_SIZE \ - : newlen + SMART_STRING_PREALLOC; \ - SMART_STRING_DO_REALLOC(d, what); \ + (d)->a = newlen < SMART_STRING_START_SIZE \ + ? SMART_STRING_START_SIZE \ + : newlen + SMART_STRING_PREALLOC; \ + SMART_STRING_DO_REALLOC(d, what); \ } else { \ + if(UNEXPECTED(n > SIZE_MAX - (d)->len)) { \ + zend_error(E_ERROR, "String size overflow"); \ + } \ newlen = (d)->len + (n); \ if (newlen >= (d)->a) { \ - (d)->a = newlen + SMART_STRING_PREALLOC; \ - SMART_STRING_DO_REALLOC(d, what); \ + (d)->a = newlen + SMART_STRING_PREALLOC; \ + SMART_STRING_DO_REALLOC(d, what); \ } \ } \ } while (0) From 6304a611cdaa3563045dbab84824202bc634bcce Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 23:46:58 -0700 Subject: [PATCH 04/49] Use size_t for path length --- main/fopen_wrappers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c index c3646ee0fd2..bf78db3bdf1 100644 --- a/main/fopen_wrappers.c +++ b/main/fopen_wrappers.c @@ -144,7 +144,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path char *path_file; int resolved_basedir_len; int resolved_name_len; - int path_len; + size_t path_len; int nesting_level = 0; /* Special case basedir==".": Use script-directory */ @@ -153,7 +153,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir)); } - path_len = (int)strlen(path); + path_len = strlen(path); if (path_len > (MAXPATHLEN - 1)) { /* empty and too long paths are invalid */ return -1; @@ -164,7 +164,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path return -1; } - path_len = (int)strlen(resolved_name); + path_len = strlen(resolved_name); memcpy(path_tmp, resolved_name, path_len + 1); /* safe */ while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) { From c2a13ced4272f2e65d2773e2ea6ca11c1ce4a911 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 14 Aug 2016 19:07:15 -0700 Subject: [PATCH 05/49] Fix bug #72742 - memory allocator fails to realloc small block to large one --- Zend/zend_alloc.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 18765593174..a79d67b4b99 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -1548,21 +1548,21 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size, si ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted"); if (info & ZEND_MM_IS_SRUN) { - int old_bin_num, bin_num; - - old_bin_num = ZEND_MM_SRUN_BIN_NUM(info); + int old_bin_num = ZEND_MM_SRUN_BIN_NUM(info); old_size = bin_data_size[old_bin_num]; - bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size); - if (old_bin_num == bin_num) { + if (size <= ZEND_MM_MAX_SMALL_SIZE) { + int bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size); + if (old_bin_num == bin_num) { #if ZEND_DEBUG - dbg = zend_mm_get_debug_info(heap, ptr); - dbg->size = real_size; - dbg->filename = __zend_filename; - dbg->orig_filename = __zend_orig_filename; - dbg->lineno = __zend_lineno; - dbg->orig_lineno = __zend_orig_lineno; + dbg = zend_mm_get_debug_info(heap, ptr); + dbg->size = real_size; + dbg->filename = __zend_filename; + dbg->orig_filename = __zend_orig_filename; + dbg->lineno = __zend_lineno; + dbg->orig_lineno = __zend_orig_lineno; #endif - return ptr; + return ptr; + } } } else /* if (info & ZEND_MM_IS_LARGE_RUN) */ { ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted"); From 67d0fe39ee554563476ecae13c626580ae1a6612 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 16 Aug 2016 12:34:25 +0200 Subject: [PATCH 06/49] Fix bug #72837 - integer overflow in bzdecompress caused heap corruption Conflicts: ext/bz2/bz2.c --- ext/bz2/bz2.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index bc6379aeeaf..60bb71ee8d7 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -594,16 +594,26 @@ static PHP_FUNCTION(bzdecompress) /* compression is better then 2:1, need to allocate more memory */ bzs.avail_out = source_len; size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; + if (size > SIZE_MAX) { + /* no reason to continue if we're going to drop it anyway */ + break; + } dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size ); bzs.next_out = dest + size; } if (error == BZ_STREAM_END || error == BZ_OK) { size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; - dest = safe_erealloc(dest, 1, (size_t) size, 1); - dest[size] = '\0'; - RETVAL_STRINGL(dest, (int) size); - efree(dest); + if (size > SIZE_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX); + efree(dest); + RETVAL_LONG(BZ_MEM_ERROR); + } else { + dest = safe_erealloc(dest, 1, (size_t) size, 1); + dest[size] = '\0'; + RETVAL_STRINGL(dest, (size_t) size); + efree(dest); + } } else { /* real error */ efree(dest); RETVAL_LONG(error); From 0c8a2a2cd1056b7dc403eacb5d2c0eec6ce47c6f Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 23:43:56 -0700 Subject: [PATCH 07/49] Fix for bug #72790 and bug #72799 (cherry picked from commit a14fdb9746262549bbbb96abb87338bacd147e1b) Conflicts: ext/wddx/wddx.c --- ext/wddx/tests/bug72790.phpt | 35 +++++++++++++++++++++++++++++++++++ ext/wddx/tests/bug72799.phpt | 28 ++++++++++++++++++++++++++++ ext/wddx/wddx.c | 2 +- 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 ext/wddx/tests/bug72790.phpt create mode 100644 ext/wddx/tests/bug72799.phpt diff --git a/ext/wddx/tests/bug72790.phpt b/ext/wddx/tests/bug72790.phpt new file mode 100644 index 00000000000..a60524bdaf1 --- /dev/null +++ b/ext/wddx/tests/bug72790.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug 72790: wddx_deserialize null dereference with invalid xml +--SKIPIF-- + +--FILE-- + + + + |array> + + + + + + + + + + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +NULL \ No newline at end of file diff --git a/ext/wddx/tests/bug72799.phpt b/ext/wddx/tests/bug72799.phpt new file mode 100644 index 00000000000..5861d5538f4 --- /dev/null +++ b/ext/wddx/tests/bug72799.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #72799: wddx_deserialize null dereference in php_wddx_pop_element +--SKIPIF-- + +--FILE-- + + + + + + 1998-06-12T04:32:12+00 + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +NULL \ No newline at end of file diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index d28cb7a0acb..11cf0be62e3 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -886,10 +886,10 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) if (Z_TYPE(ent1->data) == IS_UNDEF) { if (stack->top > 1) { stack->top--; + efree(ent1); } else { stack->done = 1; } - efree(ent1); return; } From 4bccb8e94e638f24582d8120f142d9e32c27ad0d Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 16 Aug 2016 12:53:40 +0200 Subject: [PATCH 08/49] add missing skipif section --- ext/wddx/tests/bug72142.phpt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/wddx/tests/bug72142.phpt b/ext/wddx/tests/bug72142.phpt index 3976bb2554f..0c93ecc9705 100644 --- a/ext/wddx/tests/bug72142.phpt +++ b/ext/wddx/tests/bug72142.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #72142: WDDX Packet Injection Vulnerability in wddx_serialize_value() +--SKIPIF-- + --FILE-- Date: Tue, 16 Aug 2016 13:01:06 +0200 Subject: [PATCH 09/49] fix tests --- ext/wddx/tests/bug72790.phpt | 5 +++-- ext/wddx/tests/bug72799.phpt | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ext/wddx/tests/bug72790.phpt b/ext/wddx/tests/bug72790.phpt index a60524bdaf1..5bc44784010 100644 --- a/ext/wddx/tests/bug72790.phpt +++ b/ext/wddx/tests/bug72790.phpt @@ -31,5 +31,6 @@ XML; $array = wddx_deserialize($xml); var_dump($array); ?> ---EXPECT-- -NULL \ No newline at end of file +--EXPECTF-- +Notice: Undefined variable: array in %s%ebug72790.php on line %d +NULL diff --git a/ext/wddx/tests/bug72799.phpt b/ext/wddx/tests/bug72799.phpt index 5861d5538f4..53ac95bd6a8 100644 --- a/ext/wddx/tests/bug72799.phpt +++ b/ext/wddx/tests/bug72799.phpt @@ -24,5 +24,6 @@ XML; $array = wddx_deserialize($xml); var_dump($array); ?> ---EXPECT-- -NULL \ No newline at end of file +--EXPECTF-- +Notice: Undefined variable: array in %s%ebug72799.php on line 16 +NULL From e5b0952be2d7c93bdf491d99f50a14df46c30cd2 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 16 Aug 2016 13:08:24 +0200 Subject: [PATCH 10/49] Fix bug #72771: ftps:// opendir wrapper is vulnerable to protocol downgrade attack (cherry picked from commit f9c2edb4dbc01a817989b70ca7726f177bb1a103) Conflicts: ext/standard/ftp_fopen_wrapper.c --- ext/standard/ftp_fopen_wrapper.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index 10dcdb8006a..a28b6c14b17 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -187,7 +187,8 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char /* get the response */ result = GET_FTP_RESULT(stream); if (result != 334) { - use_ssl = 0; + php_stream_wrapper_log_error(wrapper, options, "Server doesn't support FTPS."); + goto connect_errexit; } else { /* we must reuse the old SSL session id */ /* if we talk to an old ftpd-ssl */ @@ -707,7 +708,7 @@ php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const char *pat if (result > 299 || result < 200) goto opendir_errexit; - // tmp_line isn't relevant after the php_fopen_do_pasv(). + // tmp_line isn't relevant after the php_fopen_do_pasv(). tmp_line[0] = '\0'; /* set up the passive connection */ @@ -735,7 +736,7 @@ php_stream * php_stream_ftp_opendir(php_stream_wrapper *wrapper, const char *pat php_stream_wrapper_log_error(wrapper, options, "Unable to activate SSL mode"); php_stream_close(datastream); datastream = NULL; - goto opendir_errexit; + goto opendir_errexit; } From f1486f0fd63e888028e625a5ae02f10cc729c4c7 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 7 Aug 2016 16:26:52 -0700 Subject: [PATCH 11/49] Fix bug #72750: wddx_deserialize null dereference (cherry picked from commit 6930a1d12c47aa1d2675837852910d177b0ceb11) Conflicts: ext/wddx/wddx.c --- ext/wddx/tests/bug72750.phpt | 34 ++++++++++++++++++++++++++++++++++ ext/wddx/wddx.c | 6 +++++- 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 ext/wddx/tests/bug72750.phpt diff --git a/ext/wddx/tests/bug72750.phpt b/ext/wddx/tests/bug72750.phpt new file mode 100644 index 00000000000..3a6794df280 --- /dev/null +++ b/ext/wddx/tests/bug72750.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #72750: wddx_deserialize null dereference +--SKIPIF-- + +--FILE-- + + + +
+ + + + \\tYmluYXJRhdGE= + + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +array(1) { + ["aBinary"]=> + string(0) "" +} diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 11cf0be62e3..40b41ba373c 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -897,7 +897,11 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) zend_string *new_str = php_base64_decode( (unsigned char *)Z_STRVAL(ent1->data), Z_STRLEN(ent1->data)); zval_ptr_dtor(&ent1->data); - ZVAL_STR(&ent1->data, new_str); + if (new_str) { + ZVAL_STR(&ent1->data, new_str); + } else { + ZVAL_EMPTY_STRING(&ent1->data); + } } /* Call __wakeup() method on the object. */ From e70069a62fb7252252cad9506fac5baf4ac11d21 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 00:14:58 -0700 Subject: [PATCH 12/49] Fix bug #72730 - imagegammacorrect allows arbitrary write access (cherry picked from commit 047fe0ed03093a496691d376fcf51a7e2f1d04b0) Conflicts: ext/gd/gd.c --- ext/gd/gd.c | 5 +++++ ext/gd/tests/bug72730.phpt | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 ext/gd/tests/bug72730.phpt diff --git a/ext/gd/gd.c b/ext/gd/gd.c index c7c6fe3fae4..c952ee9b5a9 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3039,6 +3039,11 @@ PHP_FUNCTION(imagegammacorrect) return; } + if ( input <= 0.0 || output <= 0.0 ) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Gamma values should be positive"); + RETURN_FALSE; + } + if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) { RETURN_FALSE; } diff --git a/ext/gd/tests/bug72730.phpt b/ext/gd/tests/bug72730.phpt new file mode 100644 index 00000000000..e7c13cb5e9d --- /dev/null +++ b/ext/gd/tests/bug72730.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #72730: imagegammacorrect allows arbitrary write access +--SKIPIF-- + +--FILE-- + +DONE +--EXPECTF-- +Warning: imagegammacorrect(): Gamma values should be positive in %sbug72730.php on line %d +DONE \ No newline at end of file From b735a4419c1e796520b395a2aa0b6943d9157b73 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 3 Aug 2016 22:37:57 -0700 Subject: [PATCH 13/49] Fix bug #72708 - php_snmp_parse_oid integer overflow in memory allocation (cherry picked from commit c3f6d6da100c6451a540680504de4105b8bed83c) Conflicts: ext/snmp/snmp.c main/php_version.h --- ext/snmp/snmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index 7b685ff5dcc..63e8095ed7c 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -1011,7 +1011,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu php_error_docref(NULL, E_WARNING, "Got empty OID array"); return FALSE; } - objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_P(oid))); + objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(Z_ARRVAL_P(oid)), 0); if (objid_query->vars == NULL) { php_error_docref(NULL, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno)); efree(objid_query->vars); From 28022c9b1fd937436ab67bb3d61f652c108baf96 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 16 Aug 2016 14:37:39 +0200 Subject: [PATCH 14/49] Fix bug#72697 - select_colors write out-of-bounds (cherry picked from commit b6f13a5ef9d6280cf984826a5de012a32c396cd4) Conflicts: ext/gd/gd.c --- ext/gd/gd.c | 6 +++--- ext/gd/tests/bug72697.phpt | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 ext/gd/tests/bug72697.phpt diff --git a/ext/gd/gd.c b/ext/gd/gd.c index c952ee9b5a9..0346a74634b 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -1537,11 +1537,11 @@ PHP_FUNCTION(imagetruecolortopalette) RETURN_FALSE; } - if (ncolors <= 0) { - php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero"); + if (ncolors <= 0 || ZEND_LONG_INT_OVFL(ncolors)) { + php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero and no more than %d", INT_MAX); RETURN_FALSE; } - gdImageTrueColorToPalette(im, dither, ncolors); + gdImageTrueColorToPalette(im, dither, (int)ncolors); RETURN_TRUE; } diff --git a/ext/gd/tests/bug72697.phpt b/ext/gd/tests/bug72697.phpt new file mode 100644 index 00000000000..6110385fcb8 --- /dev/null +++ b/ext/gd/tests/bug72697.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #72697: select_colors write out-of-bounds +--SKIPIF-- + +--FILE-- + +DONE +--EXPECTF-- +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than 2147483647 in %sbug72697.php on line %d +DONE \ No newline at end of file From d926a48fd27942d15190a6defdcb05b1e07c9701 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 16 Aug 2016 14:41:24 +0200 Subject: [PATCH 15/49] fix tests --- ext/gd/tests/imagetruecolortopalette_error3.phpt | 2 +- ext/gd/tests/imagetruecolortopalette_error4.phpt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/gd/tests/imagetruecolortopalette_error3.phpt b/ext/gd/tests/imagetruecolortopalette_error3.phpt index de3a62d0a55..46e3f487e0b 100644 --- a/ext/gd/tests/imagetruecolortopalette_error3.phpt +++ b/ext/gd/tests/imagetruecolortopalette_error3.phpt @@ -25,4 +25,4 @@ Warning: imagetruecolortopalette() expects parameter 3 to be integer, resource g Warning: imagetruecolortopalette() expects parameter 3 to be integer, array given in %s on line %d -Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d \ No newline at end of file +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s on line %d diff --git a/ext/gd/tests/imagetruecolortopalette_error4.phpt b/ext/gd/tests/imagetruecolortopalette_error4.phpt index b9661e3b852..f0e18b86be1 100644 --- a/ext/gd/tests/imagetruecolortopalette_error4.phpt +++ b/ext/gd/tests/imagetruecolortopalette_error4.phpt @@ -16,6 +16,6 @@ imagetruecolortopalette($image, true, -1); ?> --EXPECTF-- -Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d -Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d \ No newline at end of file +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d From 24fb60ffe9d23a6af27d96b74a85f6a237bbd14a Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 8 Aug 2016 00:49:34 -0700 Subject: [PATCH 16/49] Fixed bug #72627: Memory Leakage In exif_process_IFD_in_TIFF (cherry picked from commit 620b01337cc39f856ca68c34c35e154f5f0682fc) Conflicts: ext/exif/exif.c --- ext/exif/exif.c | 4 ++ ext/exif/tests/bug72627.phpt | 71 +++++++++++++++++++++++++++++++++++ ext/exif/tests/bug72627.tiff | Bin 0 -> 1250 bytes 3 files changed, 75 insertions(+) create mode 100644 ext/exif/tests/bug72627.phpt create mode 100644 ext/exif/tests/bug72627.tiff diff --git a/ext/exif/exif.c b/ext/exif/exif.c index cf221419d54..2b9d560a51a 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -3747,6 +3747,10 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); if (fgot < ImageInfo->Thumbnail.size) { EXIF_ERRLOG_THUMBEOF(ImageInfo) + efree(ImageInfo->Thumbnail.data); + ImageInfo->Thumbnail.data = NULL; + } else { + exif_thumbnail_build(ImageInfo); } exif_thumbnail_build(ImageInfo); } diff --git a/ext/exif/tests/bug72627.phpt b/ext/exif/tests/bug72627.phpt new file mode 100644 index 00000000000..bb6a1fae99a --- /dev/null +++ b/ext/exif/tests/bug72627.phpt @@ -0,0 +1,71 @@ +--TEST-- +Bug #72627 (Memory Leakage In exif_process_IFD_in_TIFF) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d + +Warning: exif_read_data(%s): Error in TIFF: filesize(x04E2) less than start of IFD dir(x829A0004) in %sbug72627.php on line %d + +Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d +array(11) { + ["FileName"]=> + string(13) "bug72627.tiff" + ["FileDateTime"]=> + int(%d) + ["FileSize"]=> + int(1250) + ["FileType"]=> + int(7) + ["MimeType"]=> + string(10) "image/tiff" + ["SectionsFound"]=> + string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF" + ["COMPUTED"]=> + array(10) { + ["html"]=> + string(24) "width="128" height="132"" + ["Height"]=> + int(132) + ["Width"]=> + int(128) + ["IsColor"]=> + int(0) + ["ByteOrderMotorola"]=> + int(0) + ["ApertureFNumber"]=> + string(5) "f/1.0" + ["Thumbnail.FileType"]=> + int(2) + ["Thumbnail.MimeType"]=> + string(10) "image/jpeg" + ["Thumbnail.Height"]=> + int(132) + ["Thumbnail.Width"]=> + int(128) + } + ["XResolution"]=> + string(21) "1414812756/1414812756" + ["THUMBNAIL"]=> + array(5) { + ["ImageWidth"]=> + int(128) + ["ImageLength"]=> + int(132) + ["JPEGInterchangeFormat"]=> + int(1280) + ["JPEGInterchangeFormatLength"]=> + int(100) + ["THUMBNAIL"]=> + NULL + } + ["ExposureTime"]=> + string(21) "1414812756/1414812756" + ["FNumber"]=> + string(21) "1414812756/1414812756" +} diff --git a/ext/exif/tests/bug72627.tiff b/ext/exif/tests/bug72627.tiff new file mode 100644 index 0000000000000000000000000000000000000000..229190a6041926d960856267a5285d887eda49b5 GIT binary patch literal 1250 zcmebD)MDUZU|?WkkYZ$IU<9%lSQr>G+gZSDC9uq_CWwp>P-ZTa?E+*wKom1FgViXgZXg0u%><|2O{MVo39)0|*%fqaiRF0wXpA{@(-uY6E(R literal 0 HcmV?d00001 From e3829b88694460a2e5af10ad5eee9966fa55e589 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Thu, 4 Aug 2016 00:17:42 -0700 Subject: [PATCH 17/49] Fix bug #72749: wddx_deserialize allows illegal memory access (cherry picked from commit 659a21dc20f0b64dafd8cb16573059d3b45cce6b) Conflicts: ext/wddx/wddx.c --- ext/wddx/tests/bug72749.phpt | 34 ++++++++++++++++++++++++++++++++++ ext/wddx/wddx.c | 16 ++++++++++++---- 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 ext/wddx/tests/bug72749.phpt diff --git a/ext/wddx/tests/bug72749.phpt b/ext/wddx/tests/bug72749.phpt new file mode 100644 index 00000000000..ee17d0f2295 --- /dev/null +++ b/ext/wddx/tests/bug72749.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #72749: wddx_deserialize allows illegal memory access +--SKIPIF-- + +--FILE-- + + + +
+ + + + 2\r2004-09-10T05:52:49+00 + + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +array(1) { + ["aDateTime3"]=> + string(24) "2 +2004-09-10T05:52:49+00" +} diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 40b41ba373c..a11efe66dea 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -1038,14 +1038,22 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len) case ST_DATETIME: { char *tmp; - tmp = emalloc(len + 1); - memcpy(tmp, (char *)s, len); + if (Z_TYPE(ent->data) == IS_STRING) { + tmp = safe_emalloc(Z_STRLEN(ent->data), 1, (size_t)len + 1); + memcpy(tmp, Z_STRVAL(ent->data), Z_STRLEN(ent->data)); + memcpy(tmp + Z_STRLEN(ent->data), s, len); + len += Z_STRLEN(ent->data); + zval_dtor(&ent->data); + } else { + tmp = emalloc(len + 1); + memcpy(tmp, (char *)s, len); + } tmp[len] = '\0'; - Z_LVAL(ent->data) = php_parse_date(tmp, NULL); + ZVAL_LONG(&ent->data, php_parse_date(tmp, NULL)); /* date out of range < 1969 or > 2038 */ if (Z_LVAL(ent->data) == -1) { - ZVAL_STRINGL(&ent->data, (char *)s, len); + ZVAL_STRINGL(&ent->data, (char *)tmp, len); } efree(tmp); } From 448c9be157f4147e121f1a2a524536c75c9c6059 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 2 Aug 2016 01:08:42 -0700 Subject: [PATCH 18/49] Fix bug #72663 - destroy broken object when unserializing --- ext/standard/tests/strings/bug72663.phpt | 26 ++++++++ ext/standard/tests/strings/bug72663_2.phpt | 17 ++++++ ext/standard/var_unserializer.c | 70 ++++++++++++---------- ext/standard/var_unserializer.re | 5 +- 4 files changed, 84 insertions(+), 34 deletions(-) create mode 100644 ext/standard/tests/strings/bug72663.phpt create mode 100644 ext/standard/tests/strings/bug72663_2.phpt diff --git a/ext/standard/tests/strings/bug72663.phpt b/ext/standard/tests/strings/bug72663.phpt new file mode 100644 index 00000000000..e61f939d4db --- /dev/null +++ b/ext/standard/tests/strings/bug72663.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--FILE-- +data); + } + function unserialize($data) { + $this->data = unserialize($data); + } +} + +$inner = 'a:1:{i:0;O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:4;}'; +$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}'; + +$data = unserialize($exploit); +echo $data[1]; +?> +DONE +--EXPECTF-- +Notice: unserialize(): Unexpected end of serialized data in %sbug72663.php on line %d + +Notice: unserialize(): Error at offset 46 of 47 bytes in %sbug72663.php on line %d +DONE \ No newline at end of file diff --git a/ext/standard/tests/strings/bug72663_2.phpt b/ext/standard/tests/strings/bug72663_2.phpt new file mode 100644 index 00000000000..ac605e9fd26 --- /dev/null +++ b/ext/standard/tests/strings/bug72663_2.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--FILE-- + +DONE +--EXPECTF-- +Notice: session_decode(): Unexpected end of serialized data in %sbug72663_2.php on line %d +array(0) { +} +DONE \ No newline at end of file diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 1e45b03fcc6..e4ddecff66c 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 */ +/* Generated by re2c 0.13.7.5 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ @@ -408,7 +408,7 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) elements = parse_iv2((*p) + 2, p); (*p) += 2; - + if (ce->serialize == NULL) { object_init_ex(*rval, ce); } else { @@ -434,6 +434,9 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) } if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { + /* We've got partially constructed object on our hands here. Wipe it */ + zend_hash_clean(Z_OBJPROP_PP(rval)); + ZVAL_NULL(*rval); return 0; } @@ -482,7 +485,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 486 "ext/standard/var_unserializer.c" +#line 489 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -542,9 +545,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 851 "ext/standard/var_unserializer.re" +#line 854 "ext/standard/var_unserializer.re" { return 0; } -#line 548 "ext/standard/var_unserializer.c" +#line 551 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -587,13 +590,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 845 "ext/standard/var_unserializer.re" +#line 848 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 597 "ext/standard/var_unserializer.c" +#line 600 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -619,11 +622,12 @@ yy20: if (yybm[0+yych] & 128) { goto yy20; } - if (yych != ':') goto yy18; + if (yych <= '/') goto yy18; + if (yych >= ';') goto yy18; yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 698 "ext/standard/var_unserializer.re" +#line 701 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -770,7 +774,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 774 "ext/standard/var_unserializer.c" +#line 778 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -795,7 +799,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 689 "ext/standard/var_unserializer.re" +#line 692 "ext/standard/var_unserializer.re" { if (!var_hash) return 0; @@ -804,7 +808,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 808 "ext/standard/var_unserializer.c" +#line 812 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -825,7 +829,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 668 "ext/standard/var_unserializer.re" +#line 671 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -846,7 +850,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 850 "ext/standard/var_unserializer.c" +#line 854 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -867,7 +871,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 633 "ext/standard/var_unserializer.re" +#line 636 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -902,7 +906,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 906 "ext/standard/var_unserializer.c" +#line 910 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -923,7 +927,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 600 "ext/standard/var_unserializer.re" +#line 603 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -956,7 +960,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 960 "ext/standard/var_unserializer.c" +#line 964 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1044,7 +1048,7 @@ yy61: } yy63: ++YYCURSOR; -#line 590 "ext/standard/var_unserializer.re" +#line 593 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1054,7 +1058,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1058 "ext/standard/var_unserializer.c" +#line 1062 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1113,7 +1117,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 575 "ext/standard/var_unserializer.re" +#line 578 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1128,7 +1132,7 @@ yy73: return 1; } -#line 1132 "ext/standard/var_unserializer.c" +#line 1136 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1155,7 +1159,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 548 "ext/standard/var_unserializer.re" +#line 551 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1182,7 +1186,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1186 "ext/standard/var_unserializer.c" +#line 1190 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1190,24 +1194,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 541 "ext/standard/var_unserializer.re" +#line 544 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1201 "ext/standard/var_unserializer.c" +#line 1205 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 534 "ext/standard/var_unserializer.re" +#line 537 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1211 "ext/standard/var_unserializer.c" +#line 1215 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1230,7 +1234,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 511 "ext/standard/var_unserializer.re" +#line 514 "ext/standard/var_unserializer.re" { long id; @@ -1253,7 +1257,7 @@ yy91: return 1; } -#line 1257 "ext/standard/var_unserializer.c" +#line 1261 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1276,7 +1280,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 490 "ext/standard/var_unserializer.re" +#line 493 "ext/standard/var_unserializer.re" { long id; @@ -1297,9 +1301,9 @@ yy97: return 1; } -#line 1301 "ext/standard/var_unserializer.c" +#line 1305 "ext/standard/var_unserializer.c" } -#line 853 "ext/standard/var_unserializer.re" +#line 856 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index d1d4ef98e47..c1c18c93911 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -412,7 +412,7 @@ static inline long object_common1(UNSERIALIZE_PARAMETER, zend_class_entry *ce) elements = parse_iv2((*p) + 2, p); (*p) += 2; - + if (ce->serialize == NULL) { object_init_ex(*rval, ce); } else { @@ -438,6 +438,9 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) } if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { + /* We've got partially constructed object on our hands here. Wipe it. */ + zend_hash_clean(Z_OBJPROP_PP(rval)); + ZVAL_NULL(*rval); return 0; } From 8763c6090d627d8bb0ee1d030c30e58f406be9ce Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 3 Aug 2016 00:30:12 -0700 Subject: [PATCH 19/49] Fix bug #72681 - consume data even if we're not storing them --- ext/session/session.c | 25 ++++++++++++++++++------- ext/session/tests/bug72681.phpt | 16 ++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 ext/session/tests/bug72681.phpt diff --git a/ext/session/session.c b/ext/session/session.c index c668bb7b2a2..b2d02361dfd 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -924,11 +924,13 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ int namelen; int has_value; php_unserialize_data_t var_hash; + int skip = 0; PHP_VAR_UNSERIALIZE_INIT(var_hash); for (p = val; p < endptr; ) { zval **tmp; + skip = 0; namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF); if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) { @@ -944,22 +946,25 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) { - efree(name); - continue; + skip = 1; } } if (has_value) { ALLOC_INIT_ZVAL(current); if (php_var_unserialize(¤t, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) { - php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + if (!skip) { + php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + } } else { PHP_VAR_UNSERIALIZE_DESTROY(var_hash); return FAILURE; } var_push_dtor_no_addref(&var_hash, ¤t); } - PS_ADD_VARL(name, namelen); + if (!skip) { + PS_ADD_VARL(name, namelen); + } efree(name); } @@ -1016,6 +1021,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ int namelen; int has_value; php_unserialize_data_t var_hash; + int skip = 0; PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -1024,6 +1030,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ while (p < endptr) { zval **tmp; q = p; + skip = 0; while (*q != PS_DELIMITER) { if (++q >= endptr) goto break_outer_loop; } @@ -1040,14 +1047,16 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ if (zend_hash_find(&EG(symbol_table), name, namelen + 1, (void **) &tmp) == SUCCESS) { if ((Z_TYPE_PP(tmp) == IS_ARRAY && Z_ARRVAL_PP(tmp) == &EG(symbol_table)) || *tmp == PS(http_session_vars)) { - goto skip; + skip = 1; } } if (has_value) { ALLOC_INIT_ZVAL(current); if (php_var_unserialize(¤t, (const unsigned char **) &q, (const unsigned char *) endptr, &var_hash TSRMLS_CC)) { - php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + if (!skip) { + php_set_session_var(name, namelen, current, &var_hash TSRMLS_CC); + } } else { var_push_dtor_no_addref(&var_hash, ¤t); efree(name); @@ -1056,7 +1065,9 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ } var_push_dtor_no_addref(&var_hash, ¤t); } - PS_ADD_VARL(name, namelen); + if (!skip) { + PS_ADD_VARL(name, namelen); + } skip: efree(name); diff --git a/ext/session/tests/bug72681.phpt b/ext/session/tests/bug72681.phpt new file mode 100644 index 00000000000..ca38b07fc90 --- /dev/null +++ b/ext/session/tests/bug72681.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #72681: PHP Session Data Injection Vulnerability +--SKIPIF-- + +--FILE-- + +--EXPECT-- +array(0) { +} From da316b50bdad5850a18b1146f712395093c8f570 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 3 Aug 2016 22:37:57 -0700 Subject: [PATCH 20/49] Fix bug #72708 - php_snmp_parse_oid integer overflow in memory allocation --- ext/snmp/snmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index b88cdcd14c8..d2c1b94bb89 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -1032,7 +1032,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu php_error_docref(NULL TSRMLS_CC, E_WARNING, "Got empty OID array"); return FALSE; } - objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_PP(oid))); + objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(Z_ARRVAL_PP(oid)), 0); if (objid_query->vars == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno)); efree(objid_query->vars); From f1a0b7d690a2e89e27ccf58c19fc64fb446015b9 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Thu, 4 Aug 2016 00:03:31 -0700 Subject: [PATCH 21/49] Update comment --- ext/standard/var_unserializer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index e4ddecff66c..1d459ae0082 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -434,7 +434,7 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) } if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { - /* We've got partially constructed object on our hands here. Wipe it */ + /* We've got partially constructed object on our hands here. Wipe it. */ zend_hash_clean(Z_OBJPROP_PP(rval)); ZVAL_NULL(*rval); return 0; From 426aeb2808955ee3d3f52e0cfb102834cdb836a5 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Thu, 4 Aug 2016 00:17:42 -0700 Subject: [PATCH 22/49] Fix bug #72749: wddx_deserialize allows illegal memory access --- ext/wddx/tests/bug72749.phpt | 34 ++++++++++++++++++++++++++++++++++ ext/wddx/wddx.c | 20 ++++++++++++++------ 2 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 ext/wddx/tests/bug72749.phpt diff --git a/ext/wddx/tests/bug72749.phpt b/ext/wddx/tests/bug72749.phpt new file mode 100644 index 00000000000..ee17d0f2295 --- /dev/null +++ b/ext/wddx/tests/bug72749.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #72749: wddx_deserialize allows illegal memory access +--SKIPIF-- + +--FILE-- + + + +
+ + + + 2\r2004-09-10T05:52:49+00 + + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +array(1) { + ["aDateTime3"]=> + string(24) "2 +2004-09-10T05:52:49+00" +} diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index cde3e074064..faadbfe1dfe 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -1123,18 +1123,26 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len) case ST_DATETIME: { char *tmp; - tmp = emalloc(len + 1); - memcpy(tmp, s, len); + if (Z_TYPE_P(ent->data) == IS_STRING) { + tmp = safe_emalloc(Z_STRLEN_P(ent->data), 1, (size_t)len + 1); + memcpy(tmp, Z_STRVAL_P(ent->data), Z_STRLEN_P(ent->data)); + memcpy(tmp + Z_STRLEN_P(ent->data), s, len); + len += Z_STRLEN_P(ent->data); + efree(Z_STRVAL_P(ent->data)); + Z_TYPE_P(ent->data) = IS_LONG; + } else { + tmp = emalloc(len + 1); + memcpy(tmp, s, len); + } tmp[len] = '\0'; Z_LVAL_P(ent->data) = php_parse_date(tmp, NULL); /* date out of range < 1969 or > 2038 */ if (Z_LVAL_P(ent->data) == -1) { - Z_TYPE_P(ent->data) = IS_STRING; - Z_STRLEN_P(ent->data) = len; - Z_STRVAL_P(ent->data) = estrndup(s, len); + ZVAL_STRINGL(ent->data, tmp, len, 0); + } else { + efree(tmp); } - efree(tmp); } break; From 95d09e4b5e6b84f8340efe03e8e2f9c1380228db Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 7 Aug 2016 15:16:28 -0700 Subject: [PATCH 23/49] Fix bug #70436: Use After Free Vulnerability in unserialize() --- ext/standard/tests/strings/bug70436.phpt | 65 ++++++++++++++++++++++++ ext/standard/var.c | 1 + 2 files changed, 66 insertions(+) create mode 100644 ext/standard/tests/strings/bug70436.phpt diff --git a/ext/standard/tests/strings/bug70436.phpt b/ext/standard/tests/strings/bug70436.phpt new file mode 100644 index 00000000000..c62e4687263 --- /dev/null +++ b/ext/standard/tests/strings/bug70436.phpt @@ -0,0 +1,65 @@ +--TEST-- +Bug #70436: Use After Free Vulnerability in unserialize() +--FILE-- +data); + } + + function unserialize($data) + { + $this->data = unserialize($data); + } +} + +$fakezval = ptr2str(1122334455); +$fakezval .= ptr2str(0); +$fakezval .= "\x00\x00\x00\x00"; +$fakezval .= "\x01"; +$fakezval .= "\x00"; +$fakezval .= "\x00\x00"; + +$inner = 'C:3:"obj":3:{ryat'; +$exploit = 'a:4:{i:0;i:1;i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:2;s:'.strlen($fakezval).':"'.$fakezval.'";i:3;R:5;}'; + +$data = unserialize($exploit); + +var_dump($data); + +function ptr2str($ptr) +{ + $out = ''; + + for ($i = 0; $i < 8; $i++) { + $out .= chr($ptr & 0xff); + $ptr >>= 8; + } + + return $out; +} +?> +DONE +--EXPECTF-- +Notice: unserialize(): Error at offset 0 of 3 bytes in %sbug70436.php on line %d + +Notice: unserialize(): Error at offset 17 of 17 bytes in %sbug70436.php on line %d +array(4) { + [0]=> + int(1) + [1]=> + object(obj)#%d (1) { + ["data"]=> + bool(false) + } + [2]=> + string(24) "%s" + [3]=> + bool(false) +} +DONE \ No newline at end of file diff --git a/ext/standard/var.c b/ext/standard/var.c index f0efef2f93c..137e794fb19 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -962,6 +962,7 @@ PHP_FUNCTION(unserialize) p = (const unsigned char*) buf; PHP_VAR_UNSERIALIZE_INIT(var_hash); if (!php_var_unserialize(&return_value, &p, p + buf_len, &var_hash TSRMLS_CC)) { + var_push_dtor(&var_hash, &return_value); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); zval_dtor(return_value); if (!EG(exception)) { From 639f7fde6a51c23d7c670358fbcb777ac1a143f3 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 7 Aug 2016 15:33:29 -0700 Subject: [PATCH 24/49] Improve fix for #72663 --- ext/standard/tests/strings/bug72663_3.phpt | 18 ++++++ ext/standard/var_unserializer.c | 68 ++++++++++++---------- ext/standard/var_unserializer.re | 8 ++- 3 files changed, 62 insertions(+), 32 deletions(-) create mode 100644 ext/standard/tests/strings/bug72663_3.phpt diff --git a/ext/standard/tests/strings/bug72663_3.phpt b/ext/standard/tests/strings/bug72663_3.phpt new file mode 100644 index 00000000000..e336bc868db --- /dev/null +++ b/ext/standard/tests/strings/bug72663_3.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--FILE-- +ryat = str_repeat('A', 0x112); + } +} + +$poc = 'O:8:"stdClass":1:{i:0;O:3:"obj":1:{s:4:"ryat";R:1;'; +unserialize($poc); +?> +DONE +--EXPECTF-- +Notice: unserialize(): Error at offset 51 of 50 bytes in %sbug72663_3.php on line %d +DONE \ No newline at end of file diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 1d459ae0082..c8e6f8a0ca9 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -435,11 +435,17 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { /* We've got partially constructed object on our hands here. Wipe it. */ - zend_hash_clean(Z_OBJPROP_PP(rval)); + if(Z_TYPE_PP(rval) == IS_OBJECT) { + zend_hash_clean(Z_OBJPROP_PP(rval)); + } ZVAL_NULL(*rval); return 0; } + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { INIT_PZVAL(&fname); @@ -485,7 +491,7 @@ PHPAPI int php_var_unserialize(UNSERIALIZE_PARAMETER) -#line 489 "ext/standard/var_unserializer.c" +#line 495 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { @@ -545,9 +551,9 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 854 "ext/standard/var_unserializer.re" +#line 860 "ext/standard/var_unserializer.re" { return 0; } -#line 551 "ext/standard/var_unserializer.c" +#line 557 "ext/standard/var_unserializer.c" yy4: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy89; @@ -590,13 +596,13 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 848 "ext/standard/var_unserializer.re" +#line 854 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unexpected end of serialized data"); return 0; /* not sure if it should be 0 or 1 here? */ } -#line 600 "ext/standard/var_unserializer.c" +#line 606 "ext/standard/var_unserializer.c" yy16: yych = *++YYCURSOR; goto yy3; @@ -627,7 +633,7 @@ yy20: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 701 "ext/standard/var_unserializer.re" +#line 707 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; long elements; @@ -774,7 +780,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 778 "ext/standard/var_unserializer.c" +#line 784 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -799,7 +805,7 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 692 "ext/standard/var_unserializer.re" +#line 698 "ext/standard/var_unserializer.re" { if (!var_hash) return 0; @@ -808,7 +814,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 812 "ext/standard/var_unserializer.c" +#line 818 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -829,7 +835,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 671 "ext/standard/var_unserializer.re" +#line 677 "ext/standard/var_unserializer.re" { long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -850,7 +856,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 854 "ext/standard/var_unserializer.c" +#line 860 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -871,7 +877,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 636 "ext/standard/var_unserializer.re" +#line 642 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -906,7 +912,7 @@ yy41: ZVAL_STRINGL(*rval, str, len, 0); return 1; } -#line 910 "ext/standard/var_unserializer.c" +#line 916 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -927,7 +933,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 603 "ext/standard/var_unserializer.re" +#line 609 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -960,7 +966,7 @@ yy48: ZVAL_STRINGL(*rval, str, len, 1); return 1; } -#line 964 "ext/standard/var_unserializer.c" +#line 970 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1048,7 +1054,7 @@ yy61: } yy63: ++YYCURSOR; -#line 593 "ext/standard/var_unserializer.re" +#line 599 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 use_double: @@ -1058,7 +1064,7 @@ use_double: ZVAL_DOUBLE(*rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1062 "ext/standard/var_unserializer.c" +#line 1068 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1117,7 +1123,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 578 "ext/standard/var_unserializer.re" +#line 584 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); @@ -1132,7 +1138,7 @@ yy73: return 1; } -#line 1136 "ext/standard/var_unserializer.c" +#line 1142 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1159,7 +1165,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 551 "ext/standard/var_unserializer.re" +#line 557 "ext/standard/var_unserializer.re" { #if SIZEOF_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1186,7 +1192,7 @@ yy79: ZVAL_LONG(*rval, parse_iv(start + 2)); return 1; } -#line 1190 "ext/standard/var_unserializer.c" +#line 1196 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1194,24 +1200,24 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 544 "ext/standard/var_unserializer.re" +#line 550 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_BOOL(*rval, parse_iv(start + 2)); return 1; } -#line 1205 "ext/standard/var_unserializer.c" +#line 1211 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 537 "ext/standard/var_unserializer.re" +#line 543 "ext/standard/var_unserializer.re" { *p = YYCURSOR; INIT_PZVAL(*rval); ZVAL_NULL(*rval); return 1; } -#line 1215 "ext/standard/var_unserializer.c" +#line 1221 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1234,7 +1240,7 @@ yy91: if (yych <= '9') goto yy91; if (yych != ';') goto yy18; ++YYCURSOR; -#line 514 "ext/standard/var_unserializer.re" +#line 520 "ext/standard/var_unserializer.re" { long id; @@ -1257,7 +1263,7 @@ yy91: return 1; } -#line 1261 "ext/standard/var_unserializer.c" +#line 1267 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1280,7 +1286,7 @@ yy97: if (yych <= '9') goto yy97; if (yych != ';') goto yy18; ++YYCURSOR; -#line 493 "ext/standard/var_unserializer.re" +#line 499 "ext/standard/var_unserializer.re" { long id; @@ -1301,9 +1307,9 @@ yy97: return 1; } -#line 1305 "ext/standard/var_unserializer.c" +#line 1311 "ext/standard/var_unserializer.c" } -#line 856 "ext/standard/var_unserializer.re" +#line 862 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index c1c18c93911..11b93c522b2 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -439,11 +439,17 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, long elements) if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_OBJPROP_PP(rval), elements, 1)) { /* We've got partially constructed object on our hands here. Wipe it. */ - zend_hash_clean(Z_OBJPROP_PP(rval)); + if(Z_TYPE_PP(rval) == IS_OBJECT) { + zend_hash_clean(Z_OBJPROP_PP(rval)); + } ZVAL_NULL(*rval); return 0; } + if (Z_TYPE_PP(rval) != IS_OBJECT) { + return 0; + } + if (Z_OBJCE_PP(rval) != PHP_IC_ENTRY && zend_hash_exists(&Z_OBJCE_PP(rval)->function_table, "__wakeup", sizeof("__wakeup"))) { INIT_PZVAL(&fname); From e018ff094f8505ea77f881ba11176e3ad0b4863e Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 7 Aug 2016 16:17:54 -0700 Subject: [PATCH 25/49] Fix bug #72771: ftps:// opendir wrapper is vulnerable to protocol downgrade attack --- ext/standard/ftp_fopen_wrapper.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index bfb163167af..5bffa47855c 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -188,7 +188,8 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char /* get the response */ result = GET_FTP_RESULT(stream); if (result != 334) { - use_ssl = 0; + php_stream_wrapper_log_error(wrapper, options TSRMLS_CC, "Server doesn't support FTPS."); + goto connect_errexit; } else { /* we must reuse the old SSL session id */ /* if we talk to an old ftpd-ssl */ From 698a691724c0a949295991e5df091ce16f899e02 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 7 Aug 2016 16:26:52 -0700 Subject: [PATCH 26/49] Fix bug #72750: wddx_deserialize null dereference --- ext/wddx/tests/bug72750.phpt | 34 ++++++++++++++++++++++++++++++++++ ext/wddx/wddx.c | 8 ++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 ext/wddx/tests/bug72750.phpt diff --git a/ext/wddx/tests/bug72750.phpt b/ext/wddx/tests/bug72750.phpt new file mode 100644 index 00000000000..3a6794df280 --- /dev/null +++ b/ext/wddx/tests/bug72750.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #72750: wddx_deserialize null dereference +--SKIPIF-- + +--FILE-- + + + +
+ + + + \\tYmluYXJRhdGE= + + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +array(1) { + ["aBinary"]=> + string(0) "" +} diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index faadbfe1dfe..1b2d103af18 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -959,8 +959,12 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) new_str = php_base64_decode(Z_STRVAL_P(ent1->data), Z_STRLEN_P(ent1->data), &new_len); STR_FREE(Z_STRVAL_P(ent1->data)); - Z_STRVAL_P(ent1->data) = new_str; - Z_STRLEN_P(ent1->data) = new_len; + if (new_str) { + Z_STRVAL_P(ent1->data) = new_str; + Z_STRLEN_P(ent1->data) = new_len; + } else { + ZVAL_EMPTY_STRING(ent1->data); + } } /* Call __wakeup() method on the object. */ From 6dbb1ee46b5f4725cc6519abf91e512a2a10dfed Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 8 Aug 2016 00:49:34 -0700 Subject: [PATCH 27/49] Fixed bug #72627: Memory Leakage In exif_process_IFD_in_TIFF --- ext/exif/exif.c | 5 ++- ext/exif/tests/bug72627.phpt | 71 +++++++++++++++++++++++++++++++++++ ext/exif/tests/bug72627.tiff | Bin 0 -> 1250 bytes 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 ext/exif/tests/bug72627.phpt create mode 100644 ext/exif/tests/bug72627.tiff diff --git a/ext/exif/exif.c b/ext/exif/exif.c index f95de3a14f1..657a2cc1f26 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -3768,8 +3768,11 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size); if (fgot < ImageInfo->Thumbnail.size) { EXIF_ERRLOG_THUMBEOF(ImageInfo) + efree(ImageInfo->Thumbnail.data); + ImageInfo->Thumbnail.data = NULL; + } else { + exif_thumbnail_build(ImageInfo TSRMLS_CC); } - exif_thumbnail_build(ImageInfo TSRMLS_CC); } #ifdef EXIF_DEBUG exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read next IFD (THUMBNAIL) done"); diff --git a/ext/exif/tests/bug72627.phpt b/ext/exif/tests/bug72627.phpt new file mode 100644 index 00000000000..bb6a1fae99a --- /dev/null +++ b/ext/exif/tests/bug72627.phpt @@ -0,0 +1,71 @@ +--TEST-- +Bug #72627 (Memory Leakage In exif_process_IFD_in_TIFF) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d + +Warning: exif_read_data(%s): Error in TIFF: filesize(x04E2) less than start of IFD dir(x829A0004) in %sbug72627.php on line %d + +Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d +array(11) { + ["FileName"]=> + string(13) "bug72627.tiff" + ["FileDateTime"]=> + int(%d) + ["FileSize"]=> + int(1250) + ["FileType"]=> + int(7) + ["MimeType"]=> + string(10) "image/tiff" + ["SectionsFound"]=> + string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF" + ["COMPUTED"]=> + array(10) { + ["html"]=> + string(24) "width="128" height="132"" + ["Height"]=> + int(132) + ["Width"]=> + int(128) + ["IsColor"]=> + int(0) + ["ByteOrderMotorola"]=> + int(0) + ["ApertureFNumber"]=> + string(5) "f/1.0" + ["Thumbnail.FileType"]=> + int(2) + ["Thumbnail.MimeType"]=> + string(10) "image/jpeg" + ["Thumbnail.Height"]=> + int(132) + ["Thumbnail.Width"]=> + int(128) + } + ["XResolution"]=> + string(21) "1414812756/1414812756" + ["THUMBNAIL"]=> + array(5) { + ["ImageWidth"]=> + int(128) + ["ImageLength"]=> + int(132) + ["JPEGInterchangeFormat"]=> + int(1280) + ["JPEGInterchangeFormatLength"]=> + int(100) + ["THUMBNAIL"]=> + NULL + } + ["ExposureTime"]=> + string(21) "1414812756/1414812756" + ["FNumber"]=> + string(21) "1414812756/1414812756" +} diff --git a/ext/exif/tests/bug72627.tiff b/ext/exif/tests/bug72627.tiff new file mode 100644 index 0000000000000000000000000000000000000000..229190a6041926d960856267a5285d887eda49b5 GIT binary patch literal 1250 zcmebD)MDUZU|?WkkYZ$IU<9%lSQr>G+gZSDC9uq_CWwp>P-ZTa?E+*wKom1FgViXgZXg0u%><|2O{MVo39)0|*%fqaiRF0wXpA{@(-uY6E(R literal 0 HcmV?d00001 From a3598dd7c9b182debcb54b9322b1dece14c9b533 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 00:00:14 -0700 Subject: [PATCH 28/49] Fix bug#72697 - select_colors write out-of-bounds --- ext/gd/gd.c | 16 ++++++++-------- ext/gd/tests/bug72697.phpt | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 ext/gd/tests/bug72697.phpt diff --git a/ext/gd/gd.c b/ext/gd/gd.c index b96f901ea0e..5c604b7a80a 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -99,7 +99,7 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int, int); #include "gd_ctx.c" -/* as it is not really public, duplicate declaration here to avoid +/* as it is not really public, duplicate declaration here to avoid pointless warnings */ int overflow2(int a, int b); @@ -1197,7 +1197,7 @@ PHP_MINIT_FUNCTION(gd) REGISTER_LONG_CONSTANT("IMG_CROP_SIDES", GD_CROP_SIDES, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_CROP_THRESHOLD", GD_CROP_THRESHOLD, CONST_CS | CONST_PERSISTENT); - + REGISTER_LONG_CONSTANT("IMG_BELL", GD_BELL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_BESSEL", GD_BESSEL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("IMG_BILINEAR_FIXED", GD_BILINEAR_FIXED, CONST_CS | CONST_PERSISTENT); @@ -1658,11 +1658,11 @@ PHP_FUNCTION(imagetruecolortopalette) ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd); - if (ncolors <= 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of colors has to be greater than zero"); + if (ncolors <= 0 || ncolors > INT_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of colors has to be greater than zero and no more than %d", INT_MAX); RETURN_FALSE; } - gdImageTrueColorToPalette(im, dither, ncolors); + gdImageTrueColorToPalette(im, dither, (int)ncolors); RETURN_TRUE; } @@ -3913,7 +3913,7 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int #endif /* VIRTUAL_DIR */ PHP_GD_CHECK_OPEN_BASEDIR(fontname, "Invalid font filename"); - + #ifdef HAVE_GD_FREETYPE if (extended) { error = gdImageStringFTEx(im, brect, col, fontname, ptsize, angle, x, y, str, &strex); @@ -4491,7 +4491,7 @@ static void _php_image_convert(INTERNAL_FUNCTION_PARAMETERS, int image_type ) int x, y; float x_ratio, y_ratio; long ignore_warning; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "pplll", &f_org, &f_org_len, &f_dest, &f_dest_len, &height, &width, &threshold) == FAILURE) { return; } @@ -5374,7 +5374,7 @@ PHP_FUNCTION(imageaffinematrixget) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing y position"); RETURN_FALSE; } - + if (type == GD_AFFINE_TRANSLATE) { res = gdAffineTranslate(affine, x, y); } else { diff --git a/ext/gd/tests/bug72697.phpt b/ext/gd/tests/bug72697.phpt new file mode 100644 index 00000000000..6110385fcb8 --- /dev/null +++ b/ext/gd/tests/bug72697.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #72697: select_colors write out-of-bounds +--SKIPIF-- + +--FILE-- + +DONE +--EXPECTF-- +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than 2147483647 in %sbug72697.php on line %d +DONE \ No newline at end of file From 1bd103df00f49cf4d4ade2cfe3f456ac058a4eae Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 00:14:58 -0700 Subject: [PATCH 29/49] Fix bug #72730 - imagegammacorrect allows arbitrary write access --- ext/gd/gd.c | 5 +++++ ext/gd/tests/bug72730.phpt | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 ext/gd/tests/bug72730.phpt diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 5c604b7a80a..0fb96041087 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -3082,6 +3082,11 @@ PHP_FUNCTION(imagegammacorrect) return; } + if ( input <= 0.0 || output <= 0.0 ) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Gamma values should be positive"); + RETURN_FALSE; + } + ZEND_FETCH_RESOURCE(im, gdImagePtr, &IM, -1, "Image", le_gd); if (gdImageTrueColor(im)) { diff --git a/ext/gd/tests/bug72730.phpt b/ext/gd/tests/bug72730.phpt new file mode 100644 index 00000000000..e7c13cb5e9d --- /dev/null +++ b/ext/gd/tests/bug72730.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #72730: imagegammacorrect allows arbitrary write access +--SKIPIF-- + +--FILE-- + +DONE +--EXPECTF-- +Warning: imagegammacorrect(): Gamma values should be positive in %sbug72730.php on line %d +DONE \ No newline at end of file From 5a34bd6d1e6b4d31221c50bcf477c9508553a646 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 10 Aug 2016 23:43:56 -0700 Subject: [PATCH 30/49] Fix for bug #72790 and bug #72799 --- ext/wddx/tests/bug72790.phpt | 35 +++++++++++++++++++++++++++++++++++ ext/wddx/tests/bug72799.phpt | 28 ++++++++++++++++++++++++++++ ext/wddx/wddx.c | 14 +++++++++----- 3 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 ext/wddx/tests/bug72790.phpt create mode 100644 ext/wddx/tests/bug72799.phpt diff --git a/ext/wddx/tests/bug72790.phpt b/ext/wddx/tests/bug72790.phpt new file mode 100644 index 00000000000..a60524bdaf1 --- /dev/null +++ b/ext/wddx/tests/bug72790.phpt @@ -0,0 +1,35 @@ +--TEST-- +Bug 72790: wddx_deserialize null dereference with invalid xml +--SKIPIF-- + +--FILE-- + + + + |array> + + + + + + + + + + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +NULL \ No newline at end of file diff --git a/ext/wddx/tests/bug72799.phpt b/ext/wddx/tests/bug72799.phpt new file mode 100644 index 00000000000..5861d5538f4 --- /dev/null +++ b/ext/wddx/tests/bug72799.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #72799: wddx_deserialize null dereference in php_wddx_pop_element +--SKIPIF-- + +--FILE-- + + + + + + 1998-06-12T04:32:12+00 + + + +XML; + +$array = wddx_deserialize($xml); +var_dump($array); +?> +--EXPECT-- +NULL \ No newline at end of file diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 1b2d103af18..d7bd295832c 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -946,10 +946,10 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) if (!ent1->data) { if (stack->top > 1) { stack->top--; + efree(ent1); } else { stack->done = 1; } - efree(ent1); return; } @@ -988,7 +988,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) wddx_stack_top(stack, (void**)&ent2); /* if non-existent field */ - if (ent2->type == ST_FIELD && ent2->data == NULL) { + if (ent2->data == NULL) { zval_ptr_dtor(&ent1->data); efree(ent1); return; @@ -1179,9 +1179,13 @@ int php_wddx_deserialize_ex(char *value, int vallen, zval *return_value) if (stack.top == 1) { wddx_stack_top(&stack, (void**)&ent); - *return_value = *(ent->data); - zval_copy_ctor(return_value); - retval = SUCCESS; + if(ent->data == NULL) { + retval = FAILURE; + } else { + *return_value = *(ent->data); + zval_copy_ctor(return_value); + retval = SUCCESS; + } } else { retval = FAILURE; } From 1cd6bc64637353536032c53e0b6770233f8d03ca Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Thu, 11 Aug 2016 23:36:25 -0700 Subject: [PATCH 31/49] Fix for bug #72807 - do not produce strings with negative length --- Zend/zend_API.h | 7 +++++-- ext/curl/interface.c | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index a56075e177b..e17be4ce681 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -447,7 +447,7 @@ ZEND_API int add_property_zval_ex(zval *arg, const char *key, uint key_len, zval #define add_property_double(__arg, __key, __d) add_property_double_ex(__arg, __key, strlen(__key)+1, __d TSRMLS_CC) #define add_property_string(__arg, __key, __str, __duplicate) add_property_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate TSRMLS_CC) #define add_property_stringl(__arg, __key, __str, __length, __duplicate) add_property_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate TSRMLS_CC) -#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value TSRMLS_CC) +#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value TSRMLS_CC) ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, zend_uint param_count, zval *params[] TSRMLS_DC); @@ -458,7 +458,7 @@ ZEND_API extern const zend_fcall_info_cache empty_fcall_info_cache; /** Build zend_call_info/cache from a zval* * - * Caller is responsible to provide a return value, otherwise the we will crash. + * Caller is responsible to provide a return value, otherwise the we will crash. * fci->retval_ptr_ptr = NULL; * In order to pass parameters the following members need to be set: * fci->param_count = 0; @@ -578,6 +578,9 @@ END_EXTERN_C() const char *__s=(s); \ zval *__z = (z); \ Z_STRLEN_P(__z) = strlen(__s); \ + if (UNEXPECTED(Z_STRLEN_P(__z) < 0)) { \ + zend_error(E_ERROR, "String size overflow"); \ + } \ Z_STRVAL_P(__z) = (duplicate?estrndup(__s, Z_STRLEN_P(__z)):(char*)__s);\ Z_TYPE_P(__z) = IS_STRING; \ } while (0) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index c7112a091a0..062f9969aed 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -3478,6 +3478,10 @@ PHP_FUNCTION(curl_escape) ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl); if ((res = curl_easy_escape(ch->cp, str, str_len))) { + if (strlen(res) > INT_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Escaped string is too long, maximum is %d", INT_MAX); + RETURN_FALSE; + } RETVAL_STRING(res, 1); curl_free(res); } else { From d6a43a8562ec58043fa5e26f2a58b0c239feee40 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Sun, 14 Aug 2016 23:13:30 -0700 Subject: [PATCH 32/49] Fix bug #72836 - integer overflow in base64_decode caused heap corruption --- ext/standard/base64.c | 5 + sapi/cli/generate_mime_type_map.php | 76 +++++ sapi/fpm/www.conf.in | 413 ++++++++++++++++++++++++++++ 3 files changed, 494 insertions(+) create mode 100644 sapi/cli/generate_mime_type_map.php create mode 100644 sapi/fpm/www.conf.in diff --git a/ext/standard/base64.c b/ext/standard/base64.c index a40b86634d3..8340ed12607 100644 --- a/ext/standard/base64.c +++ b/ext/standard/base64.c @@ -66,6 +66,11 @@ PHPAPI unsigned char *php_base64_encode(const unsigned char *str, int length, in return NULL; } + if (((size_t)length + 2) / 3 > INT_MAX/4 ) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, maximum is %d", INT_MAX/4); + return NULL; + } + result = (unsigned char *) safe_emalloc((length + 2) / 3, 4 * sizeof(char), 1); p = result; diff --git a/sapi/cli/generate_mime_type_map.php b/sapi/cli/generate_mime_type_map.php new file mode 100644 index 00000000000..9e088814a04 --- /dev/null +++ b/sapi/cli/generate_mime_type_map.php @@ -0,0 +1,76 @@ +#!/usr/bin/env php + 1 ? $_SERVER['argv'][1] : 'https://raw.githubusercontent.com/apache/httpd/trunk/docs/conf/mime.types'; + +// See if we can actually load it. +$types = @file($source); +if ($types === false) { + fprintf(STDERR, "Error: unable to read $source\n"); + exit(1); +} + +// Remove comments and flip into an extensions array. +$extensions = []; +array_walk($types, function ($line) use (&$extensions) { + $line = trim($line); + if ($line && $line[0] != '#') { + $fields = preg_split('/\s+/', $line); + if (count($fields) > 1) { + $mime = array_shift($fields); + foreach ($fields as $extension) { + $extensions[$extension] = $mime; + } + } + } +}); + +?> +/* + +----------------------------------------------------------------------+ + | PHP Version 7 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997-2015 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Moriyoshi Koizumi | + +----------------------------------------------------------------------+ +*/ + +/* This is a generated file. Rather than modifying it, please run + * "php generate_mime_type_map.php > mime_type_map.h" to regenerate the file. */ + +#ifndef PHP_CLI_SERVER_MIME_TYPE_MAP_H +#define PHP_CLI_SERVER_MIME_TYPE_MAP_H + +typedef struct php_cli_server_ext_mime_type_pair { + const char *ext; + const char *mime_type; +} php_cli_server_ext_mime_type_pair; + +static php_cli_server_ext_mime_type_pair mime_type_map[] = { + $mime): ?> + { "", "" }, + + { NULL, NULL } +}; + +#endif /* PHP_CLI_SERVER_MIME_TYPE_MAP_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + * vim600: noet sw=4 ts=4 fdm=marker + * vim<600: noet sw=4 ts=4 + */ diff --git a/sapi/fpm/www.conf.in b/sapi/fpm/www.conf.in new file mode 100644 index 00000000000..394e27819d9 --- /dev/null +++ b/sapi/fpm/www.conf.in @@ -0,0 +1,413 @@ +; Start a new pool named 'www'. +; the variable $pool can we used in any directive and will be replaced by the +; pool name ('www' here) +[www] + +; Per pool prefix +; It only applies on the following directives: +; - 'access.log' +; - 'slowlog' +; - 'listen' (unixsocket) +; - 'chroot' +; - 'chdir' +; - 'php_values' +; - 'php_admin_values' +; When not set, the global prefix (or @php_fpm_prefix@) applies instead. +; Note: This directive can also be relative to the global prefix. +; Default Value: none +;prefix = /path/to/pools/$pool + +; Unix user/group of processes +; Note: The user is mandatory. If the group is not set, the default user's group +; will be used. +user = @php_fpm_user@ +group = @php_fpm_group@ + +; The address on which to accept FastCGI requests. +; Valid syntaxes are: +; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on +; a specific port; +; '[ip:6:addr:ess]:port' - to listen on a TCP socket to a specific IPv6 address on +; a specific port; +; 'port' - to listen on a TCP socket to all addresses +; (IPv6 and IPv4-mapped) on a specific port; +; '/path/to/unix/socket' - to listen on a unix socket. +; Note: This value is mandatory. +listen = 127.0.0.1:9000 + +; Set listen(2) backlog. +; Default Value: 511 (-1 on FreeBSD and OpenBSD) +;listen.backlog = 511 + +; Set permissions for unix socket, if one is used. In Linux, read/write +; permissions must be set in order to allow connections from a web server. Many +; BSD-derived systems allow connections regardless of permissions. +; Default Values: user and group are set as the running user +; mode is set to 0660 +;listen.owner = @php_fpm_user@ +;listen.group = @php_fpm_group@ +;listen.mode = 0660 +; When POSIX Access Control Lists are supported you can set them using +; these options, value is a comma separated list of user/group names. +; When set, listen.owner and listen.group are ignored +;listen.acl_users = +;listen.acl_groups = + +; List of addresses (IPv4/IPv6) of FastCGI clients which are allowed to connect. +; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original +; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address +; must be separated by a comma. If this value is left blank, connections will be +; accepted from any ip address. +; Default Value: any +;listen.allowed_clients = 127.0.0.1 + +; Specify the nice(2) priority to apply to the pool processes (only if set) +; The value can vary from -19 (highest priority) to 20 (lower priority) +; Note: - It will only work if the FPM master process is launched as root +; - The pool processes will inherit the master process priority +; unless it specified otherwise +; Default Value: no set +; process.priority = -19 + +; Choose how the process manager will control the number of child processes. +; Possible Values: +; static - a fixed number (pm.max_children) of child processes; +; dynamic - the number of child processes are set dynamically based on the +; following directives. With this process management, there will be +; always at least 1 children. +; pm.max_children - the maximum number of children that can +; be alive at the same time. +; pm.start_servers - the number of children created on startup. +; pm.min_spare_servers - the minimum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is less than this +; number then some children will be created. +; pm.max_spare_servers - the maximum number of children in 'idle' +; state (waiting to process). If the number +; of 'idle' processes is greater than this +; number then some children will be killed. +; ondemand - no children are created at startup. Children will be forked when +; new requests will connect. The following parameter are used: +; pm.max_children - the maximum number of children that +; can be alive at the same time. +; pm.process_idle_timeout - The number of seconds after which +; an idle process will be killed. +; Note: This value is mandatory. +pm = dynamic + +; The number of child processes to be created when pm is set to 'static' and the +; maximum number of child processes when pm is set to 'dynamic' or 'ondemand'. +; This value sets the limit on the number of simultaneous requests that will be +; served. Equivalent to the ApacheMaxClients directive with mpm_prefork. +; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP +; CGI. The below defaults are based on a server without much resources. Don't +; forget to tweak pm.* to fit your needs. +; Note: Used when pm is set to 'static', 'dynamic' or 'ondemand' +; Note: This value is mandatory. +pm.max_children = 5 + +; The number of child processes created on startup. +; Note: Used only when pm is set to 'dynamic' +; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2 +pm.start_servers = 2 + +; The desired minimum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.min_spare_servers = 1 + +; The desired maximum number of idle server processes. +; Note: Used only when pm is set to 'dynamic' +; Note: Mandatory when pm is set to 'dynamic' +pm.max_spare_servers = 3 + +; The number of seconds after which an idle process will be killed. +; Note: Used only when pm is set to 'ondemand' +; Default Value: 10s +;pm.process_idle_timeout = 10s; + +; The number of requests each child process should execute before respawning. +; This can be useful to work around memory leaks in 3rd party libraries. For +; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS. +; Default Value: 0 +;pm.max_requests = 500 + +; The URI to view the FPM status page. If this value is not set, no URI will be +; recognized as a status page. It shows the following informations: +; pool - the name of the pool; +; process manager - static, dynamic or ondemand; +; start time - the date and time FPM has started; +; start since - number of seconds since FPM has started; +; accepted conn - the number of request accepted by the pool; +; listen queue - the number of request in the queue of pending +; connections (see backlog in listen(2)); +; max listen queue - the maximum number of requests in the queue +; of pending connections since FPM has started; +; listen queue len - the size of the socket queue of pending connections; +; idle processes - the number of idle processes; +; active processes - the number of active processes; +; total processes - the number of idle + active processes; +; max active processes - the maximum number of active processes since FPM +; has started; +; max children reached - number of times, the process limit has been reached, +; when pm tries to start more children (works only for +; pm 'dynamic' and 'ondemand'); +; Value are updated in real time. +; Example output: +; pool: www +; process manager: static +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 62636 +; accepted conn: 190460 +; listen queue: 0 +; max listen queue: 1 +; listen queue len: 42 +; idle processes: 4 +; active processes: 11 +; total processes: 15 +; max active processes: 12 +; max children reached: 0 +; +; By default the status page output is formatted as text/plain. Passing either +; 'html', 'xml' or 'json' in the query string will return the corresponding +; output syntax. Example: +; http://www.foo.bar/status +; http://www.foo.bar/status?json +; http://www.foo.bar/status?html +; http://www.foo.bar/status?xml +; +; By default the status page only outputs short status. Passing 'full' in the +; query string will also return status for each pool process. +; Example: +; http://www.foo.bar/status?full +; http://www.foo.bar/status?json&full +; http://www.foo.bar/status?html&full +; http://www.foo.bar/status?xml&full +; The Full status returns for each process: +; pid - the PID of the process; +; state - the state of the process (Idle, Running, ...); +; start time - the date and time the process has started; +; start since - the number of seconds since the process has started; +; requests - the number of requests the process has served; +; request duration - the duration in µs of the requests; +; request method - the request method (GET, POST, ...); +; request URI - the request URI with the query string; +; content length - the content length of the request (only with POST); +; user - the user (PHP_AUTH_USER) (or '-' if not set); +; script - the main script called (or '-' if not set); +; last request cpu - the %cpu the last request consumed +; it's always 0 if the process is not in Idle state +; because CPU calculation is done when the request +; processing has terminated; +; last request memory - the max amount of memory the last request consumed +; it's always 0 if the process is not in Idle state +; because memory calculation is done when the request +; processing has terminated; +; If the process is in Idle state, then informations are related to the +; last request the process has served. Otherwise informations are related to +; the current request being served. +; Example output: +; ************************ +; pid: 31330 +; state: Running +; start time: 01/Jul/2011:17:53:49 +0200 +; start since: 63087 +; requests: 12808 +; request duration: 1250261 +; request method: GET +; request URI: /test_mem.php?N=10000 +; content length: 0 +; user: - +; script: /home/fat/web/docs/php/test_mem.php +; last request cpu: 0.00 +; last request memory: 0 +; +; Note: There is a real-time FPM status monitoring sample web page available +; It's available in: @EXPANDED_DATADIR@/fpm/status.html +; +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;pm.status_path = /status + +; The ping URI to call the monitoring page of FPM. If this value is not set, no +; URI will be recognized as a ping page. This could be used to test from outside +; that FPM is alive and responding, or to +; - create a graph of FPM availability (rrd or such); +; - remove a server from a group if it is not responding (load balancing); +; - trigger alerts for the operating team (24/7). +; Note: The value must start with a leading slash (/). The value can be +; anything, but it may not be a good idea to use the .php extension or it +; may conflict with a real PHP file. +; Default Value: not set +;ping.path = /ping + +; This directive may be used to customize the response of a ping request. The +; response is formatted as text/plain with a 200 response code. +; Default Value: pong +;ping.response = pong + +; The access log file +; Default: not set +;access.log = log/$pool.access.log + +; The access log format. +; The following syntax is allowed +; %%: the '%' character +; %C: %CPU used by the request +; it can accept the following format: +; - %{user}C for user CPU only +; - %{system}C for system CPU only +; - %{total}C for user + system CPU (default) +; %d: time taken to serve the request +; it can accept the following format: +; - %{seconds}d (default) +; - %{miliseconds}d +; - %{mili}d +; - %{microseconds}d +; - %{micro}d +; %e: an environment variable (same as $_ENV or $_SERVER) +; it must be associated with embraces to specify the name of the env +; variable. Some exemples: +; - server specifics like: %{REQUEST_METHOD}e or %{SERVER_PROTOCOL}e +; - HTTP headers like: %{HTTP_HOST}e or %{HTTP_USER_AGENT}e +; %f: script filename +; %l: content-length of the request (for POST request only) +; %m: request method +; %M: peak of memory allocated by PHP +; it can accept the following format: +; - %{bytes}M (default) +; - %{kilobytes}M +; - %{kilo}M +; - %{megabytes}M +; - %{mega}M +; %n: pool name +; %o: output header +; it must be associated with embraces to specify the name of the header: +; - %{Content-Type}o +; - %{X-Powered-By}o +; - %{Transfert-Encoding}o +; - .... +; %p: PID of the child that serviced the request +; %P: PID of the parent of the child that serviced the request +; %q: the query string +; %Q: the '?' character if query string exists +; %r: the request URI (without the query string, see %q and %Q) +; %R: remote IP address +; %s: status (response code) +; %t: server time the request was received +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %T: time the log has been written (the request has finished) +; it can accept a strftime(3) format: +; %d/%b/%Y:%H:%M:%S %z (default) +; The strftime(3) format must be encapsuled in a %{}t tag +; e.g. for a ISO8601 formatted timestring, use: %{%Y-%m-%dT%H:%M:%S%z}t +; %u: remote user +; +; Default: "%R - %u %t \"%m %r\" %s" +;access.format = "%R - %u %t \"%m %r%Q%q\" %s %f %{mili}d %{kilo}M %C%%" + +; The log file for slow requests +; Default Value: not set +; Note: slowlog is mandatory if request_slowlog_timeout is set +;slowlog = log/$pool.log.slow + +; The timeout for serving a single request after which a PHP backtrace will be +; dumped to the 'slowlog' file. A value of '0s' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_slowlog_timeout = 0 + +; The timeout for serving a single request after which the worker process will +; be killed. This option should be used when the 'max_execution_time' ini option +; does not stop script execution for some reason. A value of '0' means 'off'. +; Available units: s(econds)(default), m(inutes), h(ours), or d(ays) +; Default Value: 0 +;request_terminate_timeout = 0 + +; Set open file descriptor rlimit. +; Default Value: system defined value +;rlimit_files = 1024 + +; Set max core size rlimit. +; Possible Values: 'unlimited' or an integer greater or equal to 0 +; Default Value: system defined value +;rlimit_core = 0 + +; Chroot to this directory at the start. This value must be defined as an +; absolute path. When this value is not set, chroot is not used. +; Note: you can prefix with '$prefix' to chroot to the pool prefix or one +; of its subdirectories. If the pool prefix is not set, the global prefix +; will be used instead. +; Note: chrooting is a great security feature and should be used whenever +; possible. However, all PHP paths will be relative to the chroot +; (error_log, sessions.save_path, ...). +; Default Value: not set +;chroot = + +; Chdir to this directory at the start. +; Note: relative path can be used. +; Default Value: current directory or / when chroot +;chdir = /var/www + +; Redirect worker stdout and stderr into main error log. If not set, stdout and +; stderr will be redirected to /dev/null according to FastCGI specs. +; Note: on highloaded environement, this can cause some delay in the page +; process time (several ms). +; Default Value: no +;catch_workers_output = yes + +; Clear environment in FPM workers +; Prevents arbitrary environment variables from reaching FPM worker processes +; by clearing the environment in workers before env vars specified in this +; pool configuration are added. +; Setting to "no" will make all environment variables available to PHP code +; via getenv(), $_ENV and $_SERVER. +; Default Value: yes +;clear_env = no + +; Limits the extensions of the main script FPM will allow to parse. This can +; prevent configuration mistakes on the web server side. You should only limit +; FPM to .php extensions to prevent malicious users to use other extensions to +; exectute php code. +; Note: set an empty value to allow all extensions. +; Default Value: .php +;security.limit_extensions = .php .php3 .php4 .php5 .php7 + +; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from +; the current environment. +; Default Value: clean env +;env[HOSTNAME] = $HOSTNAME +;env[PATH] = /usr/local/bin:/usr/bin:/bin +;env[TMP] = /tmp +;env[TMPDIR] = /tmp +;env[TEMP] = /tmp + +; Additional php.ini defines, specific to this pool of workers. These settings +; overwrite the values previously defined in the php.ini. The directives are the +; same as the PHP SAPI: +; php_value/php_flag - you can set classic ini defines which can +; be overwritten from PHP call 'ini_set'. +; php_admin_value/php_admin_flag - these directives won't be overwritten by +; PHP call 'ini_set' +; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no. + +; Defining 'extension' will load the corresponding shared extension from +; extension_dir. Defining 'disable_functions' or 'disable_classes' will not +; overwrite previously defined php.ini values, but will append the new value +; instead. + +; Note: path INI options can be relative and will be expanded with the prefix +; (pool, global or @prefix@) + +; Default Value: nothing is defined by default except the values in php.ini and +; specified at startup with the -d argument +;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com +;php_flag[display_errors] = off +;php_admin_value[error_log] = /var/log/fpm-php.www.log +;php_admin_flag[log_errors] = on +;php_admin_value[memory_limit] = 32M From cfdeedd98558a7f946ed79f7100812dc2a43abfe Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 15 Aug 2016 23:17:26 -0700 Subject: [PATCH 33/49] Fix bug #72837 - integer overflow in bzdecompress caused heap corruption --- ext/bz2/bz2.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ext/bz2/bz2.c b/ext/bz2/bz2.c index 54b59f75d44..79ec3ec3fed 100644 --- a/ext/bz2/bz2.c +++ b/ext/bz2/bz2.c @@ -196,7 +196,7 @@ php_stream_ops php_stream_bz2io_ops = { }; /* {{{ Bzip2 stream openers */ -PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, +PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, const char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC) { struct php_bz2_stream_data_t *self; @@ -574,15 +574,25 @@ static PHP_FUNCTION(bzdecompress) /* compression is better then 2:1, need to allocate more memory */ bzs.avail_out = source_len; size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; + if (size > INT_MAX) { + /* no reason to continue if we're going to drop it anyway */ + break; + } dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size ); bzs.next_out = dest + size; } if (error == BZ_STREAM_END || error == BZ_OK) { size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32; - dest = safe_erealloc(dest, 1, (size_t) size, 1); - dest[size] = '\0'; - RETVAL_STRINGL(dest, (int) size, 0); + if (size > INT_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompressed size too big, max is %d", INT_MAX); + efree(dest); + RETVAL_LONG(BZ_MEM_ERROR); + } else { + dest = safe_erealloc(dest, 1, (size_t) size, 1); + dest[size] = '\0'; + RETVAL_STRINGL(dest, (int) size, 0); + } } else { /* real error */ efree(dest); RETVAL_LONG(error); From 5f91f692c354e45b9b46ba672f4182ff478bd1a3 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Mon, 15 Aug 2016 23:43:59 -0700 Subject: [PATCH 34/49] Fix bug #72838 - Integer overflow lead to heap corruption in sql_regcase --- ext/ereg/ereg.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/ereg/ereg.c b/ext/ereg/ereg.c index 5d38d043750..8eb833ac873 100644 --- a/ext/ereg/ereg.c +++ b/ext/ereg/ereg.c @@ -743,6 +743,11 @@ PHP_EREG_API PHP_FUNCTION(sql_regcase) for (i = j = 0; i < string_len; i++) { c = (unsigned char) string[i]; + if ( j >= INT_MAX - 1 || (isalpha(c) && j >= INT_MAX - 4)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, max length is %d", INT_MAX); + efree(tmp); + RETURN_FALSE; + } if (isalpha(c)) { tmp[j++] = '['; tmp[j++] = toupper(c); From 24d741d376905ab21eed17c25dd3ce09a8893f80 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 16 Aug 2016 15:48:31 -0700 Subject: [PATCH 35/49] Fix bug #72848 - integer overflow in quoted_printable_encode caused heap corruption --- ext/standard/quot_print.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c index 3b8c0eca1f8..6d5835e9a24 100644 --- a/ext/standard/quot_print.c +++ b/ext/standard/quot_print.c @@ -144,7 +144,7 @@ PHPAPI unsigned char *php_quot_print_decode(const unsigned char *str, size_t len /* }}} */ #define PHP_QPRINT_MAXL 75 - + PHPAPI unsigned char *php_quot_print_encode(const unsigned char *str, size_t length, size_t *ret_length) /* {{{ */ { unsigned long lp = 0; @@ -162,9 +162,9 @@ PHPAPI unsigned char *php_quot_print_encode(const unsigned char *str, size_t len lp = 0; } else { if (iscntrl (c) || (c == 0x7f) || (c & 0x80) || (c == '=') || ((c == ' ') && (*str == '\015'))) { - if ((((lp+= 3) > PHP_QPRINT_MAXL) && (c <= 0x7f)) - || ((c > 0x7f) && (c <= 0xdf) && ((lp + 3) > PHP_QPRINT_MAXL)) - || ((c > 0xdf) && (c <= 0xef) && ((lp + 6) > PHP_QPRINT_MAXL)) + if ((((lp+= 3) > PHP_QPRINT_MAXL) && (c <= 0x7f)) + || ((c > 0x7f) && (c <= 0xdf) && ((lp + 3) > PHP_QPRINT_MAXL)) + || ((c > 0xdf) && (c <= 0xef) && ((lp + 6) > PHP_QPRINT_MAXL)) || ((c > 0xef) && (c <= 0xf4) && ((lp + 9) > PHP_QPRINT_MAXL))) { *d++ = '='; *d++ = '\015'; @@ -208,7 +208,7 @@ PHP_FUNCTION(quoted_printable_decode) if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg1, &arg1_len) == FAILURE) { return; } - + if (arg1_len == 0) { /* shortcut */ RETURN_EMPTY_STRING(); @@ -219,11 +219,11 @@ PHP_FUNCTION(quoted_printable_decode) while (str_in[i]) { switch (str_in[i]) { case '=': - if (str_in[i + 1] && str_in[i + 2] && - isxdigit((int) str_in[i + 1]) && + if (str_in[i + 1] && str_in[i + 2] && + isxdigit((int) str_in[i + 1]) && isxdigit((int) str_in[i + 2])) { - str_out[j++] = (php_hex2int((int) str_in[i + 1]) << 4) + str_out[j++] = (php_hex2int((int) str_in[i + 1]) << 4) + php_hex2int((int) str_in[i + 2]); i += 3; } else /* check for soft line break according to RFC 2045*/ { @@ -254,7 +254,7 @@ PHP_FUNCTION(quoted_printable_decode) } } str_out[j] = '\0'; - + RETVAL_STRINGL(str_out, j, 0); } /* }}} */ @@ -275,6 +275,11 @@ PHP_FUNCTION(quoted_printable_encode) } new_str = (char *)php_quot_print_encode((unsigned char *)str, (size_t)str_len, &new_str_len); + if (new_str_len > INT_MAX) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, max length is %d", INT_MAX); + efree(new_str); + RETURN_FALSE; + } RETURN_STRINGL(new_str, new_str_len, 0); } /* }}} */ From b9e81e58440b9b5c07bf5435baef5531b2b318a0 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 16 Aug 2016 15:58:05 -0700 Subject: [PATCH 36/49] Fixed bug #72849 - integer overflow in urlencode --- ext/standard/url.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ext/standard/url.c b/ext/standard/url.c index 4b52000f645..8e471e12d82 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -520,6 +520,12 @@ PHPAPI char *php_url_encode(char const *s, int len, int *new_length) *to++ = c; } } + + if ((to-start) > INT_MAX) { + /* E_ERROR since most clients won't check for error, and this is rather rare condition */ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "String overflow, max length is %d", INT_MAX); + } + *to = 0; if (new_length) { *new_length = to - start; From 35a8ed2f6283d0dd09009e1f1ab18d66bdff5e42 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 16 Aug 2016 16:03:44 -0700 Subject: [PATCH 37/49] Fix bug #72850 - integer overflow in uuencode --- ext/standard/uuencode.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ext/standard/uuencode.c b/ext/standard/uuencode.c index cd35c288ee8..a31f14d8245 100644 --- a/ext/standard/uuencode.c +++ b/ext/standard/uuencode.c @@ -153,7 +153,7 @@ PHPAPI int php_uudecode(char *src, int src_len, char **dest) /* {{{ */ while (s < ee) { if(s+4 > e) { goto err; - } + } *p++ = PHP_UU_DEC(*s) << 2 | PHP_UU_DEC(*(s + 1)) >> 4; *p++ = PHP_UU_DEC(*(s + 1)) << 4 | PHP_UU_DEC(*(s + 2)) >> 2; *p++ = PHP_UU_DEC(*(s + 2)) << 6 | PHP_UU_DEC(*(s + 3)); @@ -188,7 +188,7 @@ err: } /* }}} */ -/* {{{ proto string convert_uuencode(string data) +/* {{{ proto string convert_uuencode(string data) uuencode a string */ PHP_FUNCTION(convert_uuencode) { @@ -200,6 +200,11 @@ PHP_FUNCTION(convert_uuencode) } dst_len = php_uuencode(src, src_len, &dst); + if (dst_len < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, max length is %d", INT_MAX); + efree(dst); + RETURN_FALSE; + } RETURN_STRINGL(dst, dst_len, 0); } From 40bd921cea0cfb96dd0a19d95ed19078d06a9988 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 16 Aug 2016 16:34:35 -0700 Subject: [PATCH 38/49] Fix TSRM build --- ext/standard/base64.c | 1 + ext/standard/url.c | 1 + 2 files changed, 2 insertions(+) diff --git a/ext/standard/base64.c b/ext/standard/base64.c index 8340ed12607..b30a5b73b16 100644 --- a/ext/standard/base64.c +++ b/ext/standard/base64.c @@ -67,6 +67,7 @@ PHPAPI unsigned char *php_base64_encode(const unsigned char *str, int length, in } if (((size_t)length + 2) / 3 > INT_MAX/4 ) { + TSRMLS_FETCH(); php_error_docref(NULL TSRMLS_CC, E_WARNING, "String too long, maximum is %d", INT_MAX/4); return NULL; } diff --git a/ext/standard/url.c b/ext/standard/url.c index 8e471e12d82..dd861a570d8 100644 --- a/ext/standard/url.c +++ b/ext/standard/url.c @@ -522,6 +522,7 @@ PHPAPI char *php_url_encode(char const *s, int len, int *new_length) } if ((to-start) > INT_MAX) { + TSRMLS_FETCH(); /* E_ERROR since most clients won't check for error, and this is rather rare condition */ php_error_docref(NULL TSRMLS_CC, E_ERROR, "String overflow, max length is %d", INT_MAX); } From d8b2de164e4900fe96094df7753d88a14893c7a5 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 16 Aug 2016 16:47:53 -0700 Subject: [PATCH 39/49] fix tests --- ext/gd/tests/imagetruecolortopalette_error3.phpt | 2 +- ext/gd/tests/imagetruecolortopalette_error4.phpt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/gd/tests/imagetruecolortopalette_error3.phpt b/ext/gd/tests/imagetruecolortopalette_error3.phpt index d65a995014c..dbbdb081cc8 100644 --- a/ext/gd/tests/imagetruecolortopalette_error3.phpt +++ b/ext/gd/tests/imagetruecolortopalette_error3.phpt @@ -25,4 +25,4 @@ Warning: imagetruecolortopalette() expects parameter 3 to be long, resource give Warning: imagetruecolortopalette() expects parameter 3 to be long, array given in %s on line %d -Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d \ No newline at end of file +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s on line %d \ No newline at end of file diff --git a/ext/gd/tests/imagetruecolortopalette_error4.phpt b/ext/gd/tests/imagetruecolortopalette_error4.phpt index b9661e3b852..1d56bfcdf05 100644 --- a/ext/gd/tests/imagetruecolortopalette_error4.phpt +++ b/ext/gd/tests/imagetruecolortopalette_error4.phpt @@ -16,6 +16,6 @@ imagetruecolortopalette($image, true, -1); ?> --EXPECTF-- -Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s on line %d -Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d \ No newline at end of file +Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s on line %d \ No newline at end of file From 4bf5c3187fe63073effea949360454b1c5641c41 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 16 Aug 2016 22:49:06 -0700 Subject: [PATCH 40/49] BLock test with memory leak --- ext/standard/tests/strings/bug72663_3.phpt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/standard/tests/strings/bug72663_3.phpt b/ext/standard/tests/strings/bug72663_3.phpt index e336bc868db..f7d66efd178 100644 --- a/ext/standard/tests/strings/bug72663_3.phpt +++ b/ext/standard/tests/strings/bug72663_3.phpt @@ -1,5 +1,7 @@ --TEST-- Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--XFAIL-- +Memory leak, TBF later. --FILE-- Date: Tue, 16 Aug 2016 23:44:59 -0700 Subject: [PATCH 41/49] Update NEWS --- NEWS | 168 +++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 100 insertions(+), 68 deletions(-) diff --git a/NEWS b/NEWS index 30a17c1d057..1d5e5f8189e 100644 --- a/NEWS +++ b/NEWS @@ -30,14 +30,23 @@ PHP NEWS 18 Aug 2016, PHP 5.6.25 +- Bz2: + . Fixed bug #72837 (integer overflow in bzdecompress caused heap + corruption). (Stas) + - Core: + . Fixed bug #70436 (Use After Free Vulnerability in unserialize()). + (Taoguang Chen) + . Fixed bug #72024 (microtime() leaks memory). (maroszek at gmx dot net) . Fixed bug #72581 (previous property undefined in Exception after deserialization). (Laruence) - . Fixed bug #72024 (microtime() leaks memory). (maroszek at gmx dot net) . Implemented FR #72614 (Support "nmake test" on building extensions by phpize). (Yuji Uchiyama) . Fixed bug #72641 (phpize (on Windows) ignores PHP_PREFIX). (Yuji Uchiyama) + . Fixed bug #72663 (Create an Unexpected Object and Don't Invoke + __wakeup() in Deserialization). (Stas) + . Fixed bug #72681 (PHP Session Data Injection Vulnerability). (Stas) - Calendar: . Fixed bug #67976 (cal_days_month() fails for final month of the French @@ -50,11 +59,18 @@ PHP NEWS (maroszek at gmx dot net) . Fixed bug #71929 (Certification information (CERTINFO) data parsing error). (Pierrick) + . Fixed bug #72807 (integer overflow in curl_escape caused heap + corruption). (Stas) - DOM: . Fixed bug #66502 (DOM document dangling reference). (Sean Heelan, cmb) +- Ereg: + . Fixed bug #72838 (Integer overflow lead to heap corruption in + sql_regcase). (Stas) + - EXIF: + . Fixed bug #72627 (Memory Leakage In exif_process_IFD_in_TIFF). (Stas) . Fixed bug #72735 (Samsung picture thumb not read (zero size)). (Kalle, Remi) - Filter: @@ -66,14 +82,16 @@ PHP NEWS (gooh) - GD: - . Fixed bug #72596 (imagetypes function won't advertise WEBP support). (cmb) - . Fixed bug #72604 (imagearc() ignores thickness for full arcs). (cmb) - . Fixed bug #70315 (500 Server Error but page is fully rendered). (cmb) . Fixed bug #43828 (broken transparency of imagearc for truecolor in blendingmode). (cmb) . Fixed bug #66555 (Always false condition in ext/gd/libgd/gdkanji.c). (cmb) . Fixed bug #68712 (suspicious if-else statements). (cmb) + . Fixed bug #70315 (500 Server Error but page is fully rendered). (cmb) + . Fixed bug #72596 (imagetypes function won't advertise WEBP support). (cmb) + . Fixed bug #72604 (imagearc() ignores thickness for full arcs). (cmb) + . Fixed bug #72697 (select_colors write out-of-bounds). (Stas) . Fixed bug #72709 (imagesetstyle() causes OOB read for empty $styles). (cmb) + . Fixed bug #72730 (imagegammacorrect allows arbitrary write access). (Stas) - Intl: . Partially fixed #72506 (idn_to_ascii for UTS #46 incorrect for long domain @@ -102,12 +120,17 @@ PHP NEWS . Fixed bug #72222 (ReflectionClass::export doesn't handle array constants). (Nikita Nefedov) +- SNMP: + . Fixed bug #72708 (php_snmp_parse_oid integer overflow in memory + allocation). (djodjo at gmail dot com) + - Standard: . Fixed bug #72330 (CSV fields incorrectly split if escape char followed by UTF chars). (cmb) - -- SPL: - . Fixed bug #72684 (AppendIterator segfault with closed generator). (Pierrick) + . Fixed bug #72836 (integer overflow in base64_decode). (Stas) + . Fixed bug #72848 (integer overflow in quoted_printable_encode). (Stas) + . Fixed bug #72849 (integer overflow in urlencode). (Stas) + . Fixed bug #72850 (integer overflow in php_uuencode). (Stas) - Streams: . Fixed bug #41021 (Problems with the ftps wrapper). (vhuk) @@ -116,11 +139,14 @@ PHP NEWS non-existent directories). (vhuk) . Fixed bug #72764 (ftps:// opendir wrapper data channel encryption fails with IIS FTP 7.5, 8.5). (vhuk) + . Fixed bug #72771 (ftps:// wrapper is vulnerable to protocol downgrade + attack). (Stas) - SPL: . Fixed bug #72122 (IteratorIterator breaks '@' error suppression). (kinglozzer) . Fixed bug #72646 (SplFileObject::getCsvControl does not return the escape character). (cmb) + . Fixed bug #72684 (AppendIterator segfault with closed generator). (Pierrick) - SQLite3: . Implemented FR #72653 (SQLite should allow opening with empty filename). @@ -129,6 +155,12 @@ PHP NEWS - Wddx: . Fixed bug #72142 (WDDX Packet Injection Vulnerability in wddx_serialize_value()). (Taoguang Chen) + . Fixed bug #72749 (wddx_deserialize allows illegal memory access) (Stas) + . Fixed bug #72750 (wddx_deserialize null dereference). (Stas) + . Fixed bug #72790 (wddx_deserialize null dereference with invalid xml). + (Stas) + . Fixed bug #72799 (wddx_deserialize null dereference in + php_wddx_pop_element). (Stas) 21 Jul 2016, PHP 5.6.24 @@ -222,7 +254,7 @@ PHP NEWS (cmb) . Fixed bug #72298 (pass2_no_dither out-of-bounds access). (Stas) . Fixed bug #72337 (invalid dimensions can lead to crash). (Pierre) - . Fixed bug #72339 (Integer Overflow in _gd2GetHeader() resulting in + . Fixed bug #72339 (Integer Overflow in _gd2GetHeader() resulting in heap overflow). (CVE-2016-5766) (Pierre) . Fixed bug #72407 (NULL Pointer Dereference at _gdScaleVert). (Stas) . Fixed bug #72446 (Integer Overflow in gdImagePaletteToTrueColor() resulting @@ -296,7 +328,7 @@ PHP NEWS - Curl: . Fixed bug #71831 (CURLOPT_NOPROXY applied as long instead of string). - (Michael Sierks) + (Michael Sierks) - Date: . Fixed bug #71889 (DateInterval::format Segmentation fault). (Thomas Punt) @@ -611,7 +643,7 @@ PHP NEWS a server). (Sergei Turchanov) - OpenSSL: - . Fixed bug #55259 (openssl extension does not get the DH parameters from + . Fixed bug #55259 (openssl extension does not get the DH parameters from DH key resource). (Jakub Zelenka) . Fixed bug #70395 (Missing ARG_INFO for openssl_seal()). (cmb) . Fixed bug #60632 (openssl_seal fails with AES). (Jakub Zelenka) @@ -703,7 +735,7 @@ PHP NEWS - Standard: . Fixed bug #70052 (getimagesize() fails for very large and very small WBMP). (cmb) - . Fixed bug #70157 (parse_ini_string() segmentation fault with + . Fixed bug #70157 (parse_ini_string() segmentation fault with INI_SCANNER_TYPED). (Tjerk) - XSLT: @@ -729,7 +761,7 @@ PHP NEWS - CLI server: . Fixed bug #69655 (php -S changes MKCALENDAR request method to MKCOL). (cmb) . Fixed bug #64878 (304 responses return Content-Type header). (cmb) - + - GD: . Fixed bug #53156 (imagerectangle problem with point ordering). (cmb) . Fixed bug #66387 (Stack overflow with imagefilltoborder). (CVE-2015-8874) @@ -810,7 +842,7 @@ PHP NEWS - Mysqlnd: . Fixed bug #69669 (mysqlnd is vulnerable to BACKRONYM). (CVE-2015-3152) (Andrey) - + - PCRE: . Fixed Bug #53823 (preg_replace: * qualifier on unicode replace garbles the string). (cmb) @@ -903,7 +935,7 @@ PHP NEWS 14 May 2015, PHP 5.6.9 - Core: - . Fixed bug #69467 (Wrong checked for the interface by using Trait). + . Fixed bug #69467 (Wrong checked for the interface by using Trait). (Laruence) . Fixed bug #69420 (Invalid read in zend_std_get_method). (Laruence) . Fixed bug #60022 ("use statement [...] has no effect" depends on leading @@ -1024,7 +1056,7 @@ PHP NEWS (Mike) . Fixed bug #64931 (phar_add_file is too restrictive on filename). (Mike) . Fixed bug #65467 (Call to undefined method cli_arg_typ_string). (Mike) - . Fixed bug #67761 (Phar::mapPhar fails for Phars inside a path containing + . Fixed bug #67761 (Phar::mapPhar fails for Phars inside a path containing ".tar"). (Mike) . Fixed bug #69324 (Buffer Over-read in unserialize when parsing Phar). (Stas) . Fixed bug #69441 (Buffer Overflow when parsing tar/zip/phar in @@ -1036,7 +1068,7 @@ PHP NEWS - SOAP: . Fixed bug #69152 (Type Confusion Infoleak Vulnerability in unserialize() with SoapFault). (Dmitry) - . Fixed bug #69293 (NEW segfault when using SoapClient::__setSoapHeader + . Fixed bug #69293 (NEW segfault when using SoapClient::__setSoapHeader (bisected, regression)). (Laruence) - SPL: @@ -1058,7 +1090,7 @@ PHP NEWS (Laruence) . Fixed bug #69121 (Segfault in get_current_user when script owner is not in passwd with ZTS build). (dan at syneto dot net) - . Fixed bug #65593 (Segfault when calling ob_start from output buffering + . Fixed bug #65593 (Segfault when calling ob_start from output buffering callback). (Mike) . Fixed bug #68986 (pointer returned by php_stream_fopen_temporary_file not validated in memory.c). (nayana at ddproperty dot com) @@ -1095,7 +1127,7 @@ PHP NEWS . Fixed bug #68964 (Allowed memory size exhausted with odbc_exec). (Anatol) - Opcache: - . Fixed bug #69159 (Opcache causes problem when passing a variable variable + . Fixed bug #69159 (Opcache causes problem when passing a variable variable to a function). (Dmitry, Laruence) . Fixed bug #69125 (Array numeric string as key). (Laruence) . Fixed bug #69038 (switch(SOMECONSTANT) misbehaves). (Laruence) @@ -1129,7 +1161,7 @@ PHP NEWS - SPL: . Fixed bug #69108 ("Segmentation fault" when (de)serializing SplObjectStorage). (Laruence) - . Fixed bug #68557 (RecursiveDirectoryIterator::seek(0) broken after + . Fixed bug #68557 (RecursiveDirectoryIterator::seek(0) broken after calling getChildren()). (Julien) - ZIP: @@ -1205,7 +1237,7 @@ PHP NEWS . Fixed bug #68063 (Empty session IDs do still start sessions) (Yasuo) - Sqlite3: - . Fixed bug #68260 (SQLite3Result::fetchArray declares wrong + . Fixed bug #68260 (SQLite3Result::fetchArray declares wrong required_num_args). (Julien) - Standard: @@ -1250,7 +1282,7 @@ PHP NEWS CURLOPT_RETURNTRANSFER isn't set). (Jille Timmermans) - Date: - . Implemented FR #68268 (DatePeriod: Getter for start date, end date and + . Implemented FR #68268 (DatePeriod: Getter for start date, end date and interval). (Marc Bennewitz) - EXIF: @@ -1327,7 +1359,7 @@ PHP NEWS (Adam) . Fixed bug #68104 (Segfault while pre-evaluating a disabled function). (Laruence) - . Fixed bug #68185 ("Inconsistent insteadof definition."- incorrectly + . Fixed bug #68185 ("Inconsistent insteadof definition."- incorrectly triggered). (Julien) . Fixed bug #68355 (Inconsistency in example php.ini comments). (Chris McCafferty) @@ -1374,7 +1406,7 @@ PHP NEWS (Matteo) - Session: - . Fixed bug #68331 (Session custom storage callable functions not being called) + . Fixed bug #68331 (Session custom storage callable functions not being called) (Yasuo Ohgaki) - SOAP: @@ -1399,13 +1431,13 @@ PHP NEWS . Fixed bug #68095 (AddressSanitizer reports a heap buffer overflow in php_getopt()). (Stas) . Fixed bug #68118 ($a->foo .= 'test'; can leave $a->foo undefined). (Nikita) - . Fixed bug #68129 (parse_url() - incomplete support for empty usernames + . Fixed bug #68129 (parse_url() - incomplete support for empty usernames and passwords) (Tjerk) . Fixed bug #68365 (zend_mm_heap corrupted after memory overflow in zend_hash_copy). (Dmitry) - CURL: - . Add CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1, and + . Add CURL_SSLVERSION_TLSv1_0, CURL_SSLVERSION_TLSv1_1, and CURL_SSLVERSION_TLSv1_2 constants if supported by libcurl (Rasmus) - Fileinfo: @@ -1577,7 +1609,7 @@ PHP NEWS . Fixed bug #67250 (iptcparse out-of-bounds read). (Stas) . Fixed bug #67252 (convert_uudecode out-of-bounds read). (Stas) . Fixed bug #67249 (printf out-of-bounds read). (Stas) - . Implemented FR #64744 (Differentiate between member function call on a null + . Implemented FR #64744 (Differentiate between member function call on a null and non-null, non-objects). (Boro Sitnikovski) . Fixed bug #67436 (Autoloader isn't called if two method definitions don't match). (Bob) @@ -1608,7 +1640,7 @@ PHP NEWS (Ralf Lang, Mike) . Reduced POST data memory usage by 200-300%. Changed INI setting always_populate_raw_post_data to throw a deprecation warning when enabling - and to accept -1 for never populating the $HTTP_RAW_POST_DATA global + and to accept -1 for never populating the $HTTP_RAW_POST_DATA global variable, which will be the default in future PHP versions. (Mike) . Implemented dedicated syntax for variadic functions (RFC: https://wiki.php.net/rfc/variadics). (Nikita) @@ -1621,9 +1653,9 @@ PHP NEWS . Allow zero length comparison in substr_compare() (Tjerk) . Fixed bug #60602 (proc_open() changes environment array) (Tjerk) . Fixed bug #61019 (Out of memory on command stream_get_contents). (Mike) - . Fixed bug #64330 (stream_socket_server() creates wrong Abstract Namespace + . Fixed bug #64330 (stream_socket_server() creates wrong Abstract Namespace UNIX sockets). (Mike) - . Fixed bug #66182 (exit in stream filter produces segfault). (Mike) + . Fixed bug #66182 (exit in stream filter produces segfault). (Mike) . Fixed bug #66736 (fpassthru broken). (Mike) . Fixed bug #66822 (Cannot use T_POW in const expression) (Tjerk) . Fixed bug #67043 (substr_compare broke by previous change) (Tjerk) @@ -1994,7 +2026,7 @@ PHP NEWS (Matteo) - PDO-ODBC: - . Fixed bug #50444 (PDO-ODBC changes for 64-bit). + . Fixed bug #50444 (PDO-ODBC changes for 64-bit). - PDO_pgsql: . Fixed Bug #42614 (PDO_pgsql: add pg_get_notify support). (Matteo) @@ -2053,7 +2085,7 @@ PHP NEWS - SPL: . Revert fix for bug #67064 (BC issues). (Bob) - . Fixed bug #67539 (ArrayIterator use-after-free due to object change during + . Fixed bug #67539 (ArrayIterator use-after-free due to object change during sorting). (CVE-2014-4698) (research at insighti dot org, Laruence) . Fixed bug #67538 (SPL Iterators use-after-free). (CVE-2014-4670) (Laruence) . Fixed bug #67492 (unserialize() SPL ArrayObject / SPLObjectStorage Type @@ -2082,7 +2114,7 @@ PHP NEWS token). (Ferenc) - XMLReader: - . Fixed bug #55285 (XMLReader::getAttribute/No/Ns methods inconsistency). + . Fixed bug #55285 (XMLReader::getAttribute/No/Ns methods inconsistency). (Mike) - XSL: @@ -2102,7 +2134,7 @@ PHP NEWS - Zlib: . Fixed bug #67865 (internal corruption phar error). Mike - . Fixed bug #67724 (chained zlib filters silently fail with large amounts of + . Fixed bug #67724 (chained zlib filters silently fail with large amounts of data). (Mike) 21 Aug 2014, PHP 5.5.16 @@ -2127,7 +2159,7 @@ PHP NEWS - Milter: . Fixed bug #67715 (php-milter does not build and crashes randomly). (Mike) - + - Network: . Fixed bug #67717 (segfault in dns_get_record). (CVE-2014-3597) (Remi) @@ -2181,7 +2213,7 @@ PHP NEWS . Fixed bug #67531 (syslog cannot be set in pool configuration). (Remi) - Intl: - . Fixed bug #66921 (Wrong argument type hint for function + . Fixed bug #66921 (Wrong argument type hint for function intltz_from_date_time_zone). (Stas) . Fixed bug #67052 (NumberFormatter::parse() resets LC_NUMERIC setting). (Stas) @@ -2198,7 +2230,7 @@ PHP NEWS . Fixed bug #67587 (Redirection loop on nginx with FPM). (Christian Weiske) - SPL: - . Fixed bug #67539 (ArrayIterator use-after-free due to object change during + . Fixed bug #67539 (ArrayIterator use-after-free due to object change during sorting). (CVE-2014-4698) (research at insighti dot org, Laruence) . Fixed bug #67538 (SPL Iterators use-after-free). (CVE-2014-4670) (Laruence) @@ -2320,9 +2352,9 @@ PHP NEWS 30 Apr 2014, PHP 5.5.12 - Core: . Fixed bug #61019 (Out of memory on command stream_get_contents). (Mike) - . Fixed bug #64330 (stream_socket_server() creates wrong Abstract Namespace + . Fixed bug #64330 (stream_socket_server() creates wrong Abstract Namespace UNIX sockets). (Mike) - . Fixed bug #66182 (exit in stream filter produces segfault). (Mike) + . Fixed bug #66182 (exit in stream filter produces segfault). (Mike) . Fixed bug #66736 (fpassthru broken). (Mike) . Fixed bug #67024 (getimagesize should recognize BMP files with negative height). (Gabor Buella) @@ -2416,7 +2448,7 @@ PHP NEWS (Nikita) - Intl: - . Fixed bug #66873 (A reproductible crash in UConverter when given invalid + . Fixed bug #66873 (A reproductible crash in UConverter when given invalid encoding) (Stas) - Mail: @@ -2491,7 +2523,7 @@ PHP NEWS (Dmitry) . Fixed bug #66461 (PHP crashes if opcache.interned_strings_buffer=0). (Dmitry) - . Fixed bug #66298 (ext/opcache/Optimizer/zend_optimizer.c has dos-style + . Fixed bug #66298 (ext/opcache/Optimizer/zend_optimizer.c has dos-style ^M as lineend). (Laruence) - PDO_pgsql: @@ -2533,12 +2565,12 @@ spaces) (willfitch, iliaa) . Fixed bug #66218 (zend_register_functions breaks reflection). (Remi) - Date: - . Fixed bug #66060 (Heap buffer over-read in DateInterval) (CVE-2013-6712). + . Fixed bug #66060 (Heap buffer over-read in DateInterval) (CVE-2013-6712). (Remi) . Fixed bug #65768 (DateTimeImmutable::diff does not work). (Nikita Nefedov) - + - DOM: - . Fixed bug #65196 (Passing DOMDocumentFragment to DOMDocument::saveHTML() + . Fixed bug #65196 (Passing DOMDocumentFragment to DOMDocument::saveHTML() Produces invalid Markup). (Mike) - Exif: @@ -2550,9 +2582,9 @@ spaces) (willfitch, iliaa) - GD: . Fixed bug #64405 (Use freetype-config for determining freetype2 dir(s)). (Adam) - + - PDO_odbc: - . Fixed bug #66311 (Stack smashing protection kills PDO/ODBC queries). + . Fixed bug #66311 (Stack smashing protection kills PDO/ODBC queries). (michael at orlitzky dot com) - MySQLi: @@ -2589,7 +2621,7 @@ spaces) (willfitch, iliaa) server) - also implements apache_response_headers() (Andrea Faulds) - Core: - . Fixed bug #66094 (unregister_tick_function tries to cast a Closure to a + . Fixed bug #66094 (unregister_tick_function tries to cast a Closure to a string). (Laruence) . Fixed bug #65969 (Chain assignment with T_LIST failure). (Dmitry) @@ -2609,7 +2641,7 @@ spaces) (willfitch, iliaa) 14 Nov 2013, PHP 5.5.6 - Core: - . Fixed bug #65947 (basename is no more working after fgetcsv in certain + . Fixed bug #65947 (basename is no more working after fgetcsv in certain situation). (Laruence) . Improved performance of array_merge() and func_get_args() by eliminating useless copying. (Dmitry) @@ -2640,7 +2672,7 @@ spaces) (willfitch, iliaa) 32 characters). (patch submitted by: michael dot y at zend dot com, Yasuo) - PDO: - . Fixed bug #66033 (Segmentation Fault when constructor of PDO statement + . Fixed bug #66033 (Segmentation Fault when constructor of PDO statement throws an exception). (Laruence) . Fixed bug 65946 (sql_parser permanently converts values bound to strings) @@ -2661,7 +2693,7 @@ spaces) (willfitch, iliaa) - CLI server: . Fixed bug #65633 (built-in server treat some http headers as case-sensitive). (Adam) - . Fixed bug #65818 (Segfault with built-in webserver and chunked transfer + . Fixed bug #65818 (Segfault with built-in webserver and chunked transfer encoding). (Felipe) . Added application/pdf to PHP CLI Web Server mime types (Chris Jones) @@ -2714,17 +2746,17 @@ spaces) (willfitch, iliaa) a default value). (Nikita) - Standard: - . Fixed bug #61548 (content-type must appear at the end of headers for 201 + . Fixed bug #61548 (content-type must appear at the end of headers for 201 Location to work in http). (Mike) - XMLReader: . Fixed bug #51936 (Crash with clone XMLReader). (Mike) . Fixed bug #64230 (XMLReader does not suppress errors). (Mike) - + - Build system: . Fixed bug #51076 (race condition in shtool's mkdir -p implementation). (Mike, Raphael Geissert) - . Fixed bug #62396 ('make test' crashes starting with 5.3.14 (missing + . Fixed bug #62396 ('make test' crashes starting with 5.3.14 (missing gzencode())). (Mike) @@ -2734,7 +2766,7 @@ spaces) (willfitch, iliaa) . Fixed bug #60598 (cli/apache sapi segfault on objects manipulation). (Laruence) . Improved fputcsv() to allow specifying escape character. - . Fixed bug #65490 (Duplicate calls to get lineno & filename for + . Fixed bug #65490 (Duplicate calls to get lineno & filename for DTRACE_FUNCTION_*). (Chris Jones) . Fixed bug #65483 (quoted-printable encode stream filter incorrectly encoding spaces). (Michael M Slusarz) @@ -2766,21 +2798,21 @@ spaces) (willfitch, iliaa) some cases). (Mark Jones) - PDO: - . Fixed bug #64953 (Postgres prepared statement positional parameter + . Fixed bug #64953 (Postgres prepared statement positional parameter casting). (Mike) - Session: . Fixed bug #65475 (Session ID is not initialized properly when strict session is enabled). (Yasuo) - . Fixed bug #51127/#65359 Request #25630/#43980/#54383 (Added php_serialize + . Fixed bug #51127/#65359 Request #25630/#43980/#54383 (Added php_serialize session serialize handler that uses plain serialize()). (Yasuo) - Standard: . Fix issue with return types of password API helper functions. Found via - static analysis by cjones. (Anthony Ferrara) + static analysis by cjones. (Anthony Ferrara) - Zlib: - . Fixed bug #65391 (Unable to send vary header user-agent when + . Fixed bug #65391 (Unable to send vary header user-agent when ob_start('ob_gzhandler') is called) (Mike) 22 Aug 2013, PHP 5.5.3 @@ -2805,8 +2837,8 @@ spaces) (willfitch, iliaa) Zend/zend_dtrace.d) (Chris Jones) - DOM: - . Added flags option to DOMDocument::schemaValidate() and - DOMDocument::schemaValidateSource(). Added LIBXML_SCHEMA_CREATE flag. + . Added flags option to DOMDocument::schemaValidate() and + DOMDocument::schemaValidateSource(). Added LIBXML_SCHEMA_CREATE flag. (Chris Wright) - OPcache: @@ -2829,12 +2861,12 @@ spaces) (willfitch, iliaa) /pg_delete()/pg_insert()). (Yasuo) - Phar: - . Fixed bug #65028 (Phar::buildFromDirectory creates corrupt archives for + . Fixed bug #65028 (Phar::buildFromDirectory creates corrupt archives for some specific contents). (Stas) - Sessions: . Implemented strict sessions RFC (https://wiki.php.net/rfc/strict_sessions) - which protects against session fixation attacks and session collisions. + which protects against session fixation attacks and session collisions. (CVE-2011-4718). (Yasuo Ohgaki) . Fixed possible buffer overflow under Windows. Note: Not a security fix. (Yasuo) @@ -2845,9 +2877,9 @@ spaces) (willfitch, iliaa) - SPL: . Fixed bug #65328 (Segfault when getting SplStack object Value). (Laruence) - . Added RecursiveTreeIterator setPostfix and getPostifx methods. (Joshua + . Added RecursiveTreeIterator setPostfix and getPostifx methods. (Joshua Thijssen) - . Fixed bug #61697 (spl_autoload_functions returns lambda functions + . Fixed bug #61697 (spl_autoload_functions returns lambda functions incorrectly). (Laruence) - Streams: @@ -2864,7 +2896,7 @@ spaces) (willfitch, iliaa) with a namespace). (Laruence) . Fixed bug #65088 (Generated configure script is malformed on OpenBSD). (Adam) - . Fixed bug #65108 (is_callable() triggers Fatal Error). + . Fixed bug #65108 (is_callable() triggers Fatal Error). (David Soria Parra, Laruence) . Fixed bug #65035 (yield / exit segfault). (Nikita) . Fixed bug #65161 (Generator + autoload + syntax error = segfault). (Nikita) @@ -3282,7 +3314,7 @@ spaces) (willfitch, iliaa) . Fixed bug #63284 (Upgrade PCRE to 8.31). (Anatoliy) - PDO: - . Fixed bug #63176 (Segmentation fault when instantiate 2 persistent PDO to + . Fixed bug #63176 (Segmentation fault when instantiate 2 persistent PDO to the same db server). (Laruence) - PDO_DBlib: @@ -3368,7 +3400,7 @@ spaces) (willfitch, iliaa) 06 Jun 2013, PHP 5.4.16 - Core: - . Fixed bug #64879 (Heap based buffer overflow in quoted_printable_encode, + . Fixed bug #64879 (Heap based buffer overflow in quoted_printable_encode, CVE 2013-2110). (Stas) . Fixed bug #64853 (Use of no longer available ini directives causes crash on TS build). (Anatol) @@ -3397,7 +3429,7 @@ spaces) (willfitch, iliaa) pointer has closed). (Laruence) - Phar - . Fixed bug #64214 (PHAR PHPTs intermittently crash when run on DFS, SMB or + . Fixed bug #64214 (PHAR PHPTs intermittently crash when run on DFS, SMB or with non std tmp dir). (Pierre) - SNMP: @@ -3410,7 +3442,7 @@ spaces) (willfitch, iliaa) on Windows x64). (Anatol) - Zend Engine: - . Fixed bug #64821 (Custom Exceptions crash when internal properties + . Fixed bug #64821 (Custom Exceptions crash when internal properties overridden). (Anatol) 09 May 2013, PHP 5.4.15 From 2135fdef9b588a34f8805b2bbf10704e36163d5a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 8 Aug 2016 18:05:29 +0200 Subject: [PATCH 42/49] Bug #72663 - part 1 Don't call __destruct() on an unserialized object that has a __wakeup() method if either a) unserialization of its properties fails or b) the __wakeup() call fails (e.g. by throwing). This basically treats __wakeup() as a form of constructor and aligns us with the usual behavior that if the constructor call fails the destructor should not be called. The security aspect here is that people use __wakeup() to prevent unserialization of objects with dangerous __destruct() methods, but this is ineffective if __destruct() can still be called while __wakeup() was skipped. --- ext/standard/tests/serialize/bug72663.phpt | 56 ++++++++++++++++++++++ ext/standard/var_unserializer.c | 18 +++++-- ext/standard/var_unserializer.re | 16 +++++-- 3 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 ext/standard/tests/serialize/bug72663.phpt diff --git a/ext/standard/tests/serialize/bug72663.phpt b/ext/standard/tests/serialize/bug72663.phpt new file mode 100644 index 00000000000..c50591ca963 --- /dev/null +++ b/ext/standard/tests/serialize/bug72663.phpt @@ -0,0 +1,56 @@ +--TEST-- +Bug #72663 (1): Don't call __destruct if __wakeup not called or fails +--FILE-- + +--EXPECTF-- +Notice: unserialize(): Error at offset 17 of 24 bytes in %s on line %d +bool(false) + +Notice: unserialize(): Error at offset 25 of 32 bytes in %s on line %d +bool(false) +Caught +Caught diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index f464c0b63a3..317c3f9c487 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -455,23 +455,32 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) zval retval; zval fname; HashTable *ht; + zend_bool has_wakeup; if (Z_TYPE_P(rval) != IS_OBJECT) { return 0; } + has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY + && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1); + ht = Z_OBJPROP_P(rval); zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED)); if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { + if (has_wakeup) { + ZVAL_DEREF(rval); + GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; + } return 0; } ZVAL_DEREF(rval); - if (Z_OBJCE_P(rval) != PHP_IC_ENTRY && - zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) { + if (has_wakeup) { ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1); BG(serialize_lock)++; - call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL); + if (call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) { + GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; + } BG(serialize_lock)--; zval_dtor(&fname); zval_dtor(&retval); @@ -482,7 +491,6 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) } return finish_nested_data(UNSERIALIZE_PASSTHRU); - } #ifdef PHP_WIN32 # pragma optimize("", on) @@ -514,7 +522,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) start = cursor; -#line 518 "ext/standard/var_unserializer.c" +#line 526 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 81cc26db9d1..fa8cce88805 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -459,23 +459,32 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) zval retval; zval fname; HashTable *ht; + zend_bool has_wakeup; if (Z_TYPE_P(rval) != IS_OBJECT) { return 0; } + has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY + && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1); + ht = Z_OBJPROP_P(rval); zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED)); if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) { + if (has_wakeup) { + ZVAL_DEREF(rval); + GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; + } return 0; } ZVAL_DEREF(rval); - if (Z_OBJCE_P(rval) != PHP_IC_ENTRY && - zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) { + if (has_wakeup) { ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1); BG(serialize_lock)++; - call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL); + if (call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) { + GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED; + } BG(serialize_lock)--; zval_dtor(&fname); zval_dtor(&retval); @@ -486,7 +495,6 @@ static inline int object_common2(UNSERIALIZE_PARAMETER, zend_long elements) } return finish_nested_data(UNSERIALIZE_PASSTHRU); - } #ifdef PHP_WIN32 # pragma optimize("", on) From 61f2f5a0f760157f9c9d32d7d3df2be47a73e74d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 10 Aug 2016 14:30:16 +0200 Subject: [PATCH 43/49] Bug #72663 - part 2 If a (nested) unserialize() call fails, we remove all the values that were inserted into var_hash during that call. This prevents their use in other unserializations in the same context. --- ext/standard/tests/serialize/bug72663_2.phpt | 27 +++++++++++++++ ext/standard/var_unserializer.c | 36 +++++++++++++++++--- ext/standard/var_unserializer.re | 34 ++++++++++++++++-- 3 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 ext/standard/tests/serialize/bug72663_2.phpt diff --git a/ext/standard/tests/serialize/bug72663_2.phpt b/ext/standard/tests/serialize/bug72663_2.phpt new file mode 100644 index 00000000000..8825dc5efc3 --- /dev/null +++ b/ext/standard/tests/serialize/bug72663_2.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #72663 (2): Don't allow references into failed unserialize +--FILE-- +data); + } + function unserialize($data) { + $this->data = unserialize($data); + } +} + +$inner = 'a:1:{i:0;O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:4;}'; +$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}'; +var_dump(unserialize($exploit)); + +?> +--EXPECTF-- +Notice: unserialize(): Unexpected end of serialized data in %s on line %d + +Notice: unserialize(): Error at offset 46 of 47 bytes in %s on line %d + +Notice: unserialize(): Error at offset 79 of 80 bytes in %s on line %d +bool(false) diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 317c3f9c487..6b33d84bd2e 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -301,6 +301,8 @@ static inline size_t parse_uiv(const unsigned char *p) #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes +static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER); + static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops) { while (elements-- > 0) { @@ -309,7 +311,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab ZVAL_UNDEF(&key); - if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) { + if (!php_var_unserialize_internal(&key, p, max, NULL, classes)) { zval_dtor(&key); return 0; } @@ -365,7 +367,7 @@ string_key: } } - if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) { + if (!php_var_unserialize_internal(data, p, max, var_hash, classes)) { zval_dtor(&key); return 0; } @@ -502,8 +504,34 @@ PHPAPI int php_var_unserialize(zval *rval, const unsigned char **p, const unsign return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU); } - PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) +{ + var_entries *orig_var_entries = (*var_hash)->last; + zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0; + int result; + + result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU); + + if (!result) { + /* If the unserialization failed, mark all elements that have been added to var_hash + * as NULL. This will forbid their use by other unserialize() calls in the same + * unserialization context. */ + var_entries *e = orig_var_entries; + zend_long s = orig_used_slots; + while (e) { + for (; s < e->used_slots; s++) { + e->data[s] = NULL; + } + + e = e->next; + s = 0; + } + } + + return result; +} + +static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER) { const unsigned char *cursor, *limit, *marker, *start; zval *rval_ref; @@ -522,7 +550,7 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) start = cursor; -#line 526 "ext/standard/var_unserializer.c" +#line 554 "ext/standard/var_unserializer.c" { YYCTYPE yych; static const unsigned char yybm[] = { diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index fa8cce88805..90518946431 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -305,6 +305,8 @@ static inline size_t parse_uiv(const unsigned char *p) #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes +static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER); + static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops) { while (elements-- > 0) { @@ -313,7 +315,7 @@ static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTab ZVAL_UNDEF(&key); - if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) { + if (!php_var_unserialize_internal(&key, p, max, NULL, classes)) { zval_dtor(&key); return 0; } @@ -369,7 +371,7 @@ string_key: } } - if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) { + if (!php_var_unserialize_internal(data, p, max, var_hash, classes)) { zval_dtor(&key); return 0; } @@ -506,8 +508,34 @@ PHPAPI int php_var_unserialize(zval *rval, const unsigned char **p, const unsign return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU); } - PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) +{ + var_entries *orig_var_entries = (*var_hash)->last; + zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0; + int result; + + result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU); + + if (!result) { + /* If the unserialization failed, mark all elements that have been added to var_hash + * as NULL. This will forbid their use by other unserialize() calls in the same + * unserialization context. */ + var_entries *e = orig_var_entries; + zend_long s = orig_used_slots; + while (e) { + for (; s < e->used_slots; s++) { + e->data[s] = NULL; + } + + e = e->next; + s = 0; + } + } + + return result; +} + +static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER) { const unsigned char *cursor, *limit, *marker, *start; zval *rval_ref; From e0f9fbdfa61012101de7f4a8653ca5538c404a71 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 10 Aug 2016 14:46:38 +0200 Subject: [PATCH 44/49] Bug #72663 - part 3 When using the php_serialize session serialization handler, do not use the result of the unserialization if it failed. --- ext/session/session.c | 9 ++++++++- ext/standard/tests/serialize/bug72663_3.phpt | 17 +++++++++++++++++ ext/wddx/wddx.c | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 ext/standard/tests/serialize/bug72663_3.phpt diff --git a/ext/session/session.c b/ext/session/session.c index 48cd0f1bdf4..85c72769131 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -905,12 +905,19 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize) /* {{{ */ const char *endptr = val + vallen; zval session_vars; php_unserialize_data_t var_hash; + int result; zend_string *var_name = zend_string_init("_SESSION", sizeof("_SESSION") - 1, 0); ZVAL_NULL(&session_vars); PHP_VAR_UNSERIALIZE_INIT(var_hash); - php_var_unserialize(&session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash); + result = php_var_unserialize( + &session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + if (!result) { + zval_ptr_dtor(&session_vars); + ZVAL_NULL(&session_vars); + } + if (!Z_ISUNDEF(PS(http_session_vars))) { zval_ptr_dtor(&PS(http_session_vars)); } diff --git a/ext/standard/tests/serialize/bug72663_3.phpt b/ext/standard/tests/serialize/bug72663_3.phpt new file mode 100644 index 00000000000..37d67706f2f --- /dev/null +++ b/ext/standard/tests/serialize/bug72663_3.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #72663 (3): If unserialization fails, don't initialize the session with the result +--SKIPIF-- + +--INI-- +session.serialize_handler=php_serialize +--FILE-- + +--EXPECTF-- +Notice: session_decode(): Unexpected end of serialized data in %s on line %d +array(0) { +} diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 08f9c4f37e7..b8b905d550e 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -1088,7 +1088,7 @@ int php_wddx_deserialize_ex(const char *value, size_t vallen, zval *return_value if (stack.top == 1) { wddx_stack_top(&stack, (void**)&ent); - if (IS_UNDEF(ent->data)) { + if (Z_ISUNDEF(ent->data)) { retval = FAILURE; } else { ZVAL_COPY(return_value, &ent->data); From ed9d916c28b042d276a28998f92eb7e6cc56025a Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Wed, 17 Aug 2016 01:12:33 -0700 Subject: [PATCH 45/49] fix test --- ext/session/tests/bug72681.phpt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/session/tests/bug72681.phpt b/ext/session/tests/bug72681.phpt index ca38b07fc90..ceca6ecc33f 100644 --- a/ext/session/tests/bug72681.phpt +++ b/ext/session/tests/bug72681.phpt @@ -6,7 +6,8 @@ Bug #72681: PHP Session Data Injection Vulnerability Date: Wed, 17 Aug 2016 16:54:21 +0800 Subject: [PATCH 46/49] Fixed bug #72853 (stream_set_blocking doesn't work) Implemented PHP_STREAM_OPTION_META_DATA_API for plain_wrappers --- NEWS | 3 ++ ext/standard/tests/streams/bug72853.phpt | 59 ++++++++++++++++++++++++ main/streams/plain_wrapper.c | 14 +++++- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/streams/bug72853.phpt diff --git a/NEWS b/NEWS index 1d5e5f8189e..fdaa671f978 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2016, PHP 5.6.26 +- Streams: + . Fixed bug #72853 (stream_set_blocking doesn't work). (Laruence) + - FTP: . Fixed bug #70195 (Cannot upload file using ftp_put to FTPES with require_ssl_reuse). (Benedict Singer) diff --git a/ext/standard/tests/streams/bug72853.phpt b/ext/standard/tests/streams/bug72853.phpt new file mode 100644 index 00000000000..48bd60e7a62 --- /dev/null +++ b/ext/standard/tests/streams/bug72853.phpt @@ -0,0 +1,59 @@ +--TEST-- +Bug #72853 (stream_set_blocking doesn't work) +--SKIPIF-- + +--FILE-- + array('pipe', 'r'), // stdin + 1 => array('pipe', 'w'), // stdout +); + +$p = proc_open("ls", $descs, $pipes, '.', NULL, NULL); + +stream_set_blocking($pipes[1], false); +var_dump(stream_get_meta_data($pipes[1])); +stream_set_blocking($pipes[1], true); +while ($outs = fgets($pipes[1], 1024)) { +} +var_dump(stream_get_meta_data($pipes[1])); +proc_close($p); +?> +--EXPECTF-- +array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(false) + ["eof"]=> + bool(false) + ["stream_type"]=> + string(5) "STDIO" + ["mode"]=> + string(1) "r" + ["unread_bytes"]=> + int(0) + ["seekable"]=> + bool(false) +} +array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(true) + ["stream_type"]=> + string(5) "STDIO" + ["mode"]=> + string(1) "r" + ["unread_bytes"]=> + int(0) + ["seekable"]=> + bool(false) +} diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index 55f744c55de..f472bad4b9e 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -818,7 +818,19 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void return ftruncate(fd, new_size) == 0 ? PHP_STREAM_OPTION_RETURN_OK : PHP_STREAM_OPTION_RETURN_ERR; } } - + case PHP_STREAM_OPTION_META_DATA_API: + if (fd == -1) + return -1; +#ifdef O_NONBLOCK + flags = fcntl(fd, F_GETFL, 0); + + add_assoc_bool((zval*)ptrparam, "timed_out", 0); + add_assoc_bool((zval*)ptrparam, "blocked", (flags & O_NONBLOCK)? 0 : 1); + add_assoc_bool((zval*)ptrparam, "eof", stream->eof); + + return PHP_STREAM_OPTION_RETURN_OK; +#endif + return -1; default: return PHP_STREAM_OPTION_RETURN_NOTIMPL; } From b172f43caa048861899e78eb56607cb5b60e5cfb Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 17 Aug 2016 16:56:20 +0800 Subject: [PATCH 47/49] Unused label --- ext/session/session.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/session/session.c b/ext/session/session.c index 85c72769131..8e5caf9bb33 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1115,7 +1115,6 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ PS_ADD_VARL(name); } } -skip: zend_string_release(name); p = q; From 1dab8e07f2e14221f534202e7d0c03600b3259eb Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 17 Aug 2016 16:56:58 +0800 Subject: [PATCH 48/49] Update NEWs --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 59d15e40b40..4353350652a 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,7 @@ PHP NEWS . Fixed bug #72278 (getimagesize returning FALSE on valid jpg). (cmb) - Streams: + . Fixed bug #72853 (stream_set_blocking doesn't work). (Laruence) . Fixed bug #72764 (ftps:// opendir wrapper data channel encryption fails with IIS FTP 7.5, 8.5). (vhuk) From 30e751fe5b1eb79114a07ac4d7ac1ea1e3ab74cf Mon Sep 17 00:00:00 2001 From: Xinchen Hui Date: Wed, 17 Aug 2016 17:14:53 +0800 Subject: [PATCH 49/49] Update NEWs --- NEWS | 1 + 1 file changed, 1 insertion(+) diff --git a/NEWS b/NEWS index 0e186ba627a..125c8bc28e9 100644 --- a/NEWS +++ b/NEWS @@ -55,6 +55,7 @@ PHP NEWS . Fixed bug #72278 (getimagesize returning FALSE on valid jpg). (cmb) - Stream: + . Fixed bug #72853 (stream_set_blocking doesn't work). (Laruence) . Fixed bug #72743 (Out-of-bound read in php_stream_filter_create). (Loianhtuan) . Implemented FR #27814 (Multiple small packets send for HTTP request).