summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2015-08-04 15:29:13 -0700
committerFerenc Kovacs <tyrael@php.net>2015-08-06 08:52:09 +0200
commit7e254ac00ea88a5e6f585fb089c240e88d99b506 (patch)
treed2fb1e6b4d555430f1223909602ff109a57fdab1
parenta3423aae54d1bb02849e6d9a514b266d01274a64 (diff)
downloadphp-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--.gitignore3
-rw-r--r--Zend/tests/bug70121.phpt9
-rw-r--r--Zend/zend_exceptions.c45
-rw-r--r--ext/date/php_date.c130
-rw-r--r--ext/date/tests/bug53437_var3.phpt12
-rw-r--r--ext/date/tests/bug53437_var5.phpt12
-rw-r--r--ext/openssl/openssl.c6
-rw-r--r--ext/phar/phar_internal.h13
-rw-r--r--ext/phar/phar_object.c50
-rw-r--r--ext/phar/tests/bug70019.phpt22
-rw-r--r--ext/phar/tests/bug70019.zipbin0 -> 184 bytes
-rw-r--r--ext/soap/php_http.c23
-rw-r--r--ext/spl/spl_array.c11
-rw-r--r--ext/spl/spl_dllist.c25
-rw-r--r--ext/spl/spl_observer.c62
-rw-r--r--ext/spl/tests/bug70068.phpt9
-rw-r--r--ext/spl/tests/bug70166.phpt29
-rw-r--r--ext/spl/tests/bug70168.phpt36
-rw-r--r--ext/spl/tests/bug70169.phpt30
-rw-r--r--ext/standard/tests/serialize/bug69152.phpt1
-rw-r--r--ext/standard/tests/serialize/bug69793.phpt17
-rw-r--r--sapi/cli/tests/005.phpt11
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
new file mode 100644
index 0000000000..faf152df7e
--- /dev/null
+++ b/ext/phar/tests/bug70019.zip
Binary files differ
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 ] {
}