From abaf9a76dc933f4d1f2ff3591ced81d4d6dcb652 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 3 Oct 2019 19:23:05 +0200 Subject: [PATCH] Fix #78620: Out of memory error The integer addition in `ZEND_MM_ALIGNED_SIZE_EX` can overflow, what we have to catch early. --- NEWS | 1 + Zend/zend_alloc.c | 9 +++++++-- .../tests/strings/wordwrap_memory_limit.phpt | 1 + .../strings/wordwrap_memory_limit_win32.phpt | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 ext/standard/tests/strings/wordwrap_memory_limit_win32.phpt diff --git a/NEWS b/NEWS index 26abd33994..a04f3bf3f8 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ PHP NEWS - Core: . Fixed bug #78535 (auto_detect_line_endings value not parsed as bool). (bugreportuser) + . Fixed bug #78620 (Out of memory error). (cmb, Nikita) - Exif: . Fixed bug #78442 ('Illegal component' on exif_read_data since PHP7) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 3a43027346..f4a6179516 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -1723,12 +1723,17 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D * We allocate them with 2MB size granularity, to avoid many * reallocations when they are extended by small pieces */ - size_t new_size = ZEND_MM_ALIGNED_SIZE_EX(size, MAX(REAL_PAGE_SIZE, ZEND_MM_CHUNK_SIZE)); + size_t alignment = MAX(REAL_PAGE_SIZE, ZEND_MM_CHUNK_SIZE); #else - size_t new_size = ZEND_MM_ALIGNED_SIZE_EX(size, REAL_PAGE_SIZE); + size_t alignment = REAL_PAGE_SIZE; #endif + size_t new_size = ZEND_MM_ALIGNED_SIZE_EX(size, alignment); void *ptr; + if (UNEXPECTED(new_size < size)) { + zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", size, alignment); + } + #if ZEND_MM_LIMIT if (UNEXPECTED(new_size > heap->limit - heap->real_size)) { if (zend_mm_gc(heap) && new_size <= heap->limit - heap->real_size) { diff --git a/ext/standard/tests/strings/wordwrap_memory_limit.phpt b/ext/standard/tests/strings/wordwrap_memory_limit.phpt index fb0cc5c3bc..21340153fa 100644 --- a/ext/standard/tests/strings/wordwrap_memory_limit.phpt +++ b/ext/standard/tests/strings/wordwrap_memory_limit.phpt @@ -2,6 +2,7 @@ No overflow should occur during the memory_limit check for wordwrap() --SKIPIF-- --INI-- diff --git a/ext/standard/tests/strings/wordwrap_memory_limit_win32.phpt b/ext/standard/tests/strings/wordwrap_memory_limit_win32.phpt new file mode 100644 index 0000000000..e0e76b5800 --- /dev/null +++ b/ext/standard/tests/strings/wordwrap_memory_limit_win32.phpt @@ -0,0 +1,19 @@ +--TEST-- +No overflow should occur during the memory_limit check for wordwrap() +--SKIPIF-- + +--INI-- +memory_limit=128M +--FILE-- + +--EXPECTF-- +Fatal error: Possible integer overflow in memory allocation (4294901777 + %d) in %s on line %d -- 2.40.0