File php-CVE-2016-7124.patch of Package php7

http://git.php.net/?p=php-src.git;a=commitdiff;h=2135fdef9b588a34f8805b2bbf10704e36163d5a
http://git.php.net/?p=php-src.git;a=commitdiff;h=61f2f5a0f760157f9c9d32d7d3df2be47a73e74d
http://git.php.net/?p=php-src.git;a=commitdiff;h=e0f9fbdfa61012101de7f4a8653ca5538c404a71
Index: php-7.0.7/ext/session/session.c
===================================================================
--- php-7.0.7.orig/ext/session/session.c	2016-09-08 13:55:14.746632823 +0200
+++ php-7.0.7/ext/session/session.c	2016-09-08 13:55:25.810821404 +0200
@@ -905,12 +905,19 @@ PS_SERIALIZER_DECODE_FUNC(php_serialize)
 	const char *endptr = val + vallen;
 	zval session_vars;
 	php_unserialize_data_t var_hash;
+       int result;
 	zend_string *var_name = zend_string_init("_SESSION", sizeof("_SESSION") - 1, 0);
 
 	ZVAL_NULL(&session_vars);
 	PHP_VAR_UNSERIALIZE_INIT(var_hash);
-	php_var_unserialize(&session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash);
+       result = php_var_unserialize(
+               &session_vars, (const unsigned char **)&val, (const unsigned char *)endptr, &var_hash);
 	PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
+       if (!result) {
+               zval_ptr_dtor(&session_vars);
+               ZVAL_NULL(&session_vars);
+       }
+
 	if (!Z_ISUNDEF(PS(http_session_vars))) {
 		zval_ptr_dtor(&PS(http_session_vars));
 	}
Index: php-7.0.7/ext/standard/var_unserializer.re
===================================================================
--- php-7.0.7.orig/ext/standard/var_unserializer.re	2016-05-25 15:14:08.000000000 +0200
+++ php-7.0.7/ext/standard/var_unserializer.re	2016-09-08 13:55:14.746632823 +0200
@@ -305,6 +305,8 @@ static inline size_t parse_uiv(const uns
 #define UNSERIALIZE_PARAMETER zval *rval, const unsigned char **p, const unsigned char *max, php_unserialize_data_t *var_hash, HashTable *classes
 #define UNSERIALIZE_PASSTHRU rval, p, max, var_hash, classes
 
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER);
+
 static zend_always_inline int process_nested_data(UNSERIALIZE_PARAMETER, HashTable *ht, zend_long elements, int objprops)
 {
 	while (elements-- > 0) {
@@ -313,7 +315,7 @@ static zend_always_inline int process_ne
 
 		ZVAL_UNDEF(&key);
 
-		if (!php_var_unserialize_ex(&key, p, max, NULL, classes)) {
+               if (!php_var_unserialize_internal(&key, p, max, NULL, classes)) {
 			zval_dtor(&key);
 			return 0;
 		}
@@ -369,7 +371,7 @@ string_key:
 			}
 		}
 
-		if (!php_var_unserialize_ex(data, p, max, var_hash, classes)) {
+               if (!php_var_unserialize_internal(data, p, max, var_hash, classes)) {
 			zval_dtor(&key);
 			return 0;
 		}
@@ -459,23 +461,32 @@ static inline int object_common2(UNSERIA
 	zval retval;
 	zval fname;
 	HashTable *ht;
+       zend_bool has_wakeup;
 
 	if (Z_TYPE_P(rval) != IS_OBJECT) {
 		return 0;
 	}
 
+       has_wakeup = Z_OBJCE_P(rval) != PHP_IC_ENTRY
+               && zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1);
+
 	ht = Z_OBJPROP_P(rval);
 	zend_hash_extend(ht, zend_hash_num_elements(ht) + elements, (ht->u.flags & HASH_FLAG_PACKED));
 	if (!process_nested_data(UNSERIALIZE_PASSTHRU, ht, elements, 1)) {
+               if (has_wakeup) {
+                       ZVAL_DEREF(rval);
+                       GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
+               }
 		return 0;
 	}
 
 	ZVAL_DEREF(rval);
-	if (Z_OBJCE_P(rval) != PHP_IC_ENTRY &&
-		zend_hash_str_exists(&Z_OBJCE_P(rval)->function_table, "__wakeup", sizeof("__wakeup")-1)) {
+       if (has_wakeup) {
 		ZVAL_STRINGL(&fname, "__wakeup", sizeof("__wakeup") - 1);
 		BG(serialize_lock)++;
-		call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL);
+               if (call_user_function_ex(CG(function_table), rval, &fname, &retval, 0, 0, 1, NULL) == FAILURE || Z_ISUNDEF(retval)) {
+                       GC_FLAGS(Z_OBJ_P(rval)) |= IS_OBJ_DESTRUCTOR_CALLED;
+               }
 		BG(serialize_lock)--;
 		zval_dtor(&fname);
 		zval_dtor(&retval);
@@ -486,7 +497,6 @@ static inline int object_common2(UNSERIA
 	}
 
 	return finish_nested_data(UNSERIALIZE_PASSTHRU);
-
 }
 #ifdef PHP_WIN32
 # pragma optimize("", on)
@@ -498,9 +508,35 @@ PHPAPI int php_var_unserialize(zval *rva
 	return php_var_unserialize_ex(UNSERIALIZE_PASSTHRU);
 }
 
-
 PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER)
 {
+       var_entries *orig_var_entries = (*var_hash)->last;
+       zend_long orig_used_slots = orig_var_entries ? orig_var_entries->used_slots : 0;
+       int result;
+       
+       result = php_var_unserialize_internal(UNSERIALIZE_PASSTHRU);
+
+       if (!result) {
+               /* If the unserialization failed, mark all elements that have been added to var_hash
+                * as NULL. This will forbid their use by other unserialize() calls in the same
+                * unserialization context. */
+               var_entries *e = orig_var_entries;
+               zend_long s = orig_used_slots;
+               while (e) {
+                       for (; s < e->used_slots; s++) {
+                               e->data[s] = NULL;
+                       }
+
+                       e = e->next;
+                       s = 0;
+               }
+       }
+
+       return result;
+}
+
+static int php_var_unserialize_internal(UNSERIALIZE_PARAMETER)
+{
 	const unsigned char *cursor, *limit, *marker, *start;
 	zval *rval_ref;
openSUSE Build Service is sponsored by