mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix is_zend_ptr() for huge blocks (#14626)
is_zend_ptr() expected zend_mm_heap.huge_list to be circular, but it's in fact NULL-terminated. It could crash when at least one huge block exists and the ptr did not belong to any block.
This commit is contained in:
parent
d7ef2c209a
commit
1ff277dee2
6 changed files with 78 additions and 11 deletions
18
Zend/tests/gh14626.phpt
Normal file
18
Zend/tests/gh14626.phpt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
--TEST--
|
||||||
|
GH-14626: is_zend_ptr() may crash for non-zend ptrs when huge blocks exist
|
||||||
|
--EXTENSIONS--
|
||||||
|
zend_test
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Ensure there is at least one huge_block
|
||||||
|
$str = str_repeat('a', 2*1024*1024);
|
||||||
|
|
||||||
|
// Check that is_zend_ptr() does not crash
|
||||||
|
zend_test_is_zend_ptr(0);
|
||||||
|
zend_test_is_zend_ptr(1<<30);
|
||||||
|
|
||||||
|
?>
|
||||||
|
==DONE==
|
||||||
|
--EXPECT--
|
||||||
|
==DONE==
|
|
@ -2455,17 +2455,15 @@ ZEND_API bool is_zend_ptr(const void *ptr)
|
||||||
} while (chunk != AG(mm_heap)->main_chunk);
|
} while (chunk != AG(mm_heap)->main_chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AG(mm_heap)->huge_list) {
|
zend_mm_huge_list *block = AG(mm_heap)->huge_list;
|
||||||
zend_mm_huge_list *block = AG(mm_heap)->huge_list;
|
while (block) {
|
||||||
|
if (ptr >= (void*)block
|
||||||
do {
|
&& ptr < (void*)((char*)block + block->size)) {
|
||||||
if (ptr >= (void*)block
|
return 1;
|
||||||
&& ptr < (void*)((char*)block + block->size)) {
|
}
|
||||||
return 1;
|
block = block->next;
|
||||||
}
|
|
||||||
block = block->next;
|
|
||||||
} while (block != AG(mm_heap)->huge_list);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
ext/ffi/tests/gh14626.phpt
Normal file
32
ext/ffi/tests/gh14626.phpt
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
--TEST--
|
||||||
|
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--
|
||||||
|
<?php
|
||||||
|
if (substr(PHP_OS, 0, 3) == 'WIN') die("skip no malloc() on windows");
|
||||||
|
?>
|
||||||
|
--INI--
|
||||||
|
ffi.enable=1
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Ensure there is at least one huge_block
|
||||||
|
$str = str_repeat('a', 2*1024*1024);
|
||||||
|
|
||||||
|
$ffi = FFI::cdef(<<<C
|
||||||
|
void *malloc(size_t size);
|
||||||
|
C);
|
||||||
|
|
||||||
|
$ptr = $ffi->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==
|
|
@ -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)
|
static zend_object *zend_test_class_new(zend_class_entry *class_type)
|
||||||
{
|
{
|
||||||
zend_object *obj = zend_objects_new(class_type);
|
zend_object *obj = zend_objects_new(class_type);
|
||||||
|
|
|
@ -189,6 +189,8 @@ function zend_test_override_libxml_global_state(): void {}
|
||||||
|
|
||||||
/** @param resource $stream */
|
/** @param resource $stream */
|
||||||
function zend_test_cast_fread($stream): void {}
|
function zend_test_cast_fread($stream): void {}
|
||||||
|
|
||||||
|
function zend_test_is_zend_ptr(int $addr): bool {}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ZendTestNS {
|
namespace ZendTestNS {
|
||||||
|
|
8
ext/zend_test/test_arginfo.h
generated
8
ext/zend_test/test_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
||||||
/* This is a generated file, edit the .stub.php file instead.
|
/* 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_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
||||||
ZEND_END_ARG_INFO()
|
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_ARG_INFO(0, stream)
|
||||||
ZEND_END_ARG_INFO()
|
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_func arginfo_zend_test_is_pcre_bundled
|
||||||
|
|
||||||
#define arginfo_ZendTestNS2_namespaced_deprecated_func arginfo_zend_test_void_return
|
#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);
|
static ZEND_FUNCTION(zend_test_set_fmode);
|
||||||
#endif
|
#endif
|
||||||
static ZEND_FUNCTION(zend_test_cast_fread);
|
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_func);
|
||||||
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func);
|
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func);
|
||||||
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_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)
|
ZEND_FE(zend_test_set_fmode, arginfo_zend_test_set_fmode)
|
||||||
#endif
|
#endif
|
||||||
ZEND_FE(zend_test_cast_fread, arginfo_zend_test_cast_fread)
|
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_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_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)
|
ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue