com php-src: Fixed bug #70258 and #70253: NEWS Zend/tests/bug70253.phpt Zend/tests/bug70258.phpt Zend/zend_hash.c Zend/zend_typ es.h
| From: | Xinchen Hui | Date: | Thu, 13 Aug 2015 04:08:57 +0000 |
| Subject: | com php-src: Fixed bug #70258 and #70253: NEWS Zend/tests/bug70253.phpt Zend/tests/bug70258.phpt Zend/zend_hash.c Zend/zend_typ es.h | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-88502@lists.php.net to get a copy of this message | ||
Commit: a089ce0cc6e0bade9bf94399a13bbd63448874b0
Author: Xinchen Hui <laruence@php.net> Thu, 13 Aug 2015 12:08:57 +0800
Parents: e17b1266dbcc55942fdfa6e62318104c2fa0f3be
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=a089ce0cc6e0bade9bf94399a13bbd63448874b0
Log:
Fixed bug #70258 and #70253
Bugs:
https://bugs.php.net/70258
https://bugs.php.net/70253
Changed paths:
M NEWS
A Zend/tests/bug70253.phpt
A Zend/tests/bug70258.phpt
M Zend/zend_hash.c
M Zend/zend_types.h
Diff:
diff --git a/NEWS b/NEWS
index aaf2417..3741df9 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,9 @@ PHP NEWS
20 Aug 2015, PHP 7.0.0 RC 1
- Core:
+ . Fixed bug #70258 (Segfault if do_resize fails to allocated memory).
+ (Laruence)
+ . Fixed bug #70253 (segfault at _efree () in zend_alloc..c:1389). (Laruence)
. Fixed bug #70240 (Segfault when doing unset($var());). (Laruence)
. Fixed bug #70223 (Incrementing value returned by magic getter). (Laruence)
. Fixed bug #70215 (Segfault when __invoke is static). (Bob)
diff --git a/Zend/tests/bug70253.phpt b/Zend/tests/bug70253.phpt
new file mode 100644
index 0000000..dd760df
--- /dev/null
+++ b/Zend/tests/bug70253.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #70253 (segfault at _efree () in zend_alloc.c:1389)
+--INI--
+memory_limit=2M
+--SKIPIF--
+<?php
+$zend_mm_enabled = getenv("USE_ZEND_ALLOC");
+if ($zend_mm_enabled === "0") {
+ die("skip Zend MM disabled");
+}
+?>
+--FILE--
+<?php
+unserialize('a:2:{i:0;O:9:"000000000":10000000');
+?>
+--EXPECTF--
+Fatal error: Allowed memory size of 2097152 bytes exhausted%s(tried to allocate %d bytes) in %s on
line %d
diff --git a/Zend/tests/bug70258.phpt b/Zend/tests/bug70258.phpt
new file mode 100644
index 0000000..5ffd7bf
--- /dev/null
+++ b/Zend/tests/bug70258.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #70258 (Segfault if do_resize fails to allocated memory)
+--INI--
+memory_limit=2M
+--SKIPIF--
+<?php
+$zend_mm_enabled = getenv("USE_ZEND_ALLOC");
+if ($zend_mm_enabled === "0") {
+ die("skip Zend MM disabled");
+}
+?>
+--FILE--
+<?php
+class A {
+ public $arr;
+ public function core() {
+ $this->arr["no_pack"] = 1;
+ while (1) {
+ $this->arr[] = 1;
+ }
+ }
+}
+
+$a = new A;
+$a->core();
+?>
+--EXPECTF--
+Fatal error: Allowed memory size of 2097152 bytes exhausted%s(tried to allocate %d bytes) in %s on
line %d
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 2347f99..7e06cf0 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -795,13 +795,15 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
zend_hash_rehash(ht);
HANDLE_UNBLOCK_INTERRUPTIONS();
} else if (ht->nTableSize < HT_MAX_SIZE) { /* Let's double the table size */
- void *old_data = HT_GET_DATA_ADDR(ht);
+ void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
+ uint32_t nSize = ht->nTableSize + ht->nTableSize;
Bucket *old_buckets = ht->arData;
HANDLE_BLOCK_INTERRUPTIONS();
- ht->nTableSize += ht->nTableSize;
+ new_data = pemalloc(HT_DATA_SIZE_EX(nSize) + HT_HASH_SIZE_EX(-nSize), ht->u.flags &
HASH_FLAG_PERSISTENT);
+ ht->nTableSize = nSize;
ht->nTableMask = -ht->nTableSize;
- HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
+ HT_SET_DATA_ADDR(ht, new_data);
memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
zend_hash_rehash(ht);
@@ -812,20 +814,22 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
}
ZEND_API void ZEND_FASTCALL zend_hash_resize(HashTable *ht, uint32_t nSize) {
- void *old_data = HT_GET_DATA_ADDR(ht);
+ nSize = zend_hash_check_size(nSize);
if (ht->u.flags & HASH_FLAG_INITIALIZED) {
+ void *new_data, *old_data = HT_GET_DATA_ADDR(ht);
Bucket *old_buckets = ht->arData;
HANDLE_BLOCK_INTERRUPTIONS();
- ht->nTableSize = zend_hash_check_size(nSize);
+ new_data = pemalloc(HT_DATA_SIZE_EX(nSize) + HT_HASH_SIZE_EX(-nSize), ht->u.flags &
HASH_FLAG_PERSISTENT);
+ ht->nTableSize = nSize;
ht->nTableMask = -ht->nTableSize;
- HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), ht->u.flags & HASH_FLAG_PERSISTENT));
+ HT_SET_DATA_ADDR(ht, new_data);
memcpy(ht->arData, old_buckets, sizeof(Bucket) * ht->nNumUsed);
pefree(old_data, ht->u.flags & HASH_FLAG_PERSISTENT);
zend_hash_rehash(ht);
HANDLE_UNBLOCK_INTERRUPTIONS();
} else {
- ht->nTableSize = zend_hash_check_size(nSize);
+ ht->nTableSize = nSize;
}
}
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index edcbe47..d4353f7 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -235,10 +235,14 @@ struct _zend_array {
#define HT_HASH(ht, idx) \
HT_HASH_EX((ht)->arData, idx)
+#define HT_HASH_SIZE_EX(nTableMask) \
+ (((size_t)(uint32_t)-(int32_t)(nTableMask)) * sizeof(uint32_t))
+#define HT_DATA_SIZE_EX(nTableSize) \
+ ((size_t)(nTableSize) * sizeof(Bucket))
#define HT_HASH_SIZE(ht) \
- (((size_t)(uint32_t)-(int32_t)(ht)->nTableMask) * sizeof(uint32_t))
+ HT_HASH_SIZE_EX((ht)->nTableMask)
#define HT_DATA_SIZE(ht) \
- ((size_t)(ht)->nTableSize * sizeof(Bucket))
+ HT_DATA_SIZE_EX((ht)->nTableSize)
#define HT_SIZE(ht) \
(HT_HASH_SIZE(ht) + HT_DATA_SIZE(ht))
#define HT_USED_SIZE(ht) \