cvs: ZendEngine2 / zend_execute_API.c zend_hash.c zend_hash.h /tests bug28072.phpt

"Dmitry Stogov" <[email protected]>
Newsgroups gmane.comp.php.cvs.zend
Message-ID <cvsdmitry1217600506@cvsserver>
dmitry		Fri Aug  1 14:21:46 2008 UTC

  Modified files:              
    /ZendEngine2	zend_execute_API.c zend_hash.c zend_hash.h 
    /ZendEngine2/tests	bug28072.phpt 
  Log:
  Fixed bug #44100 (Inconsistent handling of static array declarations with duplicate keys).

-- 
Zend Engine CVS Mailing List (http://cvs.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php
dmitry-20080801142146.txt (text/plain, 11.3 KB)
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_execute_API.c?r1=1.455&r2=1.456&diff_format=u
Index: ZendEngine2/zend_execute_API.c
diff -u ZendEngine2/zend_execute_API.c:1.455 ZendEngine2/zend_execute_API.c:1.456
--- ZendEngine2/zend_execute_API.c:1.455	Sat Jul 26 17:01:59 2008
+++ ZendEngine2/zend_execute_API.c	Fri Aug  1 14:21:45 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_execute_API.c,v 1.455 2008/07/26 17:01:59 dmitry Exp $ */
+/* $Id: zend_execute_API.c,v 1.456 2008/08/01 14:21:45 dmitry Exp $ */
 
 #include <stdio.h>
 #include <signal.h>
@@ -654,17 +654,17 @@
 			switch (Z_TYPE(const_value)) {
 				case IS_STRING:
 				case IS_UNICODE:
-					zend_u_symtable_update_current_key(Z_ARRVAL_P(p), Z_TYPE(const_value), Z_UNIVAL(const_value), Z_UNILEN(const_value) + 1);
+					zend_u_symtable_update_current_key(Z_ARRVAL_P(p), Z_TYPE(const_value), Z_UNIVAL(const_value), Z_UNILEN(const_value) + 1, HASH_UPDATE_KEY_IF_BEFORE);
 					break;
 				case IS_BOOL:
 				case IS_LONG:
-					zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, Z_LVAL(const_value));
+					zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, Z_LVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
 					break;
 				case IS_DOUBLE:
-					zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, (long)Z_DVAL(const_value));
+					zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_LONG, NULL_ZSTR, 0, (long)Z_DVAL(const_value), HASH_UPDATE_KEY_IF_BEFORE, NULL);
 					break;
 				case IS_NULL:
-					zend_hash_update_current_key(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, EMPTY_ZSTR, 1, 0);
+					zend_hash_update_current_key_ex(Z_ARRVAL_P(p), HASH_KEY_IS_STRING, EMPTY_ZSTR, 1, 0, HASH_UPDATE_KEY_IF_BEFORE, NULL);
 					break;
 			}
 			zend_hash_move_forward(Z_ARRVAL_P(p));
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_hash.c?r1=1.156&r2=1.157&diff_format=u
Index: ZendEngine2/zend_hash.c
diff -u ZendEngine2/zend_hash.c:1.156 ZendEngine2/zend_hash.c:1.157
--- ZendEngine2/zend_hash.c:1.156	Thu Jul 24 19:50:22 2008
+++ ZendEngine2/zend_hash.c	Fri Aug  1 14:21:45 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_hash.c,v 1.156 2008/07/24 19:50:22 felipe Exp $ */
+/* $Id: zend_hash.c,v 1.157 2008/08/01 14:21:45 dmitry Exp $ */
 
 #include "zend.h"
 #include "zend_operators.h"
@@ -1646,7 +1646,7 @@
 /* This function changes key of currevt element without changing elements'
  * order. If element with target key already exists, it will be deleted first.
  */
-ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, HashPosition *pos) /* {{{ */
+ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, int mode, HashPosition *pos) /* {{{ */
 {
 	Bucket *p;
 	uint real_length;
@@ -1661,23 +1661,77 @@
 			if (!p->nKeyLength && p->h == num_index) {
 				return SUCCESS;
 			}
+
+			if (mode != HASH_UPDATE_KEY_ANYWAY) {
+				Bucket *q = ht->arBuckets[num_index & ht->nTableMask];
+				int found = 0;
+
+				while (q != NULL) {
+					if (q == p) {
+						found = 1;
+					} else if (!q->nKeyLength && q->h == num_index) {
+					    if (found) {
+					    	if (mode & HASH_UPDATE_KEY_IF_BEFORE) {
+					    		break;
+					    	} else {
+								zend_hash_index_del(ht, p->h);
+					    		return FAILURE;
+					    	}
+					    } else {
+					    	if (mode & HASH_UPDATE_KEY_IF_AFTER) {
+					    		break;
+					    	} else {
+								zend_hash_index_del(ht, p->h);
+					    		return FAILURE;
+					    	}
+						}
+					}
+					q = q->pNext;
+				}
+			}
+
 			zend_hash_index_del(ht, num_index);
-		} else if (key_type == HASH_KEY_IS_STRING) {
-			real_length = str_length;
+		} else if (key_type == HASH_KEY_IS_STRING ||
+		           key_type == HASH_KEY_IS_UNICODE) {
+			real_length = key_type == HASH_KEY_IS_STRING ? str_length : str_length * sizeof(UChar);
 			if (p->nKeyLength == str_length &&
-			    p->key.type == IS_STRING &&
-			    memcmp(p->key.arKey.s, str_index.s, str_length) == 0) {
+			    p->key.type == key_type &&
+			    memcmp(p->key.arKey.s, str_index.v, real_length) == 0) {
 				return SUCCESS;
 			}
-			zend_u_hash_del(ht, IS_STRING, str_index, str_length);
-		} else if (key_type == HASH_KEY_IS_UNICODE) {
-			real_length = str_length * sizeof(UChar);
-			if (p->nKeyLength == str_length &&
-			    p->key.type == IS_UNICODE &&
-			    memcmp(p->key.arKey.u, str_index.u, real_length) == 0) {
-				return SUCCESS;
+
+			if (mode != HASH_UPDATE_KEY_ANYWAY) {
+				ulong h = zend_u_inline_hash_func(key_type, str_index, str_length);
+				Bucket *q = ht->arBuckets[h & ht->nTableMask];
+				int found = 0;
+
+				while (q != NULL) {
+					if (q == p) {
+						found = 1;
+					} else if (q->h == h && q->nKeyLength == str_length && 
+					           q->key.type == key_type &&
+					           memcmp(q->key.arKey.s, str_index.v, real_length) == 0) {
+					    if (found) {
+					    	if (mode & HASH_UPDATE_KEY_IF_BEFORE) {
+					    		break;
+					    	} else {
+								zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
+					    		return FAILURE;
+					    	}
+					    } else {
+					    	if (mode & HASH_UPDATE_KEY_IF_AFTER) {
+					    		break;
+					    	} else {
+								zend_u_hash_del(ht, p->key.type, ZSTR(p->key.arKey.s), p->nKeyLength);
+					    		return FAILURE;
+					    	}
+						}
+					}
+					q = q->pNext;
+				}
 			}
-			zend_u_hash_del(ht, IS_UNICODE, str_index, str_length);
+
+			zend_u_hash_del(ht, key_type, str_index, str_length);
 		} else {
 			return FAILURE;
 		}
@@ -1977,18 +2031,18 @@
 }
 /* }}} */
 
-ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength) /* {{{ */
+ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, int mode) /* {{{ */
 {
 	zend_uchar key_type;
 
 	if (type == IS_STRING) {
 		key_type = HASH_KEY_IS_STRING;
-		ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_update_current_key(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx));
+		ZEND_HANDLE_NUMERIC(arKey.s, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, NULL));
 	} else {
 		key_type = HASH_KEY_IS_UNICODE;
-		ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_update_current_key(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx));
+		ZEND_HANDLE_U_NUMERIC(arKey.u, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, NULL));
 	}
-	return zend_hash_update_current_key(ht, key_type, arKey, nKeyLength, 0);
+	return zend_hash_update_current_key_ex(ht, key_type, arKey, nKeyLength, 0, mode, NULL);
 }
 /* }}} */
 
@@ -2020,10 +2074,10 @@
 }
 /* }}} */
 
-ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength) /* {{{ */
+ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength, int mode) /* {{{ */
 {
-	ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx));
-	return zend_hash_update_current_key(ht, HASH_KEY_IS_STRING, ZSTR(arKey), nKeyLength, 0);
+	ZEND_HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_update_current_key_ex(ht, HASH_KEY_IS_LONG, NULL_ZSTR, 0, idx, mode, NULL));
+	return zend_hash_update_current_key_ex(ht, HASH_KEY_IS_STRING, ZSTR(arKey), nKeyLength, 0, mode, NULL);
 }
 /* }}} */
 
http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_hash.h?r1=1.95&r2=1.96&diff_format=u
Index: ZendEngine2/zend_hash.h
diff -u ZendEngine2/zend_hash.h:1.95 ZendEngine2/zend_hash.h:1.96
--- ZendEngine2/zend_hash.h:1.95	Thu Jul 24 19:50:22 2008
+++ ZendEngine2/zend_hash.h	Fri Aug  1 14:21:45 2008
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: zend_hash.h,v 1.95 2008/07/24 19:50:22 felipe Exp $ */
+/* $Id: zend_hash.h,v 1.96 2008/08/01 14:21:45 dmitry Exp $ */
 
 #ifndef ZEND_HASH_H
 #define ZEND_HASH_H
@@ -38,7 +38,10 @@
 #define HASH_DEL_INDEX 1
 #define HASH_DEL_KEY_QUICK 2
 
-
+#define HASH_UPDATE_KEY_IF_NONE    0
+#define HASH_UPDATE_KEY_IF_BEFORE  1
+#define HASH_UPDATE_KEY_IF_AFTER   2
+#define HASH_UPDATE_KEY_ANYWAY     3
 
 typedef ulong (*hash_func_t)(const char *arKey, uint nKeyLength);
 typedef int  (*compare_func_t)(const void *, const void * TSRMLS_DC);
@@ -240,7 +243,7 @@
 ZEND_API int zend_hash_get_current_data_ex(HashTable *ht, void **pData, HashPosition *pos);
 ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *pos);
 ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos);
-ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, HashPosition *pos);
+ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, zstr str_index, uint str_length, ulong num_index, int mode, HashPosition *pos);
 
 typedef struct _HashPointer {
 	HashPosition pos;
@@ -267,7 +270,7 @@
 #define zend_hash_internal_pointer_end(ht) \
 	zend_hash_internal_pointer_end_ex(ht, NULL)
 #define zend_hash_update_current_key(ht, key_type, str_index, str_length, num_index) \
-	zend_hash_update_current_key_ex(ht, key_type, str_index, str_length, num_index, NULL)
+	zend_hash_update_current_key_ex(ht, key_type, str_index, str_length, num_index, HASH_UPDATE_KEY_ANYWAY, NULL)
 
 /* Copying, merging and sorting */
 ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size);
@@ -371,7 +374,7 @@
 ZEND_API int zend_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength);
 ZEND_API int zend_symtable_find(HashTable *ht, const char *arKey, uint nKeyLength, void **pData);
 ZEND_API int zend_symtable_exists(HashTable *ht, const char *arKey, uint nKeyLength);
-ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength);
+ZEND_API int zend_symtable_update_current_key(HashTable *ht, const char *arKey, uint nKeyLength, int mode);
 
 ZEND_API int zend_ascii_symtable_update(HashTable *ht, const char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest);
 ZEND_API int zend_ascii_symtable_del(HashTable *ht, const char *arKey, uint nKeyLength);
@@ -392,7 +395,7 @@
 ZEND_API int zend_u_symtable_del(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength);
 ZEND_API int zend_u_symtable_find(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, void **pData);
 ZEND_API int zend_u_symtable_exists(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength);
-ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength);
+ZEND_API int zend_u_symtable_update_current_key(HashTable *ht, zend_uchar type, zstr arKey, uint nKeyLength, int mode);
 
 /* {{{ ZEND_HANDLE_*_NUMERIC macros */
 #define ZEND_HANDLE_NUMERIC(key, length, func) {										\
http://cvs.php.net/viewvc.cgi/ZendEngine2/tests/bug28072.phpt?r1=1.1&r2=1.2&diff_format=u
Index: ZendEngine2/tests/bug28072.phpt
diff -u ZendEngine2/tests/bug28072.phpt:1.1 ZendEngine2/tests/bug28072.phpt:1.2
--- ZendEngine2/tests/bug28072.phpt:1.1	Thu Jul  7 15:16:57 2005
+++ ZendEngine2/tests/bug28072.phpt	Fri Aug  1 14:21:46 2008
@@ -41,6 +41,6 @@
 )
 Array
 (
-    [a] => 111
+    [a] => 222
     [c] => 444
 )
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.