php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #60655
Patch rand_hash_resize.patch revision 2012-01-05 08:09 UTC by laruence@php.net
Patch max_input_vars.patch revision 2012-01-05 05:04 UTC by laruence@php.net
revision 2012-01-05 05:03 UTC by laruence@php.net
revision 2012-01-05 05:02 UTC by laruence@php.net
revision 2012-01-05 04:17 UTC by laruence@php.net
revision 2012-01-05 04:08 UTC by laruence@php.net

Patch rand_hash_resize.patch for *General Issues Bug #60655

Patch version 2012-01-05 08:09 UTC

Return to Bug #60655 | Download this patch
Patch Revisions:

Developer: laruence@php.net

Index: Zend/zend_string.c
===================================================================
--- Zend/zend_string.c	(revision 321772)
+++ Zend/zend_string.c	(working copy)
@@ -91,7 +91,7 @@
 	}
 
 	h = zend_inline_hash_func(arKey, nKeyLength);
-	nIndex = h & CG(interned_strings).nTableMask;
+	nIndex = h % (CG(interned_strings).nTableMask + 1);
 	p = CG(interned_strings).arBuckets[nIndex];
 	while (p != NULL) {
 		if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
Index: Zend/zend_hash.c
===================================================================
--- Zend/zend_hash.c	(revision 321772)
+++ Zend/zend_hash.c	(working copy)
@@ -21,6 +21,13 @@
 
 #include "zend.h"
 #include "zend_globals.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#if HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
 
 #define CONNECT_TO_BUCKET_DLLIST(element, list_head)		\
 	(element)->pNext = (list_head);							\
@@ -43,6 +50,8 @@
 		(ht)->pInternalPointer = (element);					\
 	}
 
+#define GET_INDEX_OFFSET(ht, h) ((h) % ((ht)->nTableMask + 1))
+
 #if ZEND_DEBUG
 #define HT_OK				0
 #define HT_IS_DESTROYING	1
@@ -145,6 +154,65 @@
  
 static const Bucket *uninitialized_bucket = NULL;
 
+static void zend_hash_random(unsigned char *buf, size_t size)
+{
+	size_t i = 0;
+	unsigned char t;
+
+#ifdef ZEND_WIN32
+	HCRYPTPROV   hCryptProv;
+	int has_context = 0;
+
+	if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
+		/* Could mean that the key container does not exist, let try 
+		   again by asking for a new one */
+		if (GetLastError() == NTE_BAD_KEYSET) {
+			if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
+				has_context = 1;
+			}
+		}
+	} else {
+		has_context = 1;
+	}
+	if (has_context) {
+		do {
+			BOOL ret = CryptGenRandom(hCryptProv, size, buf);
+			CryptReleaseContext(hCryptProv, 0);
+			if (ret) {
+				while (i < size && buf[i] != 0) {
+					i++;
+				}
+				if (i == size) {
+					return;
+				}
+		   }
+		} while (0);
+	}
+#elif defined(HAVE_DEV_URANDOM)
+	int fd = open("/dev/urandom", 0);
+
+	if (fd >= 0) {
+		if (read(fd, buf, size) == size) {
+			while (i < size && buf[i] != 0) {
+				i++;
+			}
+			if (i == size) {
+				close(fd);
+			    return;
+			}
+		}
+		close(fd);
+	}
+#endif
+	t = (unsigned char)getpid();
+	while (i < size) {
+		do {
+			buf[i] = ((unsigned char)rand()) ^ t;
+		} while (buf[i] == 0);
+		t = buf[i++] << 1;
+    }
+}
+
 ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
 {
 	uint i = 3;
@@ -213,7 +281,7 @@
 	CHECK_INIT(ht);
 
 	h = zend_inline_hash_func(arKey, nKeyLength);
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -290,7 +358,7 @@
 	}
 
 	CHECK_INIT(ht);
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 	
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -378,7 +446,7 @@
 	if (flag & HASH_NEXT_INSERT) {
 		h = ht->nNextFreeElement;
 	}
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -440,19 +508,22 @@
 static int zend_hash_do_resize(HashTable *ht)
 {
 	Bucket **t;
+	uint size, r;
 #ifdef ZEND_SIGNALS
 	TSRMLS_FETCH();
 #endif
 
 	IS_CONSISTENT(ht);
 
-	if ((ht->nTableSize << 1) > 0) {	/* Let's double the table size */
-		t = (Bucket **) perealloc_recoverable(ht->arBuckets, (ht->nTableSize << 1) * sizeof(Bucket *), ht->persistent);
+	zend_hash_random((unsigned char *)&r, sizeof(uint));
+	size = (ht->nTableSize << 1) + (r & ht->nTableMask);
+	if (size > 0) {
+		t = (Bucket **) perealloc_recoverable(ht->arBuckets, (size) * sizeof(Bucket *), ht->persistent);
 		if (t) {
 			HANDLE_BLOCK_INTERRUPTIONS();
 			ht->arBuckets = t;
-			ht->nTableSize = (ht->nTableSize << 1);
-			ht->nTableMask = ht->nTableSize - 1;
+			ht->nTableSize = size;
+			ht->nTableMask = size - 1;
 			zend_hash_rehash(ht);
 			HANDLE_UNBLOCK_INTERRUPTIONS();
 			return SUCCESS;
@@ -475,7 +546,7 @@
 	memset(ht->arBuckets, 0, ht->nTableSize * sizeof(Bucket *));
 	p = ht->pListHead;
 	while (p != NULL) {
-		nIndex = p->h & ht->nTableMask;
+		nIndex = GET_INDEX_OFFSET(ht, p->h);
 		CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
 		ht->arBuckets[nIndex] = p;
 		p = p->pListNext;
@@ -496,7 +567,7 @@
 	if (flag == HASH_DEL_KEY) {
 		h = zend_inline_hash_func(arKey, nKeyLength);
 	}
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -620,7 +691,7 @@
 	} else {
 		uint nIndex;
 
-		nIndex = p->h & ht->nTableMask;
+		nIndex = GET_INDEX_OFFSET(ht, p->h);
 		ht->arBuckets[nIndex] = p->pNext;
 	}
 	if (p->pNext) {
@@ -919,7 +990,7 @@
 	IS_CONSISTENT(ht);
 
 	h = zend_inline_hash_func(arKey, nKeyLength);
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -945,7 +1016,7 @@
 
 	IS_CONSISTENT(ht);
 
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -969,7 +1040,7 @@
 	IS_CONSISTENT(ht);
 
 	h = zend_inline_hash_func(arKey, nKeyLength);
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -994,7 +1065,7 @@
 
 	IS_CONSISTENT(ht);
 
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -1016,7 +1087,7 @@
 
 	IS_CONSISTENT(ht);
 
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -1037,7 +1108,7 @@
 
 	IS_CONSISTENT(ht);
 
-	nIndex = h & ht->nTableMask;
+	nIndex = GET_INDEX_OFFSET(ht, h);
 
 	p = ht->arBuckets[nIndex];
 	while (p != NULL) {
@@ -1078,7 +1149,7 @@
 		Bucket *p;
 
 		IS_CONSISTENT(ht);
-		p = ht->arBuckets[ptr->h & ht->nTableMask];
+		p = ht->arBuckets[GET_INDEX_OFFSET(ht, ptr->h)];
 		while (p != NULL) {
 			if (p == ptr->pos) {
 				ht->pInternalPointer = p;
@@ -1229,7 +1300,7 @@
 				return SUCCESS;
 			}
 
-			q = ht->arBuckets[num_index & ht->nTableMask];
+			q = ht->arBuckets[GET_INDEX_OFFSET(ht, num_index)];
 			while (q != NULL) {
 				if (!q->nKeyLength && q->h == num_index) {
 					break;
@@ -1250,7 +1321,7 @@
 				return SUCCESS;
 			}
 
-			q = ht->arBuckets[h & ht->nTableMask];
+			q = ht->arBuckets[GET_INDEX_OFFSET(ht, h)];
 
 			while (q != NULL) {
 				if (q->arKey == str_index ||
@@ -1280,8 +1351,8 @@
 				}
 				if (mode & found) {
 					/* delete current bucket */
-					if (p == ht->arBuckets[p->h & ht->nTableMask]) {
-						ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
+					if (p == ht->arBuckets[GET_INDEX_OFFSET(ht, p->h)]) {
+						ht->arBuckets[GET_INDEX_OFFSET(ht, p->h)] = p->pNext;
 					} else {
 						p->pLast->pNext = p->pNext;
 					}
@@ -1315,8 +1386,8 @@
 				}
 			}
 			/* delete another bucket with the same key */
-			if (q == ht->arBuckets[q->h & ht->nTableMask]) {
-				ht->arBuckets[q->h & ht->nTableMask] = q->pNext;
+			if (q == ht->arBuckets[GET_INDEX_OFFSET(ht, q->h)]) {
+				ht->arBuckets[GET_INDEX_OFFSET(ht, q->h)] = q->pNext;
 			} else {
 				q->pLast->pNext = q->pNext;
 			}
@@ -1353,7 +1424,7 @@
 		if (p->pLast) {
 			p->pLast->pNext = p->pNext;
 		} else {
-			ht->arBuckets[p->h & ht->nTableMask] = p->pNext;
+			ht->arBuckets[GET_INDEX_OFFSET(ht, p->h)] = p->pNext;
 		}
 
 		if ((IS_INTERNED(p->arKey) != IS_INTERNED(str_index)) ||
@@ -1408,8 +1479,8 @@
 			}
 		}
 
-		CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
-		ht->arBuckets[p->h & ht->nTableMask] = p;
+		CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[GET_INDEX_OFFSET(ht, p->h)]);
+		ht->arBuckets[GET_INDEX_OFFSET(ht, p->h)] = p;
 		HANDLE_UNBLOCK_INTERRUPTIONS();
 
 		return SUCCESS;
Index: main/php_globals.h
===================================================================
--- main/php_globals.h	(revision 321772)
+++ main/php_globals.h	(working copy)
@@ -146,7 +146,6 @@
 	zend_bool com_initialized;
 #endif
 	long max_input_nesting_level;
-	long max_input_vars;
 	zend_bool in_user_include;
 
 	char *user_ini_filename;
Index: main/php_variables.c
===================================================================
--- main/php_variables.c	(revision 321772)
+++ main/php_variables.c	(working copy)
@@ -178,15 +178,10 @@
 			} else {
 				escaped_index = index;
 				if (zend_symtable_find(symtable1, escaped_index, index_len + 1, (void **) &gpc_element_p) == FAILURE
-					|| Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {
-					if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
-						if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
-							php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
-						}
-						MAKE_STD_ZVAL(gpc_element);
-						array_init(gpc_element);
-						zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
-					}
+						|| Z_TYPE_PP(gpc_element_p) != IS_ARRAY) {
+					MAKE_STD_ZVAL(gpc_element);
+					array_init(gpc_element);
+					zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
 				}
 				if (index != escaped_index) {
 					efree(escaped_index);
@@ -225,14 +220,7 @@
 				zend_symtable_exists(symtable1, escaped_index, index_len + 1)) {
 				zval_ptr_dtor(&gpc_element);
 			} else {
-				if (zend_hash_num_elements(symtable1) <= PG(max_input_vars)) {
-					if (zend_hash_num_elements(symtable1) == PG(max_input_vars)) {
-						php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars));
-					}
-					zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
-				} else {
-					zval_ptr_dtor(&gpc_element);
-				}
+				zend_symtable_update(symtable1, escaped_index, index_len + 1, &gpc_element, sizeof(zval *), (void **) &gpc_element_p);
 			}
 			if (escaped_index != index) {
 				efree(escaped_index);
Index: main/main.c
===================================================================
--- main/main.c	(revision 321772)
+++ main/main.c	(working copy)
@@ -531,7 +531,6 @@
 	STD_PHP_INI_ENTRY("post_max_size",			"8M",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateLong,			post_max_size,			sapi_globals_struct,sapi_globals)
 	STD_PHP_INI_ENTRY("upload_tmp_dir",			NULL,		PHP_INI_SYSTEM,		OnUpdateStringUnempty,	upload_tmp_dir,			php_core_globals,	core_globals)
 	STD_PHP_INI_ENTRY("max_input_nesting_level", "64",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateLongGEZero,	max_input_nesting_level,			php_core_globals,	core_globals)
-	STD_PHP_INI_ENTRY("max_input_vars",			"1000",		PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateLongGEZero,	max_input_vars,						php_core_globals,	core_globals)
 
 	STD_PHP_INI_ENTRY("user_dir",				NULL,		PHP_INI_SYSTEM,		OnUpdateString,			user_dir,				php_core_globals,	core_globals)
 	STD_PHP_INI_ENTRY("variables_order",		"EGPCS",	PHP_INI_SYSTEM|PHP_INI_PERDIR,		OnUpdateStringUnempty,	variables_order,		php_core_globals,	core_globals)
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Sat Oct 19 05:01:27 2019 UTC