Skip to content

Commit 16d35eb

Browse files
committed
Fix overflow in memory limit checks
Due to overflows in the memory limit checks, we were missing cases where the allocation size was close to the address space size, and caused an OOM condition rather than a memory limit error.
1 parent 4b4a656 commit 16d35eb

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

Zend/zend_alloc.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ static void *zend_mm_alloc_pages(zend_mm_heap *heap, uint32_t pages_count ZEND_F
980980
heap->cached_chunks = chunk->next;
981981
} else {
982982
#if ZEND_MM_LIMIT
983-
if (UNEXPECTED(heap->real_size + ZEND_MM_CHUNK_SIZE > heap->limit)) {
983+
if (UNEXPECTED(ZEND_MM_CHUNK_SIZE > heap->limit - heap->real_size)) {
984984
if (zend_mm_gc(heap)) {
985985
goto get_chunk;
986986
} else if (heap->overflow == 0) {
@@ -1484,8 +1484,8 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size, si
14841484
}
14851485
} else /* if (new_size > old_size) */ {
14861486
#if ZEND_MM_LIMIT
1487-
if (UNEXPECTED(heap->real_size + (new_size - old_size) > heap->limit)) {
1488-
if (zend_mm_gc(heap) && heap->real_size + (new_size - old_size) <= heap->limit) {
1487+
if (UNEXPECTED(new_size - old_size > heap->limit - heap->real_size)) {
1488+
if (zend_mm_gc(heap) && new_size - old_size <= heap->limit - heap->real_size) {
14891489
/* pass */
14901490
} else if (heap->overflow == 0) {
14911491
#if ZEND_DEBUG
@@ -1730,8 +1730,8 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
17301730
void *ptr;
17311731

17321732
#if ZEND_MM_LIMIT
1733-
if (UNEXPECTED(heap->real_size + new_size > heap->limit)) {
1734-
if (zend_mm_gc(heap) && heap->real_size + new_size <= heap->limit) {
1733+
if (UNEXPECTED(new_size > heap->limit - heap->real_size)) {
1734+
if (zend_mm_gc(heap) && new_size <= heap->limit - heap->real_size) {
17351735
/* pass */
17361736
} else if (heap->overflow == 0) {
17371737
#if ZEND_DEBUG
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
No overflow should occur during the memory_limit check for wordwrap()
3+
--SKIPIF--
4+
<?php
5+
if (getenv("USE_ZEND_ALLOC") === "0") die("skip Zend MM disabled");
6+
?>
7+
--INI--
8+
memory_limit=128M
9+
--FILE--
10+
<?php
11+
12+
$str = str_repeat('x', 65534);
13+
$str2 = str_repeat('x', 65535);
14+
wordwrap($str, 1, $str2);
15+
16+
?>
17+
--EXPECTF--
18+
Fatal error: Allowed memory size of 134217728 bytes exhausted%s(tried to allocate %d bytes) in %s on line %d

0 commit comments

Comments
 (0)