Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4838205

Browse files
support neighbouring extension in the ZendMM custom handlers hook
1 parent ce96aa9 commit 4838205

File tree

4 files changed

+95
-31
lines changed

4 files changed

+95
-31
lines changed

‎ext/zend_test/php_test.h‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,11 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test)
5656
bool print_stderr_mshutdown;
5757
zend_long limit_copy_file_range;
5858
int observe_opline_in_zendmm;
59-
zend_mm_heap* zend_orig_heap;
60-
zend_mm_heap* zend_test_heap;
59+
// previous handlers that might have been installed
60+
// `USE_ZEND_ALLOC=0` installs custom handlers
61+
void* (*zendmm_orig_malloc)(size_t);
62+
void (*zendmm_orig_free)(void*);
63+
void* (*zendmm_orig_realloc)(void *, size_t);
6164
zend_test_fiber *active_fiber;
6265
zend_long quantity_value;
6366
zend_string *str_test;

‎ext/zend_test/test.c‎

Lines changed: 90 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -641,28 +641,110 @@ static bool has_opline(zend_execute_data *execute_data)
641641
;
642642
}
643643

644+
// When a custom memory manager is installed, ZendMM alters its behaviour. For
645+
// example `zend_mm_gc()` will not do anything anymore, or `zend_mm_shutdown()`
646+
// won't cleanup chunks and leak memory. This might not be a problem in tests,
647+
// but I fear folks might see and use this implementation as a boiler plate when
648+
// trying to use this hook
649+
int zend_test_prepare_zendmm_for_call(zend_mm_heap *heap)
650+
{
651+
int flag = 0;
652+
memcpy(&flag, heap, sizeof(int));
653+
int new_flag = 0;
654+
memcpy(heap, &new_flag, sizeof(int));
655+
return flag;
656+
}
657+
658+
void zend_test_restore_zendmm_after_call(zend_mm_heap *heap, int flag)
659+
{
660+
memcpy(heap, &flag, sizeof(int));
661+
}
662+
644663
void * zend_test_custom_malloc(size_t len)
645664
{
646665
if (has_opline(EG(current_execute_data))) {
647666
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
648667
}
649-
return _zend_mm_alloc(ZT_G(zend_orig_heap), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
668+
if (ZT_G(zendmm_orig_malloc)) {
669+
return ZT_G(zendmm_orig_malloc)(len);
670+
}
671+
int flag = zend_test_prepare_zendmm_for_call(zend_mm_get_heap());
672+
void * ptr = _zend_mm_alloc(zend_mm_get_heap(), len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
673+
zend_test_restore_zendmm_after_call(zend_mm_get_heap(), flag);
674+
return ptr;
650675
}
651676

652677
void zend_test_custom_free(void *ptr)
653678
{
654679
if (has_opline(EG(current_execute_data))) {
655680
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
656681
}
657-
_zend_mm_free(ZT_G(zend_orig_heap), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
682+
if (ZT_G(zendmm_orig_free)) {
683+
ZT_G(zendmm_orig_free)(ptr);
684+
return;
685+
}
686+
int flag = zend_test_prepare_zendmm_for_call(zend_mm_get_heap());
687+
_zend_mm_free(zend_mm_get_heap(), ptr ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
688+
zend_test_restore_zendmm_after_call(zend_mm_get_heap(), flag);
658689
}
659690

660691
void * zend_test_custom_realloc(void * ptr, size_t len)
661692
{
662693
if (has_opline(EG(current_execute_data))) {
663694
assert(EG(current_execute_data)->opline->lineno != (uint32_t)-1);
664695
}
665-
return _zend_mm_realloc(ZT_G(zend_orig_heap), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
696+
if (ZT_G(zendmm_orig_realloc)) {
697+
return ZT_G(zendmm_orig_realloc)(ptr, len);
698+
}
699+
int flag = zend_test_prepare_zendmm_for_call(zend_mm_get_heap());
700+
void * new_ptr = _zend_mm_realloc(zend_mm_get_heap(), ptr, len ZEND_FILE_LINE_EMPTY_CC ZEND_FILE_LINE_EMPTY_CC);
701+
zend_test_restore_zendmm_after_call(zend_mm_get_heap(), flag);
702+
return new_ptr;
703+
}
704+
705+
void zend_test_install_custom_mm_handler(void)
706+
{
707+
// fetch maybe installed previous handlers
708+
if (!is_zend_mm()) {
709+
zend_mm_get_custom_handlers(
710+
zend_mm_get_heap(),
711+
&ZT_G(zendmm_orig_malloc),
712+
&ZT_G(zendmm_orig_free),
713+
&ZT_G(zendmm_orig_realloc)
714+
);
715+
}
716+
zend_mm_set_custom_handlers(
717+
zend_mm_get_heap(),
718+
zend_test_custom_malloc,
719+
zend_test_custom_free,
720+
zend_test_custom_realloc
721+
);
722+
}
723+
724+
void zend_test_uninstall_custom_mm_handler(void)
725+
{
726+
void* (*custom_malloc)(size_t);
727+
void (*custom_free)(void*);
728+
void* (*custom_realloc)(void *, size_t);
729+
zend_mm_get_custom_handlers(
730+
zend_mm_get_heap(),
731+
&custom_malloc,
732+
&custom_free,
733+
&custom_realloc
734+
);
735+
if (custom_malloc == zend_test_custom_malloc ||
736+
custom_free == zend_test_custom_free ||
737+
custom_realloc == zend_test_custom_realloc) {
738+
zend_mm_set_custom_handlers(
739+
zend_mm_get_heap(),
740+
ZT_G(zendmm_orig_malloc),
741+
ZT_G(zendmm_orig_free),
742+
ZT_G(zendmm_orig_realloc)
743+
);
744+
ZT_G(zendmm_orig_malloc) = NULL;
745+
ZT_G(zendmm_orig_free) = NULL;
746+
ZT_G(zendmm_orig_realloc) = NULL;
747+
}
666748
}
667749

668750
static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
@@ -674,22 +756,9 @@ static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM)
674756
int int_value = zend_ini_parse_bool(new_value);
675757

676758
if (int_value == 1) {
677-
// `zend_mm_heap` is a private struct, so we have not way to find the
678-
// actual size, but 4096 bytes should be enough
679-
ZT_G(zend_test_heap) = malloc(4096);
680-
memset(ZT_G(zend_test_heap), 0, 4096);
681-
zend_mm_set_custom_handlers(
682-
ZT_G(zend_test_heap),
683-
zend_test_custom_malloc,
684-
zend_test_custom_free,
685-
zend_test_custom_realloc
686-
);
687-
ZT_G(zend_orig_heap) = zend_mm_get_heap();
688-
zend_mm_set_heap(ZT_G(zend_test_heap));
689-
} else if (ZT_G(zend_test_heap)) {
690-
free(ZT_G(zend_test_heap));
691-
ZT_G(zend_test_heap) = NULL;
692-
zend_mm_set_heap(ZT_G(zend_orig_heap));
759+
zend_test_install_custom_mm_handler();
760+
} else {
761+
zend_test_uninstall_custom_mm_handler();
693762
}
694763
return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
695764
}
@@ -1206,6 +1275,8 @@ PHP_MSHUTDOWN_FUNCTION(zend_test)
12061275

12071276
zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS_PASSTHRU);
12081277

1278+
zend_test_uninstall_custom_mm_handler();
1279+
12091280
if (ZT_G(print_stderr_mshutdown)) {
12101281
fprintf(stderr, "[zend_test] MSHUTDOWN\n");
12111282
}
@@ -1228,12 +1299,6 @@ PHP_RSHUTDOWN_FUNCTION(zend_test)
12281299
} ZEND_HASH_FOREACH_END();
12291300
zend_hash_destroy(&ZT_G(global_weakmap));
12301301

1231-
if (ZT_G(zend_test_heap)) {
1232-
free(ZT_G(zend_test_heap));
1233-
ZT_G(zend_test_heap) = NULL;
1234-
zend_mm_set_heap(ZT_G(zend_orig_heap));
1235-
}
1236-
12371302
return SUCCESS;
12381303
}
12391304

‎ext/zend_test/tests/opline_dangling.phpt‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ possible segfault in `ZEND_BIND_STATIC`
44
https://github.com/php/php-src/pull/12758
55
--EXTENSIONS--
66
zend_test
7-
--ENV--
8-
USE_ZEND_ALLOC=1
97
--INI--
108
zend_test.observe_opline_in_zendmm=1
119
--FILE--

‎ext/zend_test/tests/opline_dangling_02.phpt‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
possible segfault in `ZEND_FUNC_GET_ARGS`
33
--EXTENSIONS--
44
zend_test
5-
--ENV--
6-
USE_ZEND_ALLOC=1
75
--INI--
86
zend_test.observe_opline_in_zendmm=1
97
--FILE--

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /