Skip to content

Commit 382f95e

Browse files
committed
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: (25 commits) Fix return code (merges are hard :( ) fix bad merge Fix bug #68113 (Heap corruption in exif_thumbnail()) Fix bug #68089 - do not accept options with embedded \0 Fixed bug #68044: Integer overflow in unserialize() (32-bits only) Fix bug #68027 - fix date parsing in XMLRPC lib Fix bug #68113 (Heap corruption in exif_thumbnail()) Fix bug #68089 - do not accept options with embedded \0 Fixed bug #68044: Integer overflow in unserialize() (32-bits only) Fix bug #68027 - fix date parsing in XMLRPC lib Fix bug #68113 (Heap corruption in exif_thumbnail()) Fix bug #68089 - do not accept options with embedded \0 Fixed bug #68044: Integer overflow in unserialize() (32-bits only) Fix bug #68027 - fix date parsing in XMLRPC lib Fixed bug #68128 Added API function to retrive current custom heap handlers update NEWS and UPGRADING Allow to substitute storage layer in memory manager. Upated NEWS Address issues raised by @nikic ...
2 parents 766eb01 + 01d1722 commit 382f95e

24 files changed

+686
-317
lines changed

Zend/zend_alloc.c

+159-14
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@
119119
# define ZEND_MM_CUSTOM 1 /* support for custom memory allocator */
120120
/* USE_ZEND_ALLOC=0 may switch to system malloc() */
121121
#endif
122+
#ifndef ZEND_MM_STORAGE
123+
# define ZEND_MM_STORAGE 1 /* support for custom memory storage */
124+
#endif
122125
#ifndef ZEND_MM_ERROR
123126
# define ZEND_MM_ERROR 1 /* report system errors */
124127
#endif
@@ -217,6 +220,9 @@ struct _zend_mm_heap {
217220
#if ZEND_MM_CUSTOM
218221
int use_custom_heap;
219222
#endif
223+
#if ZEND_MM_STORAGE
224+
zend_mm_storage *storage;
225+
#endif
220226
#if ZEND_MM_STAT
221227
size_t size; /* current memory usage */
222228
size_t peak; /* peak memory usage */
@@ -707,7 +713,7 @@ static zend_always_inline int zend_mm_bitset_is_free_range(zend_mm_bitset *bitse
707713
/* Chunks */
708714
/**********/
709715

710-
static void *zend_mm_chunk_alloc(size_t size, size_t alignment)
716+
static void *zend_mm_chunk_alloc_int(size_t size, size_t alignment)
711717
{
712718
void *ptr = zend_mm_mmap(size);
713719

@@ -751,6 +757,40 @@ static void *zend_mm_chunk_alloc(size_t size, size_t alignment)
751757
}
752758
}
753759

760+
static void *zend_mm_chunk_alloc(zend_mm_heap *heap, size_t size, size_t alignment)
761+
{
762+
#if ZEND_MM_STORAGE
763+
if (UNEXPECTED(heap->storage)) {
764+
void *ptr = heap->storage->chunk_alloc(heap->storage, size, alignment);
765+
ZEND_ASSERT(((zend_uintptr_t)((char*)ptr + (alignment-1)) & (alignment-1)) == (zend_uintptr_t)ptr);
766+
return ptr;
767+
}
768+
#endif
769+
return zend_mm_chunk_alloc_int(size, alignment);
770+
}
771+
772+
static void zend_mm_chunk_free(zend_mm_heap *heap, void *addr, size_t size)
773+
{
774+
#if ZEND_MM_STORAGE
775+
if (UNEXPECTED(heap->storage)) {
776+
heap->storage->chunk_free(heap->storage, addr, size);
777+
return;
778+
}
779+
#endif
780+
zend_mm_munmap(addr, size);
781+
}
782+
783+
static void zend_mm_chunk_truncate(zend_mm_heap *heap, void *addr, size_t old_size, size_t new_size)
784+
{
785+
#if ZEND_MM_STORAGE
786+
if (UNEXPECTED(heap->storage)) {
787+
heap->storage->chunk_truncate(heap->storage, addr, old_size, new_size);
788+
return;
789+
}
790+
#endif
791+
zend_mm_munmap((char*)addr + new_size, old_size - new_size);
792+
}
793+
754794
static zend_always_inline void zend_mm_chunk_init(zend_mm_heap *heap, zend_mm_chunk *chunk)
755795
{
756796
chunk->heap = heap;
@@ -928,7 +968,7 @@ static void *zend_mm_alloc_pages(zend_mm_heap *heap, int pages_count ZEND_FILE_L
928968
}
929969
}
930970
#endif
931-
chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
971+
chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(heap, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
932972
if (UNEXPECTED(chunk == NULL)) {
933973
/* insufficient memory */
934974
#if !ZEND_MM_LIMIT
@@ -1019,11 +1059,11 @@ static void zend_mm_free_pages(zend_mm_heap *heap, zend_mm_chunk *chunk, int pag
10191059
heap->real_size -= ZEND_MM_CHUNK_SIZE;
10201060
#endif
10211061
if (!heap->cached_chunks || chunk->num > heap->cached_chunks->num) {
1022-
zend_mm_munmap(chunk, ZEND_MM_CHUNK_SIZE);
1062+
zend_mm_chunk_free(heap, chunk, ZEND_MM_CHUNK_SIZE);
10231063
} else {
10241064
//TODO: select the best chunk to delete???
10251065
chunk->next = heap->cached_chunks->next;
1026-
zend_mm_munmap(heap->cached_chunks, ZEND_MM_CHUNK_SIZE);
1066+
zend_mm_chunk_free(heap, heap->cached_chunks, ZEND_MM_CHUNK_SIZE);
10271067
heap->cached_chunks = chunk;
10281068
}
10291069
}
@@ -1355,7 +1395,7 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size ZEN
13551395
#ifndef _WIN32
13561396
} else if (new_size < old_size) {
13571397
/* unmup tail */
1358-
zend_mm_munmap((char*)ptr + new_size, old_size - new_size);
1398+
zend_mm_chunk_truncate(heap, ptr, old_size, new_size);
13591399
#if ZEND_MM_STAT || ZEND_MM_LIMIT
13601400
heap->real_size -= old_size - new_size;
13611401
#endif
@@ -1607,7 +1647,7 @@ static void *zend_mm_alloc_huge(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_D
16071647
}
16081648
}
16091649
#endif
1610-
ptr = zend_mm_chunk_alloc(new_size, ZEND_MM_CHUNK_SIZE);
1650+
ptr = zend_mm_chunk_alloc(heap, new_size, ZEND_MM_CHUNK_SIZE);
16111651
if (UNEXPECTED(ptr == NULL)) {
16121652
/* insufficient memory */
16131653
#if !ZEND_MM_LIMIT
@@ -1649,7 +1689,7 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
16491689

16501690
ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(ptr, ZEND_MM_CHUNK_SIZE) == 0, "zend_mm_heap corrupted");
16511691
size = zend_mm_del_huge_block(heap, ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
1652-
zend_mm_munmap(ptr, size);
1692+
zend_mm_chunk_free(heap, ptr, size);
16531693
#if ZEND_MM_STAT || ZEND_MM_LIMIT
16541694
heap->real_size -= size;
16551695
#endif
@@ -1662,9 +1702,9 @@ static void zend_mm_free_huge(zend_mm_heap *heap, void *ptr ZEND_FILE_LINE_DC ZE
16621702
/* Initialization */
16631703
/******************/
16641704

1665-
zend_mm_heap *zend_mm_init(void)
1705+
static zend_mm_heap *zend_mm_init(void)
16661706
{
1667-
zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
1707+
zend_mm_chunk *chunk = (zend_mm_chunk*)zend_mm_chunk_alloc_int(ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
16681708
zend_mm_heap *heap;
16691709

16701710
if (UNEXPECTED(chunk == NULL)) {
@@ -1706,6 +1746,9 @@ zend_mm_heap *zend_mm_init(void)
17061746
#endif
17071747
#if ZEND_MM_CUSTOM
17081748
heap->use_custom_heap = 0;
1749+
#endif
1750+
#if ZEND_MM_STORAGE
1751+
heap->storage = NULL;
17091752
#endif
17101753
heap->huge_list = NULL;
17111754
return heap;
@@ -1805,7 +1848,7 @@ static void zend_mm_check_leaks(zend_mm_heap *heap TSRMLS_DC)
18051848
}
18061849

18071850
list = list->next;
1808-
zend_mm_munmap(q->ptr, q->size);
1851+
zend_mm_chunk_free(heap, q->ptr, q->size);
18091852
zend_mm_free_heap(heap, q, NULL, 0, NULL, 0);
18101853
}
18111854

@@ -1904,7 +1947,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC)
19041947
while (list) {
19051948
zend_mm_huge_list *q = list;
19061949
list = list->next;
1907-
zend_mm_munmap(q->ptr, q->size);
1950+
zend_mm_chunk_free(heap, q->ptr, q->size);
19081951
}
19091952

19101953
/* move all chunks except of the first one into the cache */
@@ -1923,10 +1966,20 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC)
19231966
while (heap->cached_chunks) {
19241967
p = heap->cached_chunks;
19251968
heap->cached_chunks = p->next;
1926-
zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE);
1969+
zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE);
19271970
}
19281971
/* free the first chunk */
1929-
zend_mm_munmap(heap->main_chunk, ZEND_MM_CHUNK_SIZE);
1972+
#if ZEND_MM_STORAGE
1973+
if (UNEXPECTED(heap->storage)) {
1974+
zend_mm_storage *storage = heap->storage;
1975+
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
1976+
storage->dtor(storage);
1977+
} else {
1978+
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
1979+
}
1980+
#else
1981+
zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE);
1982+
#endif
19301983
} else {
19311984
zend_mm_heap old_heap;
19321985

@@ -1936,7 +1989,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent TSRMLS_DC)
19361989
heap->cached_chunks) {
19371990
p = heap->cached_chunks;
19381991
heap->cached_chunks = p->next;
1939-
zend_mm_munmap(p, ZEND_MM_CHUNK_SIZE);
1992+
zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE);
19401993
heap->cached_chunks_count--;
19411994
}
19421995
/* clear cached chunks */
@@ -2343,6 +2396,98 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
23432396
#endif
23442397
}
23452398

2399+
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
2400+
void* (**_malloc)(size_t),
2401+
void (**_free)(void*),
2402+
void* (**_realloc)(void*, size_t))
2403+
{
2404+
#if ZEND_MM_CUSTOM
2405+
zend_mm_heap *_heap = (zend_mm_heap*)heap;
2406+
2407+
if (heap->use_custom_heap) {
2408+
*_malloc = _heap->_malloc;
2409+
*_free = _heap->_free;
2410+
*_realloc = _heap->_realloc;
2411+
} else {
2412+
*_malloc = NULL;
2413+
*_free = NULL;
2414+
*_realloc = NULL;
2415+
}
2416+
#else
2417+
*_malloc = NULL;
2418+
*_free = NULL;
2419+
*_realloc = NULL;
2420+
#endif
2421+
}
2422+
2423+
ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap)
2424+
{
2425+
#if ZEND_MM_CUSTOM
2426+
return heap->storage;
2427+
#else
2428+
return NULL
2429+
#endif
2430+
}
2431+
2432+
ZEND_API zend_mm_heap *zend_mm_startup(void)
2433+
{
2434+
return zend_mm_init();
2435+
}
2436+
2437+
ZEND_API zend_mm_heap *zend_mm_startup_ex(zend_mm_storage *storage)
2438+
{
2439+
#if ZEND_MM_STORAGE
2440+
zend_mm_chunk *chunk = (zend_mm_chunk*)storage->chunk_alloc(storage, ZEND_MM_CHUNK_SIZE, ZEND_MM_CHUNK_SIZE);
2441+
zend_mm_heap *heap;
2442+
2443+
if (UNEXPECTED(chunk == NULL)) {
2444+
#if ZEND_MM_ERROR
2445+
#ifdef _WIN32
2446+
stderr_last_error("Can't initialize heap");
2447+
#else
2448+
fprintf(stderr, "\nCan't initialize heap: [%d] %s\n", errno, strerror(errno));
2449+
#endif
2450+
#endif
2451+
return NULL;
2452+
}
2453+
heap = &chunk->heap_slot;
2454+
chunk->heap = heap;
2455+
chunk->next = chunk;
2456+
chunk->prev = chunk;
2457+
chunk->free_pages = ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE;
2458+
chunk->free_tail = ZEND_MM_FIRST_PAGE;
2459+
chunk->num = 0;
2460+
chunk->free_map[0] = (Z_L(1) << ZEND_MM_FIRST_PAGE) - 1;
2461+
chunk->map[0] = ZEND_MM_LRUN(ZEND_MM_FIRST_PAGE);
2462+
heap->main_chunk = chunk;
2463+
heap->cached_chunks = NULL;
2464+
heap->chunks_count = 1;
2465+
heap->peak_chunks_count = 1;
2466+
heap->cached_chunks_count = 0;
2467+
heap->avg_chunks_count = 1.0;
2468+
#if ZEND_MM_STAT || ZEND_MM_LIMIT
2469+
heap->real_size = ZEND_MM_CHUNK_SIZE;
2470+
#endif
2471+
#if ZEND_MM_STAT
2472+
heap->real_peak = ZEND_MM_CHUNK_SIZE;
2473+
heap->size = 0;
2474+
heap->peak = 0;
2475+
#endif
2476+
#if ZEND_MM_LIMIT
2477+
heap->limit = (Z_L(-1) >> Z_L(1));
2478+
heap->overflow = 0;
2479+
#endif
2480+
#if ZEND_MM_CUSTOM
2481+
heap->use_custom_heap = 0;
2482+
#endif
2483+
heap->storage = storage;
2484+
heap->huge_list = NULL;
2485+
return heap;
2486+
#else
2487+
return NULL;
2488+
#endif
2489+
}
2490+
23462491
/*
23472492
* Local variables:
23482493
* tab-width: 4

Zend/zend_alloc.h

+21
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,27 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap,
259259
void* (*_malloc)(size_t),
260260
void (*_free)(void*),
261261
void* (*_realloc)(void*, size_t));
262+
ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap,
263+
void* (**_malloc)(size_t),
264+
void (**_free)(void*),
265+
void* (**_realloc)(void*, size_t));
266+
267+
typedef struct _zend_mm_storage zend_mm_storage;
268+
269+
typedef void* (*zend_mm_chunk_alloc_t)(zend_mm_storage *storage, size_t size, size_t alignment);
270+
typedef void (*zend_mm_chunk_free_t)(zend_mm_storage *storage, void *chunk, size_t size);
271+
typedef void (*zend_mm_chunk_truncate_t)(zend_mm_storage *storage, void *chunk, size_t old_size, size_t new_size);
272+
typedef void (*zend_mm_storage_dtor_t)(zend_mm_storage *storage);
273+
274+
struct _zend_mm_storage {
275+
zend_mm_chunk_alloc_t chunk_alloc;
276+
zend_mm_chunk_free_t chunk_free;
277+
zend_mm_chunk_truncate_t chunk_truncate;
278+
zend_mm_storage_dtor_t dtor;
279+
};
280+
281+
ZEND_API zend_mm_storage *zend_mm_get_storage(zend_mm_heap *heap);
282+
ZEND_API zend_mm_heap *zend_mm_startup_ex(zend_mm_storage *storage);
262283

263284
END_EXTERN_C()
264285

ext/curl/interface.c

+5
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ static int php_curl_option_str(php_curl *ch, zend_long option, const char *str,
170170
{
171171
CURLcode error = CURLE_OK;
172172

173+
if (strlen(str) != len) {
174+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Curl option contains invalid characters (\\0)");
175+
return FAILURE;
176+
}
177+
173178
#if LIBCURL_VERSION_NUM >= 0x071100
174179
if (make_copy) {
175180
#endif

ext/curl/tests/bug68089.phpt

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Bug #68089 (NULL byte injection - cURL lib)
3+
--SKIPIF--
4+
<?php
5+
include 'skipif.inc';
6+
7+
?>
8+
--FILE--
9+
<?php
10+
$url = "file:///etc/passwd\0http://google.com";
11+
$ch = curl_init();
12+
var_dump(curl_setopt($ch, CURLOPT_URL, $url));
13+
?>
14+
Done
15+
--EXPECTF--
16+
Warning: curl_setopt(): Curl option contains invalid characters (\0) in %s/bug68089.php on line 4
17+
bool(false)
18+
Done

ext/exif/exif.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2413,11 +2413,11 @@ static void* exif_ifd_make_value(image_info_data *info_data, int motorola_intel
24132413
data_ptr += 8;
24142414
break;
24152415
case TAG_FMT_SINGLE:
2416-
memmove(data_ptr, &info_data->value.f, byte_count);
2416+
memmove(data_ptr, &info_value->f, 4);
24172417
data_ptr += 4;
24182418
break;
24192419
case TAG_FMT_DOUBLE:
2420-
memmove(data_ptr, &info_data->value.d, byte_count);
2420+
memmove(data_ptr, &info_value->d, 8);
24212421
data_ptr += 8;
24222422
break;
24232423
}

ext/exif/tests/bug68113.jpg

368 Bytes
Loading

ext/exif/tests/bug68113.phpt

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Bug #68113 (Heap corruption in exif_thumbnail())
3+
--SKIPIF--
4+
<?php
5+
extension_loaded("exif") or die("skip need exif");
6+
?>
7+
--FILE--
8+
<?php
9+
var_dump(exif_thumbnail(__DIR__."/bug68113.jpg"));
10+
?>
11+
Done
12+
--EXPECTF--
13+
Warning: exif_thumbnail(bug68113.jpg): File structure corrupted in %s/bug68113.php on line 2
14+
15+
Warning: exif_thumbnail(bug68113.jpg): Invalid JPEG file in %s/bug68113.php on line 2
16+
bool(false)
17+
Done

0 commit comments

Comments
 (0)