dmitry                                   Thu, 13 May 2010 08:09:54 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=299327

Log:
Fixed a possible memory corruption in ArrayObject::uasort() Reported by Stefan 
Esser

Changed paths:
    U   php/php-src/branches/PHP_5_3/NEWS
    U   php/php-src/branches/PHP_5_3/ext/spl/spl_array.c
    U   php/php-src/trunk/ext/spl/spl_array.c

Modified: php/php-src/branches/PHP_5_3/NEWS
===================================================================
--- php/php-src/branches/PHP_5_3/NEWS	2010-05-13 08:01:52 UTC (rev 299326)
+++ php/php-src/branches/PHP_5_3/NEWS	2010-05-13 08:09:54 UTC (rev 299327)
@@ -28,6 +28,8 @@
 - Fixed a possible memory corruption because of unexpected call-time pass by
   refernce and following memory clobbering through callbacks.
   Reported by Stefan Esser (Dmitry)
+- Fixed a possible memory corruption in ArrayObject::uasort() Reported by
+  Stefan Esser (Dmitry)
 - Fixed a possible memory corruption in parse_str(). Reported by Stefan Esser
   (Dmitry)
 - Fixed a possible memory corruption in pack(). Reported by Stefan Esser

Modified: php/php-src/branches/PHP_5_3/ext/spl/spl_array.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/spl/spl_array.c	2010-05-13 08:01:52 UTC (rev 299326)
+++ php/php-src/branches/PHP_5_3/ext/spl/spl_array.c	2010-05-13 08:09:54 UTC (rev 299327)
@@ -320,6 +320,11 @@
 		return &EG(uninitialized_zval_ptr);
 	}

+	if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->nApplyCount > 0)) {
+		zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+		return &EG(uninitialized_zval_ptr);;
+	}
+
 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
 		if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) {
@@ -421,6 +426,7 @@
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	long index;
+	HashTable *ht;

 	if (check_inherited && intern->fptr_offset_set) {
 		if (!offset) {
@@ -434,30 +440,50 @@
 	}

 	if (!offset) {
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		Z_ADDREF_P(value);
-		zend_hash_next_index_insert(spl_array_get_hash_table(intern, 0 TSRMLS_CC), (void**)&value, sizeof(void*), NULL);
+		zend_hash_next_index_insert(ht, (void**)&value, sizeof(void*), NULL);
 		return;
 	}
 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		Z_ADDREF_P(value);
-		zend_symtable_update(spl_array_get_hash_table(intern, 0 TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL);
+		zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL);
 		return;
 	case IS_DOUBLE:
 	case IS_RESOURCE:
 	case IS_BOOL:
 	case IS_LONG:
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		if (offset->type == IS_DOUBLE) {
 			index = (long)Z_DVAL_P(offset);
 		} else {
 			index = Z_LVAL_P(offset);
 		}
 		Z_ADDREF_P(value);
-		zend_hash_index_update(spl_array_get_hash_table(intern, 0 TSRMLS_CC), index, (void**)&value, sizeof(void*), NULL);
+		zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), NULL);
 		return;
 	case IS_NULL:
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		Z_ADDREF_P(value);
-		zend_hash_next_index_insert(spl_array_get_hash_table(intern, 0 TSRMLS_CC), (void**)&value, sizeof(void*), NULL);
+		zend_hash_next_index_insert(ht, (void**)&value, sizeof(void*), NULL);
 		return;
 	default:
 		zend_error(E_WARNING, "Illegal offset type");
@@ -474,6 +500,7 @@
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	long index;
+	HashTable *ht;

 	if (check_inherited && intern->fptr_offset_del) {
 		SEPARATE_ARG_IF_REF(offset);
@@ -484,12 +511,17 @@

 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
-		if (spl_array_get_hash_table(intern, 0 TSRMLS_CC) == &EG(symbol_table)) {
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
+		if (ht == &EG(symbol_table)) {
 			if (zend_delete_global_variable(Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC)) {
 				zend_error(E_NOTICE,"Undefined index:  %s", Z_STRVAL_P(offset));
 			}
 		} else {
-			if (zend_symtable_del(spl_array_get_hash_table(intern, 0 TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
+			if (zend_symtable_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
 				zend_error(E_NOTICE,"Undefined index:  %s", Z_STRVAL_P(offset));
 			}
 		}
@@ -503,7 +535,12 @@
 		} else {
 			index = Z_LVAL_P(offset);
 		}
-		if (zend_hash_index_del(spl_array_get_hash_table(intern, 0 TSRMLS_CC), index) == FAILURE) {
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
+		if (zend_hash_index_del(ht, index) == FAILURE) {
 			zend_error(E_NOTICE,"Undefined offset:  %ld", Z_LVAL_P(offset));
 		}
 		break;
@@ -746,7 +783,7 @@

 	if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
 	&& !std_object_handlers.has_property(object, member, 2 TSRMLS_CC)) {
-		return spl_array_get_dimension_ptr_ptr(1, object, member, 0 TSRMLS_CC);
+		return spl_array_get_dimension_ptr_ptr(1, object, member, BP_VAR_RW TSRMLS_CC);
 	}
 	return std_object_handlers.get_property_ptr_ptr(object, member TSRMLS_CC);
 } /* }}} */
@@ -1303,9 +1340,13 @@
 			zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
 			return;
 		}
+		aht->nApplyCount++;
 		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC);
+		aht->nApplyCount--;
 	} else {
+		aht->nApplyCount++;
 		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
+		aht->nApplyCount--;
 	}
 	Z_TYPE_P(tmp) = IS_NULL; /* we want to destroy the zval, not the hashtable */
 	zval_ptr_dtor(&tmp);

Modified: php/php-src/trunk/ext/spl/spl_array.c
===================================================================
--- php/php-src/trunk/ext/spl/spl_array.c	2010-05-13 08:01:52 UTC (rev 299326)
+++ php/php-src/trunk/ext/spl/spl_array.c	2010-05-13 08:09:54 UTC (rev 299327)
@@ -320,6 +320,11 @@
 		return &EG(uninitialized_zval_ptr);
 	}

+	if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->nApplyCount > 0)) {
+		zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+		return &EG(uninitialized_zval_ptr);;
+	}
+
 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
 		if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) &retval) == FAILURE) {
@@ -421,6 +426,7 @@
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	long index;
+	HashTable *ht;

 	if (check_inherited && intern->fptr_offset_set) {
 		if (!offset) {
@@ -434,30 +440,50 @@
 	}

 	if (!offset) {
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		Z_ADDREF_P(value);
-		zend_hash_next_index_insert(spl_array_get_hash_table(intern, 0 TSRMLS_CC), (void**)&value, sizeof(void*), NULL);
+		zend_hash_next_index_insert(ht, (void**)&value, sizeof(void*), NULL);
 		return;
 	}
 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		Z_ADDREF_P(value);
-		zend_symtable_update(spl_array_get_hash_table(intern, 0 TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL);
+		zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)&value, sizeof(void*), NULL);
 		return;
 	case IS_DOUBLE:
 	case IS_RESOURCE:
 	case IS_BOOL:
 	case IS_LONG:
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		if (offset->type == IS_DOUBLE) {
 			index = (long)Z_DVAL_P(offset);
 		} else {
 			index = Z_LVAL_P(offset);
 		}
 		Z_ADDREF_P(value);
-		zend_hash_index_update(spl_array_get_hash_table(intern, 0 TSRMLS_CC), index, (void**)&value, sizeof(void*), NULL);
+		zend_hash_index_update(ht, index, (void**)&value, sizeof(void*), NULL);
 		return;
 	case IS_NULL:
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
 		Z_ADDREF_P(value);
-		zend_hash_next_index_insert(spl_array_get_hash_table(intern, 0 TSRMLS_CC), (void**)&value, sizeof(void*), NULL);
+		zend_hash_next_index_insert(ht, (void**)&value, sizeof(void*), NULL);
 		return;
 	default:
 		zend_error(E_WARNING, "Illegal offset type");
@@ -474,6 +500,7 @@
 {
 	spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
 	long index;
+	HashTable *ht;

 	if (check_inherited && intern->fptr_offset_del) {
 		SEPARATE_ARG_IF_REF(offset);
@@ -484,12 +511,17 @@

 	switch(Z_TYPE_P(offset)) {
 	case IS_STRING:
-		if (spl_array_get_hash_table(intern, 0 TSRMLS_CC) == &EG(symbol_table)) {
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
+		if (ht == &EG(symbol_table)) {
 			if (zend_delete_global_variable(Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC)) {
 				zend_error(E_NOTICE,"Undefined index:  %s", Z_STRVAL_P(offset));
 			}
 		} else {
-			if (zend_symtable_del(spl_array_get_hash_table(intern, 0 TSRMLS_CC), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
+			if (zend_symtable_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) {
 				zend_error(E_NOTICE,"Undefined index:  %s", Z_STRVAL_P(offset));
 			}
 		}
@@ -503,7 +535,12 @@
 		} else {
 			index = Z_LVAL_P(offset);
 		}
-		if (zend_hash_index_del(spl_array_get_hash_table(intern, 0 TSRMLS_CC), index) == FAILURE) {
+		ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC);
+		if (ht->nApplyCount > 0) {
+			zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+			return;
+		}
+		if (zend_hash_index_del(ht, index) == FAILURE) {
 			zend_error(E_NOTICE,"Undefined offset:  %ld", Z_LVAL_P(offset));
 		}
 		break;
@@ -746,7 +783,7 @@

 	if ((intern->ar_flags & SPL_ARRAY_ARRAY_AS_PROPS) != 0
 	&& !std_object_handlers.has_property(object, member, 2, key TSRMLS_CC)) {
-		return spl_array_get_dimension_ptr_ptr(1, object, member, 0 TSRMLS_CC);
+		return spl_array_get_dimension_ptr_ptr(1, object, member, BP_VAR_RW TSRMLS_CC);
 	}
 	return std_object_handlers.get_property_ptr_ptr(object, member, key TSRMLS_CC);
 } /* }}} */
@@ -1302,9 +1339,13 @@
 			zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0 TSRMLS_CC);
 			return;
 		}
+		aht->nApplyCount++;
 		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 2, tmp, arg TSRMLS_CC);
+		aht->nApplyCount--;
 	} else {
+		aht->nApplyCount++;
 		zend_call_method(NULL, NULL, NULL, fname, fname_len, &retval_ptr, 1, tmp, NULL TSRMLS_CC);
+		aht->nApplyCount--;
 	}
 	Z_TYPE_P(tmp) = IS_NULL; /* we want to destroy the zval, not the hashtable */
 	zval_ptr_dtor(&tmp);
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to