From 1964e84ec40d905bd3b329c72b9a1880b79418a1 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 21 Jun 2024 19:49:30 +0200 Subject: [PATCH 1/4] Fix is_zend_ptr() for huge blocks zend_mm_heap.huge_list is NULL-terminated --- Zend/tests/is_zend_ptr.phpt | 16 ++++++++++++++++ Zend/zend_alloc.c | 18 ++++++++---------- ext/ffi/tests/is_zend_ptr.phpt | 24 ++++++++++++++++++++++++ ext/zend_test/test.c | 11 +++++++++++ ext/zend_test/test.stub.php | 2 ++ ext/zend_test/test_arginfo.h | 8 +++++++- 6 files changed, 68 insertions(+), 11 deletions(-) create mode 100644 Zend/tests/is_zend_ptr.phpt create mode 100644 ext/ffi/tests/is_zend_ptr.phpt diff --git a/Zend/tests/is_zend_ptr.phpt b/Zend/tests/is_zend_ptr.phpt new file mode 100644 index 0000000000000..8650fc1acb932 --- /dev/null +++ b/Zend/tests/is_zend_ptr.phpt @@ -0,0 +1,16 @@ +--TEST-- +is_zend_ptr() is broken for huge blocks +--FILE-- + +==DONE== +--EXPECT-- +==DONE== diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 0952a88a41194..e86f2961cfac9 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2455,17 +2455,15 @@ ZEND_API bool is_zend_ptr(const void *ptr) } while (chunk != AG(mm_heap)->main_chunk); } - if (AG(mm_heap)->huge_list) { - zend_mm_huge_list *block = AG(mm_heap)->huge_list; - - do { - if (ptr >= (void*)block - && ptr < (void*)((char*)block + block->size)) { - return 1; - } - block = block->next; - } while (block != AG(mm_heap)->huge_list); + zend_mm_huge_list *block = AG(mm_heap)->huge_list; + while (block) { + if (ptr >= (void*)block + && ptr < (void*)((char*)block + block->size)) { + return 1; + } + block = block->next; } + return 0; } diff --git a/ext/ffi/tests/is_zend_ptr.phpt b/ext/ffi/tests/is_zend_ptr.phpt new file mode 100644 index 0000000000000..d1664f035b50a --- /dev/null +++ b/ext/ffi/tests/is_zend_ptr.phpt @@ -0,0 +1,24 @@ +--TEST-- +FFI::free() +--FILE-- +malloc(10); +$addr = $ffi->cast("uintptr_t", $ffi->cast("char*", $ptr))->cdata; + +$ptr = FFI::cdef()->cast("char*", $addr); + +// Should not crash in is_zend_ptr() +FFI::free($ptr); + +?> +==DONE== +--EXPECT-- +==DONE== diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 8ab8a06107eb1..2df6c2027498a 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -628,6 +628,17 @@ static ZEND_FUNCTION(zend_test_cast_fread) } } +static ZEND_FUNCTION(zend_test_is_zend_ptr) +{ + zend_long addr; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(addr); + ZEND_PARSE_PARAMETERS_END(); + + RETURN_BOOL(is_zend_ptr((void*)addr)); +} + static zend_object *zend_test_class_new(zend_class_entry *class_type) { zend_object *obj = zend_objects_new(class_type); diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index e4439fe38c05f..7dc348934400f 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -189,6 +189,8 @@ function zend_test_set_fmode(bool $binary): void {} /** @param resource $stream */ function zend_test_cast_fread($stream): void {} + + function zend_test_is_zend_ptr(int $addr): bool {} } namespace ZendTestNS { diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index c07e3dca01bed..19ea9e7a2adf5 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 98cade449e4dcf038166adeee07b17308dd48725 */ + * Stub hash: 07ce28cd75080118509ac0d30d8ce5ef54110747 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -122,6 +122,10 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_cast_fread, 0, 1, IS_V ZEND_ARG_INFO(0, stream) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_is_zend_ptr, 0, 1, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO(0, addr, IS_LONG, 0) +ZEND_END_ARG_INFO() + #define arginfo_ZendTestNS2_namespaced_func arginfo_zend_test_is_pcre_bundled #define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return @@ -230,6 +234,7 @@ static ZEND_FUNCTION(zend_test_is_pcre_bundled); static ZEND_FUNCTION(zend_test_set_fmode); #endif static ZEND_FUNCTION(zend_test_cast_fread); +static ZEND_FUNCTION(zend_test_is_zend_ptr); static ZEND_FUNCTION(ZendTestNS2_namespaced_func); static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func); static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func); @@ -293,6 +298,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(zend_test_set_fmode, arginfo_zend_test_set_fmode) #endif ZEND_FE(zend_test_cast_fread, arginfo_zend_test_cast_fread) + ZEND_FE(zend_test_is_zend_ptr, arginfo_zend_test_is_zend_ptr) ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func) ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func) ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func) From a872bebb676bcfca93b19dd87b9f21298a8e2a71 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 21 Jun 2024 19:58:59 +0200 Subject: [PATCH 2/4] Rename tests --- Zend/tests/{is_zend_ptr.phpt => gh14626.phpt} | 2 +- ext/ffi/tests/{is_zend_ptr.phpt => gh14626.phpt} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Zend/tests/{is_zend_ptr.phpt => gh14626.phpt} (76%) rename ext/ffi/tests/{is_zend_ptr.phpt => gh14626.phpt} (78%) diff --git a/Zend/tests/is_zend_ptr.phpt b/Zend/tests/gh14626.phpt similarity index 76% rename from Zend/tests/is_zend_ptr.phpt rename to Zend/tests/gh14626.phpt index 8650fc1acb932..9a0a983602a99 100644 --- a/Zend/tests/is_zend_ptr.phpt +++ b/Zend/tests/gh14626.phpt @@ -1,5 +1,5 @@ --TEST-- -is_zend_ptr() is broken for huge blocks +GH-14626: is_zend_ptr() may crash for non-zend ptrs when huge blocks exist --FILE-- Date: Fri, 21 Jun 2024 20:43:53 +0200 Subject: [PATCH 3/4] Fix tests --- Zend/tests/gh14626.phpt | 2 ++ ext/ffi/tests/gh14626.phpt | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Zend/tests/gh14626.phpt b/Zend/tests/gh14626.phpt index 9a0a983602a99..c0c029fcd8474 100644 --- a/Zend/tests/gh14626.phpt +++ b/Zend/tests/gh14626.phpt @@ -1,5 +1,7 @@ --TEST-- GH-14626: is_zend_ptr() may crash for non-zend ptrs when huge blocks exist +--EXTENSIONS-- +zend_test --FILE-- Date: Tue, 25 Jun 2024 13:42:00 +0200 Subject: [PATCH 4/4] Skip test on Windows --- ext/ffi/tests/gh14626.phpt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/ffi/tests/gh14626.phpt b/ext/ffi/tests/gh14626.phpt index 1ab1790a9ae3a..f69122e288917 100644 --- a/ext/ffi/tests/gh14626.phpt +++ b/ext/ffi/tests/gh14626.phpt @@ -2,6 +2,10 @@ GH-14626: FFI::free() may crash in is_zend_ptr() when at least one huge block exists and the ptr is non-zend --EXTENSIONS-- ffi +--SKIPIF-- + --INI-- ffi.enable=1 --FILE--