diff options
author | Stanislav Malyshev <stas@php.net> | 2015-08-04 14:10:57 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2015-08-04 14:10:57 -0700 |
commit | 69ed3969dd3b00feaa62f611c5095e27ba96274d (patch) | |
tree | 0eaaac44be832888b856808ec83153f42ccc577c | |
parent | 66edc158755a8e960499913f16f6455797bb5803 (diff) | |
parent | 51f9a00b47159ed13dfe5bd5af7e98986aa1a6fa (diff) | |
download | php-git-69ed3969dd3b00feaa62f611c5095e27ba96274d.tar.gz |
Merge branch 'PHP-5.4' into PHP-5.5
* PHP-5.4:
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:
.gitignore
ext/date/php_date.c
ext/spl/spl_array.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 | 66 | ||||
-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 |
21 files changed, 398 insertions, 151 deletions
diff --git a/.gitignore b/.gitignore index f696b15ebf..9a6319597b 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 5071e2eef0..47f78a22cd 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -593,7 +593,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; \ @@ -762,7 +762,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" @@ -784,19 +784,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" @@ -889,7 +889,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); @@ -1041,8 +1041,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) @@ -1050,8 +1050,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]; } /* }}} */ @@ -1083,7 +1083,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 ); @@ -1129,7 +1129,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; } @@ -1229,7 +1229,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); } /* }}} */ @@ -1253,7 +1253,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; } @@ -1294,7 +1294,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 ); @@ -1326,7 +1326,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; } @@ -1378,7 +1378,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; @@ -1406,7 +1406,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; @@ -1477,7 +1477,7 @@ PHP_FUNCTION(strtotime) } if (!time_len) { - timelib_time_dtor(now); + timelib_time_dtor(now); RETURN_FALSE; } @@ -1926,7 +1926,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; } /* }}} */ @@ -2120,13 +2120,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; } @@ -2140,12 +2140,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; @@ -2155,7 +2155,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; } @@ -2272,10 +2272,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; } @@ -2289,12 +2289,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) { @@ -2310,7 +2310,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; } @@ -2371,10 +2371,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; } @@ -2388,7 +2388,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 **/ @@ -2460,10 +2460,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; } @@ -2477,7 +2477,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 **/ @@ -2563,7 +2563,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); } @@ -2942,7 +2942,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 { @@ -3009,7 +3009,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; } @@ -3028,7 +3028,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; } @@ -3512,7 +3512,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); } @@ -3701,7 +3701,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); @@ -3979,7 +3979,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; @@ -4138,7 +4138,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) { @@ -4161,8 +4161,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; \ @@ -4173,8 +4172,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; \ } \ @@ -4352,7 +4358,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; @@ -4381,7 +4387,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) { @@ -4496,7 +4502,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) { @@ -4530,7 +4536,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; @@ -4606,11 +4612,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; @@ -4654,7 +4660,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; } @@ -4708,7 +4714,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; } @@ -4722,7 +4728,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) { @@ -4866,7 +4872,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); @@ -4949,7 +4955,7 @@ static int php_date_period_initialize_from_hash(php_period_obj *period_obj, Hash } period_obj->initialized = 1; - + return 1; } @@ -4966,7 +4972,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 9c4131f608..fb3069a4a7 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -5136,7 +5136,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; @@ -5154,7 +5153,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); @@ -5164,7 +5162,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); @@ -5177,7 +5175,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 e97c9b56fc..d8c8ed1bb1 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -561,13 +561,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 46c3d7cb34..6d25509cdf 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -4117,6 +4117,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 */ @@ -4126,8 +4129,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; @@ -4141,18 +4175,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; } @@ -4160,14 +4197,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'; } @@ -4177,23 +4215,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 90a2728fbf..21a0da0876 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); @@ -821,18 +821,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(Z_ARRVAL_PP(cookies), &key, &numindx, FALSE); zend_hash_get_current_data(Z_ARRVAL_PP(cookies), (void **)&data); - zend_hash_get_current_key(Z_ARRVAL_PP(cookies), &key, NULL, FALSE); - 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, strlen(key)); @@ -1059,7 +1062,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);} @@ -1110,7 +1113,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 355cb08ffe..c89cf4994b 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -1762,13 +1762,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 @@ -1790,6 +1789,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; @@ -1808,6 +1808,7 @@ SPL_METHOD(Array, unserialize) goto outexcept; } + var_push_dtor(&var_hash, &pmembers); /* copy members */ if (!intern->std.properties) { rebuild_object_properties(&intern->std); @@ -1818,10 +1819,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 a894dd9594..053173f010 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; } @@ -1208,6 +1208,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 18c875b50d..a5ec94b7a8 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -101,9 +101,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); @@ -202,7 +202,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) { @@ -238,7 +238,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; } /* }}}*/ @@ -481,7 +481,7 @@ SPL_METHOD(SplObjectStorage, getHash) hash = emalloc(33); php_spl_object_hash(obj, hash TSRMLS_CC); - + RETVAL_STRING(hash, 0); } /* }}} */ @@ -610,11 +610,11 @@ SPL_METHOD(SplObjectStorage, contains) SPL_METHOD(SplObjectStorage, count) { spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(getThis() TSRMLS_CC); - + if (zend_parse_parameters_none() == FAILURE) { return; } - + RETURN_LONG(zend_hash_num_elements(&intern->storage)); } /* }}} */ @@ -623,11 +623,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; } /* }}} */ @@ -637,11 +637,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); } /* }}} */ @@ -650,11 +650,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); } /* }}} */ @@ -664,11 +664,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; } @@ -685,7 +685,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; } @@ -699,7 +699,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; } @@ -717,11 +717,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++; } /* }}} */ @@ -743,7 +743,7 @@ SPL_METHOD(SplObjectStorage, serialize) } PHP_VAR_SERIALIZE_INIT(var_hash); - + /* storage */ smart_str_appendl(&buf, "x:", 2); MAKE_STD_ZVAL(flags); @@ -783,7 +783,7 @@ SPL_METHOD(SplObjectStorage, serialize) } else { RETURN_NULL(); } - + } /* }}} */ /* {{{ proto void SplObjectStorage::unserialize(string serialized) @@ -798,7 +798,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; } @@ -822,14 +822,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; } @@ -870,7 +871,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); @@ -893,6 +894,7 @@ SPL_METHOD(SplObjectStorage, unserialize) goto outexcept; } + var_push_dtor(&var_hash, &pmembers); /* copy members */ if (!intern->std.properties) { rebuild_object_properties(&intern->std); @@ -1010,7 +1012,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; } @@ -1077,7 +1079,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; } @@ -1100,7 +1102,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; } @@ -1124,7 +1126,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; } @@ -1170,7 +1172,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; @@ -1232,7 +1234,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; } @@ -1247,7 +1249,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}" |