diff options
author | Stanislav Malyshev <stas@php.net> | 2015-08-04 15:29:13 -0700 |
---|---|---|
committer | Ferenc Kovacs <tyrael@php.net> | 2015-08-06 08:52:09 +0200 |
commit | 7e254ac00ea88a5e6f585fb089c240e88d99b506 (patch) | |
tree | d2fb1e6b4d555430f1223909602ff109a57fdab1 | |
parent | a3423aae54d1bb02849e6d9a514b266d01274a64 (diff) | |
download | php-git-7e254ac00ea88a5e6f585fb089c240e88d99b506.tar.gz |
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5:
update NEWS
fix test
update NEWS
Fix bug #70019 - limit extracted files to given directory
Do not do convert_to_* on unserialize, it messes up references
Fix #69793 - limit what we accept when unserializing exception
Fixed bug #70169 (Use After Free Vulnerability in unserialize() with SplDoublyLinkedList)
Fixed bug #70166 - Use After Free Vulnerability in unserialize() with SPLArrayObject
ignore signatures for packages too
Fix bug #70168 - Use After Free Vulnerability in unserialize() with SplObjectStorage
Fixed bug #69892
Fix bug #70014 - use RAND_bytes instead of deprecated RAND_pseudo_bytes
Improved fix for Bug #69441
Fix bug #70068 (Dangling pointer in the unserialization of ArrayObject items)
Fix bug #70121 (unserialize() could lead to unexpected methods execution / NULL pointer deref)
Fix bug #70081: check types for SOAP variables
Conflicts:
ext/soap/php_http.c
ext/spl/spl_observer.c
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Zend/tests/bug70121.phpt | 9 | ||||
-rw-r--r-- | Zend/zend_exceptions.c | 45 | ||||
-rw-r--r-- | ext/date/php_date.c | 130 | ||||
-rw-r--r-- | ext/date/tests/bug53437_var3.phpt | 12 | ||||
-rw-r--r-- | ext/date/tests/bug53437_var5.phpt | 12 | ||||
-rw-r--r-- | ext/openssl/openssl.c | 6 | ||||
-rw-r--r-- | ext/phar/phar_internal.h | 13 | ||||
-rw-r--r-- | ext/phar/phar_object.c | 50 | ||||
-rw-r--r-- | ext/phar/tests/bug70019.phpt | 22 | ||||
-rw-r--r-- | ext/phar/tests/bug70019.zip | bin | 0 -> 184 bytes | |||
-rw-r--r-- | ext/soap/php_http.c | 23 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 11 | ||||
-rw-r--r-- | ext/spl/spl_dllist.c | 25 | ||||
-rw-r--r-- | ext/spl/spl_observer.c | 62 | ||||
-rw-r--r-- | ext/spl/tests/bug70068.phpt | 9 | ||||
-rw-r--r-- | ext/spl/tests/bug70166.phpt | 29 | ||||
-rw-r--r-- | ext/spl/tests/bug70168.phpt | 36 | ||||
-rw-r--r-- | ext/spl/tests/bug70169.phpt | 30 | ||||
-rw-r--r-- | ext/standard/tests/serialize/bug69152.phpt | 1 | ||||
-rw-r--r-- | ext/standard/tests/serialize/bug69793.phpt | 17 | ||||
-rw-r--r-- | sapi/cli/tests/005.phpt | 11 |
22 files changed, 403 insertions, 153 deletions
diff --git a/.gitignore b/.gitignore index 7f4f814050..e69463a240 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,9 @@ *.tar.gz *.tar.bz2 *.tar.xz +*.tar.gz.asc +*.tar.bz2.asc +*.tar.xz.asc .FBCIndex .FBCLockFolder .deps diff --git a/Zend/tests/bug70121.phpt b/Zend/tests/bug70121.phpt new file mode 100644 index 0000000000..9f8b7d6055 --- /dev/null +++ b/Zend/tests/bug70121.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bug #70121 (unserialize() could lead to unexpected methods execution / NULL pointer deref) +--FILE-- +<?php +unserialize('O:12:"DateInterval":1:{s:4:"days";O:9:"Exception":7:{s:10:"'."\0".'*'."\0".'message";s:1:"x";s:17:"'."\0".'Exception'."\0".'string";s:1:"A";s:7:"'."\0".'*'."\0".'code";i:0;s:7:"'."\0".'*'."\0".'file";s:1:"a";s:7:"'."\0".'*'."\0".'line";i:1337;s:16:"'."\0".'Exception'."\0".'trace";a:0:{}s:19:"'."\0".'Exception'."\0".'previous";O:8:"stdClass":0:{}}}'); +?> +OK +--EXPECT-- +OK diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index f7eac9212c..806c2ef9e3 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -41,7 +41,7 @@ void zend_exception_set_previous(zval *exception, zval *add_previous TSRMLS_DC) if (exception == add_previous || !add_previous || !exception) { return; } - if (Z_TYPE_P(add_previous) != IS_OBJECT && !instanceof_function(Z_OBJCE_P(add_previous), default_exception_ce TSRMLS_CC)) { + if (Z_TYPE_P(add_previous) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(add_previous), default_exception_ce TSRMLS_CC)) { zend_error(E_ERROR, "Cannot set non exception as previous exception"); return; } @@ -218,6 +218,33 @@ ZEND_METHOD(exception, __construct) } /* }}} */ +/* {{{ proto Exception::__wakeup() + Exception unserialize checks */ +#define CHECK_EXC_TYPE(name, type) \ + value = zend_read_property(default_exception_ce, object, name, sizeof(name)-1, 0 TSRMLS_CC); \ + if(value && Z_TYPE_P(value) != type) { \ + zval *tmp; \ + MAKE_STD_ZVAL(tmp); \ + ZVAL_STRINGL(tmp, name, sizeof(name)-1, 1); \ + Z_OBJ_HANDLER_P(object, unset_property)(object, tmp, 0 TSRMLS_CC); \ + zval_ptr_dtor(&tmp); \ + } + +ZEND_METHOD(exception, __wakeup) +{ + zval *value; + zval *object = getThis(); + HashTable *intern_ht = zend_std_get_properties(getThis() TSRMLS_CC); + CHECK_EXC_TYPE("message", IS_STRING); + CHECK_EXC_TYPE("string", IS_STRING); + CHECK_EXC_TYPE("code", IS_LONG); + CHECK_EXC_TYPE("file", IS_STRING); + CHECK_EXC_TYPE("line", IS_LONG); + CHECK_EXC_TYPE("trace", IS_ARRAY); + CHECK_EXC_TYPE("previous", IS_OBJECT); +} +/* }}} */ + /* {{{ proto ErrorException::__construct(string message, int code, int severity [, string filename [, int lineno [, Exception previous]]]) ErrorException constructor */ ZEND_METHOD(error_exception, __construct) @@ -586,7 +613,7 @@ ZEND_METHOD(exception, getTraceAsString) int res_len = 0, *len = &res_len, num = 0; DEFAULT_0_PARAMS; - + trace = zend_read_property(default_exception_ce, getThis(), "trace", sizeof("trace")-1, 1 TSRMLS_CC); if (Z_TYPE_P(trace) != IS_ARRAY) { RETURN_FALSE; @@ -602,8 +629,8 @@ ZEND_METHOD(exception, getTraceAsString) TRACE_APPEND_STRL(s_tmp, strlen(s_tmp)); efree(s_tmp); - res[res_len] = '\0'; - RETURN_STRINGL(res, res_len, 0); + res[res_len] = '\0'; + RETURN_STRINGL(res, res_len, 0); } /* }}} */ @@ -640,15 +667,15 @@ ZEND_METHOD(exception, __toString) int len = 0; zend_fcall_info fci; zval fname; - + DEFAULT_0_PARAMS; - + str = estrndup("", 0); exception = getThis(); ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 1); - while (exception && Z_TYPE_P(exception) == IS_OBJECT) { + while (exception && Z_TYPE_P(exception) == IS_OBJECT && instanceof_function(Z_OBJCE_P(exception), default_exception_ce TSRMLS_CC)) { prev_str = str; _default_exception_get_entry(exception, "message", sizeof("message")-1, &message TSRMLS_CC); _default_exception_get_entry(exception, "file", sizeof("file")-1, &file TSRMLS_CC); @@ -658,6 +685,7 @@ ZEND_METHOD(exception, __toString) convert_to_string(&file); convert_to_long(&line); + trace = NULL; fci.size = sizeof(fci); fci.function_table = &Z_OBJCE_P(exception)->function_table; fci.function_name = &fname; @@ -670,7 +698,7 @@ ZEND_METHOD(exception, __toString) zend_call_function(&fci, NULL TSRMLS_CC); - if (Z_TYPE_P(trace) != IS_STRING) { + if (trace && Z_TYPE_P(trace) != IS_STRING) { zval_ptr_dtor(&trace); trace = NULL; } @@ -727,6 +755,7 @@ ZEND_END_ARG_INFO() const static zend_function_entry default_exception_functions[] = { ZEND_ME(exception, __clone, NULL, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL) ZEND_ME(exception, __construct, arginfo_exception___construct, ZEND_ACC_PUBLIC) + ZEND_ME(exception, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getMessage, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getCode, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) ZEND_ME(exception, getFile, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 6169f40690..2e3b3fdf11 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -601,7 +601,7 @@ static zend_object_handlers date_object_handlers_period; #define DATE_SET_CONTEXT \ zval *object; \ object = getThis(); \ - + #define DATE_FETCH_OBJECT \ php_date_obj *obj; \ DATE_SET_CONTEXT; \ @@ -770,7 +770,7 @@ PHP_RSHUTDOWN_FUNCTION(date) * RFC2822, Section 3.3: http://www.ietf.org/rfc/rfc2822.txt * FWS = ([*WSP CRLF] 1*WSP) / ; Folding white space * CFWS = *([FWS] comment) (([FWS] comment) / FWS) - * + * * date-time = [ day-of-week "," ] date FWS time [CFWS] * day-of-week = ([FWS] day-name) * day-name = "Mon" / "Tue" / "Wed" / "Thu" / "Fri" / "Sat" / "Sun" @@ -792,19 +792,19 @@ PHP_RSHUTDOWN_FUNCTION(date) * date-fullyear = 4DIGIT * date-month = 2DIGIT ; 01-12 * date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year - * + * * time-hour = 2DIGIT ; 00-23 * time-minute = 2DIGIT ; 00-59 * time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules - * + * * time-secfrac = "." 1*DIGIT * time-numoffset = ("+" / "-") time-hour ":" time-minute * time-offset = "Z" / time-numoffset - * + * * partial-time = time-hour ":" time-minute ":" time-second [time-secfrac] * full-date = date-fullyear "-" date-month "-" date-mday * full-time = partial-time time-offset - * + * * date-time = full-date "T" full-time */ #define DATE_FORMAT_RFC3339 "Y-m-d\\TH:i:sP" @@ -897,7 +897,7 @@ PHP_MSHUTDOWN_FUNCTION(date) PHP_MINFO_FUNCTION(date) { const timelib_tzdb *tzdb = DATE_TIMEZONEDB; - + php_info_print_table_start(); php_info_print_table_row(2, "date/time support", "enabled"); php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version); @@ -1049,8 +1049,8 @@ char *php_date_full_day_name(timelib_sll y, timelib_sll m, timelib_sll d) timelib_sll day_of_week = timelib_day_of_week(y, m, d); if (day_of_week < 0) { return "Unknown"; - } - return day_full_names[day_of_week]; + } + return day_full_names[day_of_week]; } char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d) @@ -1058,8 +1058,8 @@ char *php_date_short_day_name(timelib_sll y, timelib_sll m, timelib_sll d) timelib_sll day_of_week = timelib_day_of_week(y, m, d); if (day_of_week < 0) { return "Unknown"; - } - return day_short_names[day_of_week]; + } + return day_short_names[day_of_week]; } /* }}} */ @@ -1091,7 +1091,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca offset->leap_secs = 0; offset->is_dst = 0; offset->abbr = malloc(9); /* GMT�xxxx\0 */ - snprintf(offset->abbr, 9, "GMT%c%02d%02d", + snprintf(offset->abbr, 9, "GMT%c%02d%02d", localtime ? ((offset->offset < 0) ? '-' : '+') : '+', localtime ? abs(offset->offset / 3600) : 0, localtime ? abs((offset->offset % 3600) / 60) : 0 ); @@ -1137,7 +1137,7 @@ static char *date_format(char *format, int format_len, timelib_time *t, int loca case 'a': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "pm" : "am"); break; case 'A': length = slprintf(buffer, 32, "%s", t->h >= 12 ? "PM" : "AM"); break; case 'B': { - int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); + int retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); while (retval < 0) { retval += 1000; } @@ -1237,7 +1237,7 @@ static void php_date(INTERNAL_FUNCTION_PARAMETERS, int localtime) } string = php_format_date(format, format_len, ts, localtime TSRMLS_CC); - + RETVAL_STRING(string, 0); } /* }}} */ @@ -1261,7 +1261,7 @@ PHPAPI char *php_format_date(char *format, int format_len, time_t ts, int localt } string = date_format(format, format_len, t, localtime); - + timelib_time_dtor(t); return string; } @@ -1302,7 +1302,7 @@ PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC) offset->leap_secs = 0; offset->is_dst = t->dst; offset->abbr = malloc(9); /* GMT�xxxx\0 */ - snprintf(offset->abbr, 9, "GMT%c%02d%02d", + snprintf(offset->abbr, 9, "GMT%c%02d%02d", !localtime ? ((offset->offset < 0) ? '-' : '+') : '+', !localtime ? abs(offset->offset / 3600) : 0, !localtime ? abs((offset->offset % 3600) / 60) : 0 ); @@ -1334,7 +1334,7 @@ PHPAPI int php_idate(char format, time_t ts, int localtime TSRMLS_DC) /* Swatch Beat a.k.a. Internet Time */ case 'B': - retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); + retval = (((((long)t->sse)-(((long)t->sse) - ((((long)t->sse) % 86400) + 3600))) * 10) / 864); while (retval < 0) { retval += 1000; } @@ -1386,7 +1386,7 @@ PHP_FUNCTION(idate) char *format; int format_len; long ts = 0; - int ret; + int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &format, &format_len, &ts) == FAILURE) { RETURN_FALSE; @@ -1414,7 +1414,7 @@ PHP_FUNCTION(idate) PHPAPI void php_date_set_tzdb(timelib_tzdb *tzdb) { const timelib_tzdb *builtin = timelib_builtin_db(); - + if (php_version_compare(tzdb->version, builtin->version) > 0) { php_date_global_timezone_db = tzdb; php_date_global_timezone_db_enabled = 1; @@ -1485,7 +1485,7 @@ PHP_FUNCTION(strtotime) } if (!time_len) { - timelib_time_dtor(now); + timelib_time_dtor(now); RETURN_FALSE; } @@ -1934,7 +1934,7 @@ static void date_period_it_current_data(zend_object_iterator *iter, zval ***data if (it_time->tz_info) { newdateobj->time->tz_info = it_time->tz_info; } - + *data = &iterator->current; } /* }}} */ @@ -2128,13 +2128,13 @@ static inline zend_object_value date_object_new_date_ex(zend_class_entry *class_ if (ptr) { *ptr = intern; } - + zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_date, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_date; - + return retval; } @@ -2148,12 +2148,12 @@ static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC) php_date_obj *new_obj = NULL; php_date_obj *old_obj = (php_date_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); zend_object_value new_ov = date_object_new_date_ex(old_obj->std.ce, &new_obj TSRMLS_CC); - + zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); if (!old_obj->time) { return new_ov; } - + /* this should probably moved to a new `timelib_time *timelime_time_clone(timelib_time *)` */ new_obj->time = timelib_time_ctor(); *new_obj->time = *old_obj->time; @@ -2163,7 +2163,7 @@ static zend_object_value date_object_clone_date(zval *this_ptr TSRMLS_DC) if (old_obj->time->tz_info) { new_obj->time->tz_info = old_obj->time->tz_info; } - + return new_ov; } @@ -2280,10 +2280,10 @@ static inline zend_object_value date_object_new_timezone_ex(zend_class_entry *cl zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_timezone, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_timezone; - + return retval; } @@ -2297,12 +2297,12 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC) php_timezone_obj *new_obj = NULL; php_timezone_obj *old_obj = (php_timezone_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); zend_object_value new_ov = date_object_new_timezone_ex(old_obj->std.ce, &new_obj TSRMLS_CC); - + zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); if (!old_obj->initialized) { return new_ov; } - + new_obj->type = old_obj->type; new_obj->initialized = 1; switch (new_obj->type) { @@ -2318,7 +2318,7 @@ static zend_object_value date_object_clone_timezone(zval *this_ptr TSRMLS_DC) new_obj->tzi.z.abbr = strdup(old_obj->tzi.z.abbr); break; } - + return new_ov; } @@ -2379,10 +2379,10 @@ static inline zend_object_value date_object_new_interval_ex(zend_class_entry *cl zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_interval, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_interval; - + return retval; } @@ -2396,7 +2396,7 @@ static zend_object_value date_object_clone_interval(zval *this_ptr TSRMLS_DC) php_interval_obj *new_obj = NULL; php_interval_obj *old_obj = (php_interval_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); zend_object_value new_ov = date_object_new_interval_ex(old_obj->std.ce, &new_obj TSRMLS_CC); - + zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); /** FIX ME ADD CLONE STUFF **/ @@ -2468,10 +2468,10 @@ static inline zend_object_value date_object_new_period_ex(zend_class_entry *clas zend_object_std_init(&intern->std, class_type TSRMLS_CC); object_properties_init(&intern->std, class_type); - + retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) date_object_free_storage_period, NULL TSRMLS_CC); retval.handlers = &date_object_handlers_period; - + return retval; } @@ -2485,7 +2485,7 @@ static zend_object_value date_object_clone_period(zval *this_ptr TSRMLS_DC) php_period_obj *new_obj = NULL; php_period_obj *old_obj = (php_period_obj *) zend_object_store_get_object(this_ptr TSRMLS_CC); zend_object_value new_ov = date_object_new_period_ex(old_obj->std.ce, &new_obj TSRMLS_CC); - + zend_objects_clone_members(&new_obj->std, new_ov, &old_obj->std, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC); /** FIX ME ADD CLONE STUFF **/ @@ -2571,7 +2571,7 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str, int type = TIMELIB_ZONETYPE_ID, new_dst = 0; char *new_abbr = NULL; timelib_sll new_offset; - + if (dateobj->time) { timelib_time_dtor(dateobj->time); } @@ -2970,7 +2970,7 @@ void php_date_do_return_parsed_time(INTERNAL_FUNCTION_PARAMETERS, timelib_time * PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(hour, h); PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(minute, i); PHP_DATE_PARSE_DATE_SET_TIME_ELEMENT(second, s); - + if (parsed_time->f == -99999) { add_assoc_bool(return_value, "fraction", 0); } else { @@ -3037,7 +3037,7 @@ PHP_FUNCTION(date_parse) int date_len; struct timelib_error_container *error; timelib_time *parsed_time; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &date, &date_len) == FAILURE) { RETURN_FALSE; } @@ -3056,7 +3056,7 @@ PHP_FUNCTION(date_parse_from_format) int date_len, format_len; struct timelib_error_container *error; timelib_time *parsed_time; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &format, &format_len, &date, &date_len) == FAILURE) { RETURN_FALSE; } @@ -3540,7 +3540,7 @@ static void php_date_isodate_set(zval *object, long y, long w, long d, zval *ret memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative)); dateobj->time->relative.d = timelib_daynr_from_weeknr(y, w, d); dateobj->time->have_relative = 1; - + timelib_update_ts(dateobj->time, NULL); } @@ -3729,7 +3729,7 @@ PHP_METHOD(DateTimeZone, __construct) int tz_len; php_timezone_obj *tzobj; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &tz, &tz_len)) { tzobj = zend_object_store_get_object(getThis() TSRMLS_CC); @@ -4007,7 +4007,7 @@ static int date_interval_initialize(timelib_rel_time **rt, /*const*/ char *forma struct timelib_error_container *errors; timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors); - + if (errors->error_count > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format); retval = FAILURE; @@ -4166,7 +4166,7 @@ PHP_METHOD(DateInterval, __construct) php_interval_obj *diobj; timelib_rel_time *reltime; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &interval_string, &interval_string_length) == SUCCESS) { if (date_interval_initialize(&reltime, interval_string, interval_string_length TSRMLS_CC) == SUCCESS) { @@ -4189,8 +4189,7 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter #define PHP_DATE_INTERVAL_READ_PROPERTY(element, member, itype, def) \ do { \ zval **z_arg = NULL; \ - if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \ - convert_to_long(*z_arg); \ + if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS && Z_TYPE_PP(z_arg) == IS_LONG) { \ (*intobj)->diff->member = (itype)Z_LVAL_PP(z_arg); \ } else { \ (*intobj)->diff->member = (itype)def; \ @@ -4201,8 +4200,15 @@ static int php_date_interval_initialize_from_hash(zval **return_value, php_inter do { \ zval **z_arg = NULL; \ if (zend_hash_find(myht, element, strlen(element) + 1, (void**) &z_arg) == SUCCESS) { \ - convert_to_string(*z_arg); \ - DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \ + if (Z_TYPE_PP(z_arg) == IS_STRING) { \ + DATE_A64I((*intobj)->diff->member, Z_STRVAL_PP(z_arg)); \ + } else if (Z_TYPE_PP(z_arg) == IS_LONG || Z_TYPE_PP(z_arg) == IS_BOOL) { \ + (*intobj)->diff->member = (timelib_sll)Z_LVAL_PP(z_arg); \ + } else if (Z_TYPE_PP(z_arg) == IS_DOUBLE) { \ + (*intobj)->diff->member = (timelib_sll)Z_DVAL_PP(z_arg); \ + } else { \ + (*intobj)->diff->member = -1LL; \ + } \ } else { \ (*intobj)->diff->member = -1LL; \ } \ @@ -4380,7 +4386,7 @@ static int date_period_initialize(timelib_time **st, timelib_time **et, timelib_ struct timelib_error_container *errors; timelib_strtointerval(format, format_length, &b, &e, &p, &r, &errors); - + if (errors->error_count > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown or bad format (%s)", format); retval = FAILURE; @@ -4409,7 +4415,7 @@ PHP_METHOD(DatePeriod, __construct) int isostr_len = 0; timelib_time *clone; zend_error_handling error_handling; - + zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC); if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOl|l", &start, date_ce_interface, &interval, date_ce_interval, &recurrences, &options) == FAILURE) { if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "OOO|l", &start, date_ce_interface, &interval, date_ce_interval, &end, date_ce_interface, &options) == FAILURE) { @@ -4599,7 +4605,7 @@ PHP_FUNCTION(timezone_identifiers_list) tzdb = DATE_TIMEZONEDB; item_count = tzdb->index_size; table = tzdb->index; - + array_init(return_value); for (i = 0; i < item_count; ++i) { @@ -4633,7 +4639,7 @@ PHP_FUNCTION(timezone_abbreviations_list) { const timelib_tz_lookup_table *table, *entry; zval *element, **abbr_array_pp, *abbr_array; - + table = timelib_timezone_abbreviations_list(); array_init(return_value); entry = table; @@ -4709,11 +4715,11 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su timelib_time *t; timelib_tzinfo *tzi; char *retstr; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|ldddd", &time, &retformat, &latitude, &longitude, &zenith, &gmt_offset) == FAILURE) { RETURN_FALSE; } - + switch (ZEND_NUM_ARGS()) { case 1: retformat = SUNFUNCS_RET_STRING; @@ -4757,7 +4763,7 @@ static void php_do_date_sunrise_sunset(INTERNAL_FUNCTION_PARAMETERS, int calc_su timelib_unixtime2local(t, time); rs = timelib_astro_rise_set_altitude(t, longitude, latitude, altitude, 1, &h_rise, &h_set, &rise, &set, &transit); timelib_time_dtor(t); - + if (rs != 0) { RETURN_FALSE; } @@ -4811,7 +4817,7 @@ PHP_FUNCTION(date_sun_info) timelib_sll rise, set, transit; int dummy; double ddummy; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ldd", &time, &latitude, &longitude) == FAILURE) { RETURN_FALSE; } @@ -4825,7 +4831,7 @@ PHP_FUNCTION(date_sun_info) /* Setup */ t2 = timelib_time_ctor(); array_init(return_value); - + /* Get sun up/down and transit */ rs = timelib_astro_rise_set_altitude(t, longitude, latitude, -35.0/60, 1, &ddummy, &ddummy, &rise, &set, &transit); switch (rs) { @@ -4969,7 +4975,7 @@ static HashTable *date_object_get_properties_period(zval *object TSRMLS_DC) ZVAL_NULL(zv); } zend_hash_update(props, "interval", sizeof("interval"), &zv, sizeof(zv), NULL); - + /* converted to larger type (int->long); must check when unserializing */ MAKE_STD_ZVAL(zv); ZVAL_LONG(zv, (long) period_obj->recurrences); @@ -5052,7 +5058,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash } period_obj->initialized = 1; - + return 1; } @@ -5069,7 +5075,7 @@ PHP_METHOD(DatePeriod, __set_state) } myht = Z_ARRVAL_P(array); - + object_init_ex(return_value, date_ce_period); period_obj = zend_object_store_get_object(return_value TSRMLS_CC); if (!php_date_period_initialize_from_hash(period_obj, myht TSRMLS_CC)) { diff --git a/ext/date/tests/bug53437_var3.phpt b/ext/date/tests/bug53437_var3.phpt index 82b90f559b..d3a0652ee6 100644 --- a/ext/date/tests/bug53437_var3.phpt +++ b/ext/date/tests/bug53437_var3.phpt @@ -14,17 +14,17 @@ var_dump($di); --EXPECTF-- object(DateInterval)#%d (15) { ["y"]=> - int(2) + int(-1) ["m"]=> - int(0) + int(-1) ["d"]=> - int(0) + int(-1) ["h"]=> - int(6) + int(-1) ["i"]=> - int(8) + int(-1) ["s"]=> - int(0) + int(-1) ["weekday"]=> int(10) ["weekday_behavior"]=> diff --git a/ext/date/tests/bug53437_var5.phpt b/ext/date/tests/bug53437_var5.phpt index e95fcdae96..e9b3a3cd82 100644 --- a/ext/date/tests/bug53437_var5.phpt +++ b/ext/date/tests/bug53437_var5.phpt @@ -14,17 +14,17 @@ var_dump($di); --EXPECTF-- object(DateInterval)#%d (15) { ["y"]=> - int(2) + int(-1) ["m"]=> - int(0) + int(-1) ["d"]=> - int(0) + int(-1) ["h"]=> - int(6) + int(-1) ["i"]=> - int(8) + int(-1) ["s"]=> - int(0) + int(-1) ["weekday"]=> int(10) ["weekday_behavior"]=> diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 58ca098bcf..ef5162283b 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5390,7 +5390,6 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) long buffer_length; unsigned char *buffer = NULL; zval *zstrong_result_returned = NULL; - int strong_result = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) { return; @@ -5408,7 +5407,6 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) buffer = emalloc(buffer_length + 1); #ifdef PHP_WIN32 - strong_result = 1; /* random/urandom equivalent on Windows */ if (php_win32_get_random_bytes(buffer, (size_t) buffer_length) == FAILURE){ efree(buffer); @@ -5418,7 +5416,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) RETURN_FALSE; } #else - if ((strong_result = RAND_pseudo_bytes(buffer, buffer_length)) < 0) { + if (RAND_bytes(buffer, buffer_length) <= 0) { efree(buffer); if (zstrong_result_returned) { ZVAL_BOOL(zstrong_result_returned, 0); @@ -5431,7 +5429,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) RETVAL_STRINGL((char *)buffer, buffer_length, 0); if (zstrong_result_returned) { - ZVAL_BOOL(zstrong_result_returned, strong_result); + ZVAL_BOOL(zstrong_result_returned, 1); } } /* }}} */ diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index b9a8019088..aa369abe3a 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -536,13 +536,16 @@ static inline void phar_set_inode(phar_entry_info *entry TSRMLS_DC) /* {{{ */ { char tmp[MAXPATHLEN]; int tmp_len; - size_t len; + size_t len1, len2; tmp_len = MIN(MAXPATHLEN, entry->filename_len + entry->phar->fname_len); - len = MIN(entry->phar->fname_len, tmp_len); - memcpy(tmp, entry->phar->fname, len); - len = MIN(tmp_len - len, entry->filename_len); - memcpy(tmp + entry->phar->fname_len, entry->filename, len); + + len1 = MIN(entry->phar->fname_len, tmp_len); + memcpy(tmp, entry->phar->fname, len1); + + len2 = MIN(tmp_len - len1, entry->filename_len); + memcpy(tmp + len1, entry->filename, len2); + entry->inode = (unsigned short)zend_get_hash_value(tmp, tmp_len); } /* }}} */ diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 49cbbf2b74..22d59c228a 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -4119,6 +4119,9 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * char *fullpath; const char *slash; mode_t mode; + cwd_state new_state; + char *filename; + size_t filename_len; if (entry->is_mounted) { /* silently ignore mounted entries */ @@ -4128,8 +4131,39 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * if (entry->filename_len >= sizeof(".phar")-1 && !memcmp(entry->filename, ".phar", sizeof(".phar")-1)) { return SUCCESS; } + /* strip .. from path and restrict it to be under dest directory */ + new_state.cwd = (char*)malloc(2); + new_state.cwd[0] = DEFAULT_SLASH; + new_state.cwd[1] = '\0'; + new_state.cwd_length = 1; + if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND TSRMLS_CC) != 0 || + new_state.cwd_length <= 1) { + if (EINVAL == errno && entry->filename_len > 50) { + char *tmp = estrndup(entry->filename, 50); + spprintf(error, 4096, "Cannot extract \"%s...\" to \"%s...\", extracted filename is too long for filesystem", tmp, dest); + efree(tmp); + } else { + spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename); + } + free(new_state.cwd); + return FAILURE; + } + filename = new_state.cwd + 1; + filename_len = new_state.cwd_length - 1; +#ifdef PHP_WIN32 + /* unixify the path back, otherwise non zip formats might be broken */ + { + int cnt = filename_len; + + do { + if ('\\' == filename[cnt]) { + filename[cnt] = '/'; + } + } while (cnt-- >= 0); + } +#endif - len = spprintf(&fullpath, 0, "%s/%s", dest, entry->filename); + len = spprintf(&fullpath, 0, "%s/%s", dest, filename); if (len >= MAXPATHLEN) { char *tmp; @@ -4143,18 +4177,21 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * spprintf(error, 4096, "Cannot extract \"%s\" to \"%s...\", extracted filename is too long for filesystem", entry->filename, fullpath); } efree(fullpath); + free(new_state.cwd); return FAILURE; } if (!len) { spprintf(error, 4096, "Cannot extract \"%s\", internal error", entry->filename); efree(fullpath); + free(new_state.cwd); return FAILURE; } if (PHAR_OPENBASEDIR_CHECKPATH(fullpath)) { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath); efree(fullpath); + free(new_state.cwd); return FAILURE; } @@ -4162,14 +4199,15 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * if (!overwrite && SUCCESS == php_stream_stat_path(fullpath, &ssb)) { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", path already exists", entry->filename, fullpath); efree(fullpath); + free(new_state.cwd); return FAILURE; } /* perform dirname */ - slash = zend_memrchr(entry->filename, '/', entry->filename_len); + slash = zend_memrchr(filename, '/', filename_len); if (slash) { - fullpath[dest_len + (slash - entry->filename) + 1] = '\0'; + fullpath[dest_len + (slash - filename) + 1] = '\0'; } else { fullpath[dest_len] = '\0'; } @@ -4179,23 +4217,27 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) { spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath); efree(fullpath); + free(new_state.cwd); return FAILURE; } } else { if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) { spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath); efree(fullpath); + free(new_state.cwd); return FAILURE; } } } if (slash) { - fullpath[dest_len + (slash - entry->filename) + 1] = '/'; + fullpath[dest_len + (slash - filename) + 1] = '/'; } else { fullpath[dest_len] = '/'; } + filename = NULL; + free(new_state.cwd); /* it is a standalone directory, job done */ if (entry->is_dir) { efree(fullpath); diff --git a/ext/phar/tests/bug70019.phpt b/ext/phar/tests/bug70019.phpt new file mode 100644 index 0000000000..d7976a180d --- /dev/null +++ b/ext/phar/tests/bug70019.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #70019 Files extracted from archive may be placed outside of destination directory +--FILE-- +<?php +$dir = __DIR__."/bug70019"; +$phar = new PharData(__DIR__."/bug70019.zip"); +if(!is_dir($dir)) { + mkdir($dir); +} +$phar->extractTo($dir); +var_dump(file_exists("$dir/ThisIsATestFile.txt")); +?> +===DONE=== +--CLEAN-- +<?php +$dir = __DIR__."/bug70019"; +unlink("$dir/ThisIsATestFile.txt"); +rmdir($dir); +?> +--EXPECTF-- +bool(true) +===DONE=== diff --git a/ext/phar/tests/bug70019.zip b/ext/phar/tests/bug70019.zip Binary files differnew file mode 100644 index 0000000000..faf152df7e --- /dev/null +++ b/ext/phar/tests/bug70019.zip diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index 2045162367..c8eba98bc8 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -375,7 +375,7 @@ int make_http_soap_request(zval *this_ptr, int kind = Z_LVAL_PP(tmp) & SOAP_COMPRESSION_DEFLATE; if (level > 9) {level = 9;} - + if ((Z_LVAL_PP(tmp) & SOAP_COMPRESSION_ACCEPT) != 0) { smart_str_append_const(&soap_headers_z,"Accept-Encoding: gzip, deflate\r\n"); } @@ -434,7 +434,7 @@ int make_http_soap_request(zval *this_ptr, context = php_stream_context_from_zval(*tmp, 0); } - if (context && + if (context && php_stream_context_get_option(context, "http", "max_redirects", &tmp) == SUCCESS) { if (Z_TYPE_PP(tmp) != IS_STRING || !is_numeric_string(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &redirect_max, NULL, 1)) { if (Z_TYPE_PP(tmp) == IS_LONG) @@ -532,7 +532,7 @@ try_again: add_property_resource(this_ptr, "httpurl", ret); /*zend_list_addref(ret);*/ - if (context && + if (context && php_stream_context_get_option(context, "http", "protocol_version", &tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_DOUBLE && Z_DVAL_PP(tmp) == 1.0) { @@ -590,7 +590,7 @@ try_again: smart_str_appendl(&soap_headers, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); smart_str_append_const(&soap_headers, "\r\n"); } - } else if (context && + } else if (context && php_stream_context_get_option(context, "http", "user_agent", &tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) { if (Z_STRLEN_PP(tmp) > 0) { @@ -732,7 +732,7 @@ try_again: PHP_MD5Update(&md5ctx, (unsigned char*)HA2, 32); PHP_MD5Final(hash, &md5ctx); make_digest(response, hash); - + smart_str_append_const(&soap_headers, "Authorization: Digest username=\""); smart_str_appendl(&soap_headers, Z_STRVAL_PP(login), Z_STRLEN_PP(login)); if (zend_hash_find(Z_ARRVAL_PP(digest), "realm", sizeof("realm"), (void **)&tmp) == SUCCESS && @@ -750,7 +750,7 @@ try_again: smart_str_appends(&soap_headers, phpurl->path); } else { smart_str_appendc(&soap_headers, '/'); - } + } if (phpurl->query) { smart_str_appendc(&soap_headers, '?'); smart_str_appends(&soap_headers, phpurl->query); @@ -822,18 +822,21 @@ try_again: zend_hash_internal_pointer_reset(Z_ARRVAL_PP(cookies)); smart_str_append_const(&soap_headers, "Cookie: "); for (i = 0; i < n; i++) { + ulong numindx; + int res = zend_hash_get_current_key_ex(Z_ARRVAL_PP(cookies), &key, &key_len, &numindx, 0, NULL); zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data); - zend_hash_get_current_key_ex(Z_ARRVAL_PP(cookies), &key, &key_len, NULL, 0, NULL); - if (Z_TYPE_PP(data) == IS_ARRAY) { + if (res == HASH_KEY_IS_STRING && Z_TYPE_PP(data) == IS_ARRAY) { zval** value; if (zend_hash_index_find(Z_ARRVAL_PP(data), 0, (void**)&value) == SUCCESS && Z_TYPE_PP(value) == IS_STRING) { zval **tmp; if ((zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == FAILURE || + Z_TYPE_PP(tmp) != IS_STRING || strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0) && (zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE || + Z_TYPE_PP(tmp) != IS_STRING || in_domain(phpurl->host,Z_STRVAL_PP(tmp))) && (use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) { smart_str_appendl(&soap_headers, key, key_len-1); @@ -1060,7 +1063,7 @@ try_again: efree(connection); } } - } + } if (!get_http_body(stream, http_close, http_headers, &http_body, &http_body_size TSRMLS_CC)) { if (request != buf) {efree(request);} @@ -1111,7 +1114,7 @@ try_again: strcat(s, new_url->path); efree(new_url->path); new_url->path = s; - } + } } else { char *s = emalloc(strlen(new_url->path) + 2); s[0] = '/'; s[1] = 0; diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 4f7c3a82d5..42490fc007 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1770,13 +1770,12 @@ SPL_METHOD(Array, unserialize) ALLOC_INIT_ZVAL(pflags); if (!php_var_unserialize(&pflags, &p, s + buf_len, &var_hash TSRMLS_CC) || Z_TYPE_P(pflags) != IS_LONG) { - zval_ptr_dtor(&pflags); goto outexcept; } + var_push_dtor(&var_hash, &pflags); --p; /* for ';' */ flags = Z_LVAL_P(pflags); - zval_ptr_dtor(&pflags); /* flags needs to be verified and we also need to verify whether the next * thing we get is ';'. After that we require an 'm' or somethign else * where 'm' stands for members and anything else should be an array. If @@ -1798,6 +1797,7 @@ SPL_METHOD(Array, unserialize) if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash TSRMLS_CC)) { goto outexcept; } + var_push_dtor(&var_hash, &intern->array); } if (*p != ';') { goto outexcept; @@ -1816,6 +1816,7 @@ SPL_METHOD(Array, unserialize) goto outexcept; } + var_push_dtor(&var_hash, &pmembers); /* copy members */ if (!intern->std.properties) { rebuild_object_properties(&intern->std); @@ -1826,10 +1827,16 @@ SPL_METHOD(Array, unserialize) /* done reading $serialized */ PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + if (pflags) { + zval_ptr_dtor(&pflags); + } return; outexcept: PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + if (pflags) { + zval_ptr_dtor(&pflags); + } zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0 TSRMLS_CC, "Error at offset %ld of %d bytes", (long)((char*)p - buf), buf_len); return; diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 82fdc14954..7a92e2073d 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -500,7 +500,7 @@ static int spl_dllist_object_count_elements(zval *object, long *count TSRMLS_DC) *count = spl_ptr_llist_count(intern->llist); return SUCCESS; -} +} /* }}} */ static HashTable* spl_dllist_object_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /* {{{{ */ @@ -571,7 +571,7 @@ SPL_METHOD(SplDoublyLinkedList, push) spl_ptr_llist_push(intern->llist, value TSRMLS_CC); RETURN_TRUE; -} +} /* }}} */ /* {{{ proto bool SplDoublyLinkedList::unshift(mixed $value) U @@ -614,7 +614,7 @@ SPL_METHOD(SplDoublyLinkedList, pop) } RETURN_ZVAL(value, 1, 1); -} +} /* }}} */ /* {{{ proto mixed SplDoublyLinkedList::shift() U @@ -637,7 +637,7 @@ SPL_METHOD(SplDoublyLinkedList, shift) } RETURN_ZVAL(value, 1, 1); -} +} /* }}} */ /* {{{ proto mixed SplDoublyLinkedList::top() U @@ -1050,7 +1050,7 @@ static void spl_dllist_it_move_forward(zend_object_iterator *iter TSRMLS_DC) /* SPL_METHOD(SplDoublyLinkedList, key) { spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1064,7 +1064,7 @@ SPL_METHOD(SplDoublyLinkedList, key) SPL_METHOD(SplDoublyLinkedList, prev) { spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1078,7 +1078,7 @@ SPL_METHOD(SplDoublyLinkedList, prev) SPL_METHOD(SplDoublyLinkedList, next) { spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1092,7 +1092,7 @@ SPL_METHOD(SplDoublyLinkedList, next) SPL_METHOD(SplDoublyLinkedList, valid) { spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1106,7 +1106,7 @@ SPL_METHOD(SplDoublyLinkedList, valid) SPL_METHOD(SplDoublyLinkedList, rewind) { spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1121,7 +1121,7 @@ SPL_METHOD(SplDoublyLinkedList, current) { spl_dllist_object *intern = (spl_dllist_object*)zend_object_store_get_object(getThis() TSRMLS_CC); spl_ptr_llist_element *element = intern->traverse_pointer; - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1176,7 +1176,7 @@ SPL_METHOD(SplDoublyLinkedList, serialize) } else { RETURN_NULL(); } - + } /* }}} */ /* {{{ proto void SplDoublyLinkedList::unserialize(string serialized) @@ -1189,7 +1189,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize) int buf_len; const unsigned char *p, *s; php_unserialize_data_t var_hash; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { return; } @@ -1207,6 +1207,7 @@ SPL_METHOD(SplDoublyLinkedList, unserialize) zval_ptr_dtor(&flags); goto error; } + var_push_dtor(&var_hash, &flags); intern->flags = Z_LVAL_P(flags); zval_ptr_dtor(&flags); diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index cf8663632b..43f4d7d29d 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -102,9 +102,9 @@ void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */ spl_SplObjectStorage *intern = (spl_SplObjectStorage *)object; zend_object_std_dtor(&intern->std TSRMLS_CC); - + zend_hash_destroy(&intern->storage); - + if (intern->debug_info != NULL) { zend_hash_destroy(intern->debug_info); efree(intern->debug_info); @@ -203,7 +203,7 @@ spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern void spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf TSRMLS_DC) /* {{{ */ { spl_SplObjectStorageElement *pelement, element; - + int hash_len; char *hash = spl_object_storage_get_hash(intern, this, obj, &hash_len TSRMLS_CC); if (!hash) { @@ -239,7 +239,7 @@ int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *ob } ret = zend_hash_del(&intern->storage, hash, hash_len); spl_object_storage_free_hash(intern, hash); - + return ret; } /* }}}*/ @@ -482,7 +482,7 @@ SPL_METHOD(SplObjectStorage, getHash) hash = emalloc(33); php_spl_object_hash(obj, hash TSRMLS_CC); - + RETVAL_STRING(hash, 0); } /* }}} */ @@ -640,11 +640,11 @@ SPL_METHOD(SplObjectStorage, count) SPL_METHOD(SplObjectStorage, rewind) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } - + zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); intern->index = 0; } /* }}} */ @@ -654,11 +654,11 @@ SPL_METHOD(SplObjectStorage, rewind) SPL_METHOD(SplObjectStorage, valid) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } - + RETURN_BOOL(zend_hash_has_more_elements_ex(&intern->storage, &intern->pos) == SUCCESS); } /* }}} */ @@ -667,11 +667,11 @@ SPL_METHOD(SplObjectStorage, valid) SPL_METHOD(SplObjectStorage, key) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } - + RETURN_LONG(intern->index); } /* }}} */ @@ -681,11 +681,11 @@ SPL_METHOD(SplObjectStorage, current) { spl_SplObjectStorageElement *element; spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } - + if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) { return; } @@ -702,7 +702,7 @@ SPL_METHOD(SplObjectStorage, getInfo) if (zend_parse_parameters_none() == FAILURE) { return; } - + if (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == FAILURE) { return; } @@ -716,7 +716,7 @@ SPL_METHOD(SplObjectStorage, setInfo) spl_SplObjectStorageElement *element; spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); zval *inf; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &inf) == FAILURE) { return; } @@ -734,11 +734,11 @@ SPL_METHOD(SplObjectStorage, setInfo) SPL_METHOD(SplObjectStorage, next) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } - + zend_hash_move_forward_ex(&intern->storage, &intern->pos); intern->index++; } /* }}} */ @@ -760,7 +760,7 @@ SPL_METHOD(SplObjectStorage, serialize) } PHP_VAR_SERIALIZE_INIT(var_hash); - + /* storage */ smart_str_appendl(&buf, "x:", 2); MAKE_STD_ZVAL(flags); @@ -800,7 +800,7 @@ SPL_METHOD(SplObjectStorage, serialize) } else { RETURN_NULL(); } - + } /* }}} */ /* {{{ proto void SplObjectStorage::unserialize(string serialized) @@ -815,7 +815,7 @@ SPL_METHOD(SplObjectStorage, unserialize) php_unserialize_data_t var_hash; zval *pentry, *pmembers, *pcount = NULL, *pinf; long count; - + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &buf, &buf_len) == FAILURE) { return; } @@ -838,14 +838,15 @@ SPL_METHOD(SplObjectStorage, unserialize) goto outexcept; } + var_push_dtor(&var_hash, &pcount); --p; /* for ';' */ count = Z_LVAL_P(pcount); - + while(count-- > 0) { spl_SplObjectStorageElement *pelement; char *hash; int hash_len; - + if (*p != ';') { goto outexcept; } @@ -886,7 +887,7 @@ SPL_METHOD(SplObjectStorage, unserialize) if(pelement->obj) { var_push_dtor(&var_hash, &pelement->obj); } - } + } spl_object_storage_attach(intern, getThis(), pentry, pinf TSRMLS_CC); zval_ptr_dtor(&pentry); zval_ptr_dtor(&pinf); @@ -909,6 +910,7 @@ SPL_METHOD(SplObjectStorage, unserialize) goto outexcept; } + var_push_dtor(&var_hash, &pmembers); /* copy members */ if (!intern->std.properties) { rebuild_object_properties(&intern->std); @@ -1026,7 +1028,7 @@ SPL_METHOD(MultipleIterator, __construct) SPL_METHOD(MultipleIterator, getFlags) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1093,7 +1095,7 @@ SPL_METHOD(MultipleIterator, rewind) zval *it; intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1116,7 +1118,7 @@ SPL_METHOD(MultipleIterator, next) zval *it; intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1140,7 +1142,7 @@ SPL_METHOD(MultipleIterator, valid) long expect, valid; intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1186,7 +1188,7 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ } array_init_size(return_value, num_elements); - + zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while (zend_hash_get_current_data_ex(&intern->storage, (void**)&element, &intern->pos) == SUCCESS && !EG(exception)) { it = element->obj; @@ -1248,7 +1250,7 @@ SPL_METHOD(MultipleIterator, current) { spl_SplObjectStorage *intern; intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } @@ -1263,7 +1265,7 @@ SPL_METHOD(MultipleIterator, key) { spl_SplObjectStorage *intern; intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } diff --git a/ext/spl/tests/bug70068.phpt b/ext/spl/tests/bug70068.phpt new file mode 100644 index 0000000000..92a38dfbd6 --- /dev/null +++ b/ext/spl/tests/bug70068.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bug #70068 (Dangling pointer in the unserialization of ArrayObject items) +--FILE-- +<?php +$a = unserialize('a:3:{i:0;C:11:"ArrayObject":20:{x:i:0;r:3;;m:a:0:{};}i:1;d:11;i:2;S:31:"AAAAAAAABBBBCCCC\01\00\00\00\04\00\00\00\00\00\00\00\00\00\00";}'); +?> +OK +--EXPECT-- +OK
\ No newline at end of file diff --git a/ext/spl/tests/bug70166.phpt b/ext/spl/tests/bug70166.phpt new file mode 100644 index 0000000000..51a35965a5 --- /dev/null +++ b/ext/spl/tests/bug70166.phpt @@ -0,0 +1,29 @@ +--TEST-- +SPL: Bug #70166 Use After Free Vulnerability in unserialize() with SPLArrayObject +--FILE-- +<?php +$inner = 'x:i:1;a:0:{};m:a:0:{}'; +$exploit = 'a:2:{i:0;C:11:"ArrayObject":'.strlen($inner).':{'.$inner.'}i:1;R:5;}'; + +$data = unserialize($exploit); + +for($i = 0; $i < 5; $i++) { + $v[$i] = 'hi'.$i; +} + +var_dump($data); +?> +===DONE=== +--EXPECTF-- +array(2) { + [0]=> + object(ArrayObject)#%d (1) { + ["storage":"ArrayObject":private]=> + array(0) { + } + } + [1]=> + array(0) { + } +} +===DONE=== diff --git a/ext/spl/tests/bug70168.phpt b/ext/spl/tests/bug70168.phpt new file mode 100644 index 0000000000..e1f7e9f820 --- /dev/null +++ b/ext/spl/tests/bug70168.phpt @@ -0,0 +1,36 @@ +--TEST-- +SPL: Bug #70168 Use After Free Vulnerability in unserialize() with SplObjectStorage +--FILE-- +<?php +$inner = 'x:i:1;O:8:"stdClass":0:{};m:a:0:{}'; +$exploit = 'a:2:{i:0;C:16:"SplObjectStorage":'.strlen($inner).':{'.$inner.'}i:1;R:3;}'; + +$data = unserialize($exploit); + +for($i = 0; $i < 5; $i++) { + $v[$i] = 'hi'.$i; +} + +var_dump($data); +?> +===DONE=== +--EXPECTF-- +array(2) { + [0]=> + object(SplObjectStorage)#%d (1) { + ["storage":"SplObjectStorage":private]=> + array(1) { + ["%s"]=> + array(2) { + ["obj"]=> + object(stdClass)#2 (0) { + } + ["inf"]=> + NULL + } + } + } + [1]=> + int(1) +} +===DONE=== diff --git a/ext/spl/tests/bug70169.phpt b/ext/spl/tests/bug70169.phpt new file mode 100644 index 0000000000..9d814be5fa --- /dev/null +++ b/ext/spl/tests/bug70169.phpt @@ -0,0 +1,30 @@ +--TEST-- +SPL: Bug #70169 Use After Free Vulnerability in unserialize() with SplDoublyLinkedList +--FILE-- +<?php +$inner = 'i:1;'; +$exploit = 'a:2:{i:0;C:19:"SplDoublyLinkedList":'.strlen($inner).':{'.$inner.'}i:1;R:3;}'; + +$data = unserialize($exploit); + +for($i = 0; $i < 5; $i++) { + $v[$i] = 'hi'.$i; +} + +var_dump($data); +?> +===DONE=== +--EXPECTF-- +array(2) { + [0]=> + object(SplDoublyLinkedList)#%d (2) { + ["flags":"SplDoublyLinkedList":private]=> + int(1) + ["dllist":"SplDoublyLinkedList":private]=> + array(0) { + } + } + [1]=> + int(1) +} +===DONE=== diff --git a/ext/standard/tests/serialize/bug69152.phpt b/ext/standard/tests/serialize/bug69152.phpt index 4e741685cc..bc2b302ddb 100644 --- a/ext/standard/tests/serialize/bug69152.phpt +++ b/ext/standard/tests/serialize/bug69152.phpt @@ -9,6 +9,7 @@ $x->test(); ?> --EXPECTF-- +Notice: Undefined property: Exception::$previous in %s on line %d exception 'Exception' in %s:%d Stack trace: #0 {main} diff --git a/ext/standard/tests/serialize/bug69793.phpt b/ext/standard/tests/serialize/bug69793.phpt new file mode 100644 index 0000000000..134b4dd696 --- /dev/null +++ b/ext/standard/tests/serialize/bug69793.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #69793: Remotely triggerable stack exhaustion via recursive method calls +--FILE-- +<?php +$e = unserialize('O:9:"Exception":7:{s:17:"'."\0".'Exception'."\0".'string";s:1:"a";s:7:"'."\0".'*'."\0".'code";i:0;s:7:"'."\0".'*'."\0".'file";R:1;s:7:"'."\0".'*'."\0".'line";i:1337;s:16:"'."\0".'Exception'."\0".'trace";a:0:{}s:19:"'."\0".'Exception'."\0".'previous";i:10;s:10:"'."\0".'*'."\0".'message";N;}'); + +var_dump($e.""); +?> +--EXPECTF-- +Notice: Undefined property: Exception::$message in %s/bug69793.php on line %d + +Notice: Undefined property: Exception::$file in %s/bug69793.php on line %d + +Notice: Undefined property: Exception::$previous in %s/bug69793.php on line %d +string(53) "exception 'Exception' in :1337 +Stack trace: +#0 {main}" diff --git a/sapi/cli/tests/005.phpt b/sapi/cli/tests/005.phpt index 84b0f98440..a840e8ffd2 100644 --- a/sapi/cli/tests/005.phpt +++ b/sapi/cli/tests/005.phpt @@ -4,7 +4,7 @@ show information about class <?php include "skipif.inc"; if (!extension_loaded("reflection")) { - die("skip reflection extension required"); + die("skip reflection extension required"); } ?> --FILE-- @@ -18,7 +18,7 @@ var_dump(`"$php" -n --rc exception`); echo "Done\n"; ?> ---EXPECTF-- +--EXPECTF-- string(40) "Exception: Class unknown does not exist " string(183) "Class [ <internal:Core> class stdClass ] { @@ -40,7 +40,7 @@ string(183) "Class [ <internal:Core> class stdClass ] { } " -string(1355) "Class [ <internal:Core> class Exception ] { +string(1424) "Class [ <internal:Core> class Exception ] { - Constants [0] { } @@ -61,7 +61,7 @@ string(1355) "Class [ <internal:Core> class Exception ] { Property [ <default> private $previous ] } - - Methods [10] { + - Methods [11] { Method [ <internal:Core> final private method __clone ] { } @@ -74,6 +74,9 @@ string(1355) "Class [ <internal:Core> class Exception ] { } } + Method [ <internal:Core> final public method __wakeup ] { + } + Method [ <internal:Core> final public method getMessage ] { } |