diff options
-rw-r--r-- | NEWS | 6 | ||||
-rw-r--r-- | ext/fileinfo/libmagic.patch | 68 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 9 | ||||
-rw-r--r-- | ext/spl/spl_directory.c | 2 | ||||
-rw-r--r-- | ext/spl/spl_iterators.c | 2 | ||||
-rw-r--r-- | ext/spl/tests/bug67359.phpt | 28 | ||||
-rw-r--r-- | ext/spl/tests/bug67360.phpt | 34 | ||||
-rw-r--r-- | ext/standard/formatted_print.c | 6 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug67249.phpt | 8 |
9 files changed, 154 insertions, 9 deletions
@@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2014, PHP 5.6.0 Beta 4 +- Core: + . Fixed bug #67249 (printf out-of-bounds read). (Stas) + - Date: . Fixed bug #67308 (Serialize of DateTime truncates fractions of second). (Adam) @@ -11,6 +14,9 @@ PHP NEWS . Fixed bug #67328 (fileinfo: fileinfo: numerous file_printf calls resulting in performance degradation). +- SPL: + . Fixed bug #67359 (Segfault in recursiveDirectoryIterator). (Laruence) + 15 May 2014, PHP 5.6.0 Beta 3 - Core: diff --git a/ext/fileinfo/libmagic.patch b/ext/fileinfo/libmagic.patch index 662537bf7f..bb9a0dafae 100644 --- a/ext/fileinfo/libmagic.patch +++ b/ext/fileinfo/libmagic.patch @@ -822,7 +822,7 @@ diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c } diff -u libmagic.orig/cdf.c libmagic/cdf.c --- libmagic.orig/cdf.c Tue Feb 26 17:20:42 2013 -+++ libmagic/cdf.c Fri Feb 21 00:21:27 2014 ++++ libmagic/cdf.c Tue May 27 22:28:51 2014 @@ -43,7 +43,17 @@ #include <err.h> #endif @@ -853,7 +853,63 @@ diff -u libmagic.orig/cdf.c libmagic/cdf.c return -1; return (ssize_t)len; -@@ -1132,7 +1145,7 @@ +@@ -810,6 +823,10 @@ + i, inp[i].pi_id, inp[i].pi_type, q - p, offs)); + if (inp[i].pi_type & CDF_VECTOR) { + nelements = CDF_GETUINT32(q, 1); ++ if (nelements == 0) { ++ DPRINTF(("CDF_VECTOR with nelements == 0\n")); ++ goto out; ++ } + o = 2; + } else { + nelements = 1; +@@ -884,7 +901,9 @@ + } + DPRINTF(("nelements = %" SIZE_T_FORMAT "u\n", + nelements)); +- for (j = 0; j < nelements; j++, i++) { ++ for (j = 0; j < nelements && i < sh.sh_properties; ++ j++, i++) ++ { + uint32_t l = CDF_GETUINT32(q, o); + inp[i].pi_str.s_len = l; + inp[i].pi_str.s_buf = (const char *) +@@ -929,7 +948,7 @@ + cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, + cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count) + { +- size_t i, maxcount; ++ size_t maxcount; + const cdf_summary_info_header_t *si = + CAST(const cdf_summary_info_header_t *, sst->sst_tab); + const cdf_section_declaration_t *sd = +@@ -944,21 +963,13 @@ + ssi->si_os = CDF_TOLE2(si->si_os); + ssi->si_class = si->si_class; + cdf_swap_class(&ssi->si_class); +- ssi->si_count = CDF_TOLE2(si->si_count); ++ ssi->si_count = CDF_TOLE4(si->si_count); + *count = 0; + maxcount = 0; + *info = NULL; +- for (i = 0; i < CDF_TOLE4(si->si_count); i++) { +- if (i >= CDF_LOOP_LIMIT) { +- DPRINTF(("Unpack summary info loop limit")); +- errno = EFTYPE; +- return -1; +- } +- if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset), +- info, count, &maxcount) == -1) { ++ if (cdf_read_property_info(sst, h, CDF_TOLE4(sd->sd_offset), info, ++ count, &maxcount) == -1) + return -1; +- } +- } + return 0; + } + +@@ -1132,7 +1143,7 @@ cdf_directory_t *d; char name[__arraycount(d->d_name)]; cdf_stream_t scn; @@ -862,7 +918,7 @@ diff -u libmagic.orig/cdf.c libmagic/cdf.c static const char *types[] = { "empty", "user storage", "user stream", "lockbytes", "property", "root storage" }; -@@ -1185,7 +1198,7 @@ +@@ -1185,7 +1196,7 @@ cdf_dump_property_info(const cdf_property_info_t *info, size_t count) { cdf_timestamp_t tp; @@ -871,7 +927,7 @@ diff -u libmagic.orig/cdf.c libmagic/cdf.c char buf[64]; size_t i, j; -@@ -1229,7 +1242,11 @@ +@@ -1229,7 +1240,11 @@ break; case CDF_FILETIME: tp = info[i].pi_tp; @@ -885,7 +941,7 @@ diff -u libmagic.orig/cdf.c libmagic/cdf.c } else { diff -u libmagic.orig/cdf.h libmagic/cdf.h --- libmagic.orig/cdf.h Thu Jun 21 00:19:55 2012 -+++ libmagic/cdf.h Fri Feb 21 00:21:27 2014 ++++ libmagic/cdf.h Tue May 27 22:28:51 2014 @@ -35,10 +35,12 @@ #ifndef _H_CDF_ #define _H_CDF_ @@ -2543,7 +2599,7 @@ diff -u libmagic.orig/print.c libmagic/print.c } diff -u libmagic.orig/readcdf.c libmagic/readcdf.c --- libmagic.orig/readcdf.c Tue Jan 7 04:13:42 2014 -+++ libmagic/readcdf.c Thu Apr 24 20:07:51 2014 ++++ libmagic/readcdf.c Tue May 27 22:28:51 2014 @@ -30,7 +30,11 @@ #endif diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 01ee1e2d01..899516eca8 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -931,7 +931,14 @@ static int spl_array_skip_protected(spl_array_object *intern, HashTable *aht TSR if (Z_TYPE_P(intern->array) == IS_OBJECT) { do { if (zend_hash_get_current_key_ex(aht, &string_key, &string_length, &num_key, 0, &intern->pos) == HASH_KEY_IS_STRING) { - if (!string_length || string_key[0]) { + /* zend_hash_get_current_key_ex() should never set + * string_length to 0 when returning HASH_KEY_IS_STRING, but we + * may as well be defensive and consider that successful. + * Beyond that, we're looking for protected keys (which will + * have a null byte at string_key[0]), but want to avoid + * skipping completely empty keys (which will also have the + * null byte, but a string_length of 1). */ + if (!string_length || string_key[0] || string_length == 1) { return SUCCESS; } } else { diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 1033d48aa7..151da4b724 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -830,6 +830,7 @@ SPL_METHOD(DirectoryIterator, seek) zend_call_method_with_0_params(&this_ptr, Z_OBJCE_P(getThis()), &intern->u.dir.func_rewind, "rewind", &retval); if (retval) { zval_ptr_dtor(&retval); + retval = NULL; } } @@ -839,6 +840,7 @@ SPL_METHOD(DirectoryIterator, seek) if (retval) { valid = zend_is_true(retval); zval_ptr_dtor(&retval); + retval = NULL; } if (!valid) { break; diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 4be7631205..9437ac7707 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -848,6 +848,8 @@ static union _zend_function *spl_recursive_it_get_method(zval **object_ptr, char *object_ptr = zobj; function_handler = Z_OBJ_HT_P(*object_ptr)->get_method(object_ptr, method, method_len, key TSRMLS_CC); } + } else { + *object_ptr = zobj; } } return function_handler; diff --git a/ext/spl/tests/bug67359.phpt b/ext/spl/tests/bug67359.phpt new file mode 100644 index 0000000000..e2e61133f3 --- /dev/null +++ b/ext/spl/tests/bug67359.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #67359 (Segfault in recursiveDirectoryIterator) +--FILE-- +<?php +try +{ + $rdi = new recursiveDirectoryIterator(dirname(__FILE__), FilesystemIterator::SKIP_DOTS | FilesystemIterator::UNIX_PATHS); + $it = new recursiveIteratorIterator( $rdi ); + $it->seek(1); + while( $it->valid()) + { + if( $it->isFile() ) + { + $it->current(); + } + + $it->next(); + } + + $it->current(); +} +catch(Exception $e) +{ +} +echo "okey" +?> +--EXPECTF-- +okey diff --git a/ext/spl/tests/bug67360.phpt b/ext/spl/tests/bug67360.phpt new file mode 100644 index 0000000000..552c02ad74 --- /dev/null +++ b/ext/spl/tests/bug67360.phpt @@ -0,0 +1,34 @@ +--TEST-- +Bug #67360 (Missing element after ArrayObject::getIterator) +--FILE-- +<?php + +$array = array('' => 1, 1 => 2, 3 => 4); +$ArrayObject = new ArrayObject($array); +var_dump($ArrayObject); +$Iterator = $ArrayObject->getIterator(); +var_dump(count($Iterator) === count($array)); +var_dump(iterator_to_array($Iterator)); + +?> +--EXPECTF-- +object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(3) { + [""]=> + int(1) + [1]=> + int(2) + [3]=> + int(4) + } +} +bool(true) +array(3) { + [""]=> + int(1) + [1]=> + int(2) + [3]=> + int(4) +} diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c index 44ee9b61f8..727de705ff 100644 --- a/ext/standard/formatted_print.c +++ b/ext/standard/formatted_print.c @@ -374,6 +374,7 @@ php_formatted_print(int ht, php_size_t *len, int use_array, int format_offset TS int alignment, currarg, adjusting, argnum, width, precision; char *format, *result, padding; int always_sign; + int format_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &args, &argc) == FAILURE) { return NULL; @@ -412,11 +413,12 @@ php_formatted_print(int ht, php_size_t *len, int use_array, int format_offset TS convert_to_string_ex(args[format_offset]); format = Z_STRVAL_PP(args[format_offset]); + format_len = Z_STRLEN_PP(args[format_offset]); result = emalloc(size); currarg = 1; - while (inpos<Z_STRSIZE_PP(args[format_offset])) { + while (inpos<format_len) { int expprec = 0, multiuse = 0; zval *tmp; @@ -471,7 +473,7 @@ php_formatted_print(int ht, php_size_t *len, int use_array, int format_offset TS /* space padding, the default */ } else if (format[inpos] == '+') { always_sign = 1; - } else if (format[inpos] == '\'') { + } else if (format[inpos] == '\'' && inpos+1<format_len) { padding = format[++inpos]; } else { PRINTF_DEBUG(("sprintf: end of modifiers\n")); diff --git a/ext/standard/tests/strings/bug67249.phpt b/ext/standard/tests/strings/bug67249.phpt new file mode 100644 index 0000000000..6ea75289e6 --- /dev/null +++ b/ext/standard/tests/strings/bug67249.phpt @@ -0,0 +1,8 @@ +--TEST-- +Bug #67249 (printf out-of-bounds read) +--FILE-- +<?php +var_dump(sprintf("%'", "foo")); +?> +--EXPECT-- +string(0) "" |