1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Florian Engelhardt <florian@engelhardt.tc> |
14 +----------------------------------------------------------------------+
15 */
16
17 #include "php.h"
18 #include "php_test.h"
19 #include "Zend/zend_alloc.h"
20 #include "zend_portability.h"
21 #include <stddef.h>
22 #include <stdio.h>
23
observe_malloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)24 void* observe_malloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
25 {
26 void *ptr = NULL;
27 if (ZT_G(custom_malloc)) {
28 zend_mm_set_heap(ZT_G(original_heap));
29 ptr = ZT_G(custom_malloc)(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
30 zend_mm_set_heap(ZT_G(observed_heap));
31 } else {
32 ptr = _zend_mm_alloc(ZT_G(original_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
33 }
34 printf("Allocated %zu bytes at %p\n", size, ptr);
35 return ptr;
36 }
37
observe_free(void * ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)38 void observe_free(void* ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
39 {
40 if (ZT_G(custom_free))
41 {
42 zend_mm_set_heap(ZT_G(original_heap));
43 ZT_G(custom_free)(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
44 zend_mm_set_heap(ZT_G(observed_heap));
45 } else {
46 _zend_mm_free(ZT_G(original_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
47 }
48 printf("Freed memory at %p\n", ptr);
49 }
50
observe_realloc(void * ptr,size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)51 void* observe_realloc(void* ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
52 {
53 void * new_ptr;
54 if (ZT_G(custom_realloc))
55 {
56 zend_mm_set_heap(ZT_G(original_heap));
57 new_ptr = ZT_G(custom_realloc)(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
58 zend_mm_set_heap(ZT_G(observed_heap));
59 } else {
60 new_ptr = _zend_mm_realloc(ZT_G(original_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
61 }
62 printf("Realloc of %zu bytes from %p to %p\n", size, ptr, new_ptr);
63 return new_ptr;
64 }
65
observe_gc(void)66 size_t observe_gc(void)
67 {
68 size_t size = 0;
69 if (ZT_G(custom_gc)) {
70 zend_mm_set_heap(ZT_G(original_heap));
71 size = ZT_G(custom_gc)();
72 zend_mm_set_heap(ZT_G(observed_heap));
73 } else {
74 size = zend_mm_gc(ZT_G(original_heap));
75 }
76 printf("ZendMM GC freed %zu bytes", size);
77 return size;
78 }
79
observe_shutdown(bool full,bool silent)80 void observe_shutdown(bool full, bool silent)
81 {
82 if (ZT_G(custom_shutdown)) {
83 zend_mm_set_heap(ZT_G(original_heap));
84 ZT_G(custom_shutdown)(full, silent);
85 zend_mm_set_heap(ZT_G(observed_heap));
86 } else {
87 zend_mm_shutdown(ZT_G(original_heap), full, silent);
88 }
89 printf("Shutdown happened: full -> %d, silent -> %d\n", full, silent);
90 }
91
zend_test_mm_custom_handlers_init(void)92 void zend_test_mm_custom_handlers_init(void)
93 {
94 if (ZT_G(observed_heap) != NULL) {
95 return;
96 }
97 ZT_G(original_heap) = zend_mm_get_heap();
98 if (zend_mm_is_custom_heap(ZT_G(original_heap))) {
99 zend_mm_get_custom_handlers_ex(
100 ZT_G(original_heap),
101 &ZT_G(custom_malloc),
102 &ZT_G(custom_free),
103 &ZT_G(custom_realloc),
104 &ZT_G(custom_gc),
105 &ZT_G(custom_shutdown)
106 );
107 }
108 printf("Prev handlers at %p, %p, %p, %p, %p\n", ZT_G(custom_malloc), ZT_G(custom_free), ZT_G(custom_realloc), ZT_G(custom_gc), ZT_G(custom_shutdown));
109 ZT_G(observed_heap) = zend_mm_startup();
110 zend_mm_set_custom_handlers_ex(
111 ZT_G(observed_heap),
112 observe_malloc,
113 observe_free,
114 observe_realloc,
115 observe_gc,
116 observe_shutdown
117 );
118 zend_mm_set_heap(ZT_G(observed_heap));
119 printf("Heap at %p installed in ZendMM (orig at %p)\n", ZT_G(observed_heap), ZT_G(original_heap));
120 }
121
zend_test_mm_custom_handlers_shutdown(void)122 void zend_test_mm_custom_handlers_shutdown(void)
123 {
124 if (ZT_G(observed_heap) == NULL) {
125 return;
126 }
127 zend_mm_set_heap(ZT_G(original_heap));
128 zend_mm_set_custom_handlers_ex(
129 ZT_G(observed_heap),
130 NULL,
131 NULL,
132 NULL,
133 NULL,
134 NULL
135 );
136 zend_mm_shutdown(ZT_G(observed_heap), true, true);
137 ZT_G(observed_heap) = NULL;
138 printf("Prev heap at %p restored in ZendMM\n", ZT_G(original_heap));
139 }
140
zend_test_mm_custom_handlers_rshutdown(void)141 void zend_test_mm_custom_handlers_rshutdown(void)
142 {
143 zend_test_mm_custom_handlers_shutdown();
144 }
145
zend_test_mm_custom_handlers_rinit(void)146 void zend_test_mm_custom_handlers_rinit(void)
147 {
148 if (ZT_G(zend_mm_custom_handlers_enabled)) {
149 zend_test_mm_custom_handlers_init();
150 }
151 }
152
PHP_INI_MH(OnUpdateZendTestMMCustomHandlersEnabled)153 static PHP_INI_MH(OnUpdateZendTestMMCustomHandlersEnabled)
154 {
155 if (new_value == NULL) {
156 return FAILURE;
157 }
158
159 int int_value = zend_ini_parse_bool(new_value);
160
161 if (int_value == 1) {
162 zend_test_mm_custom_handlers_init();
163 } else {
164 zend_test_mm_custom_handlers_shutdown();
165 }
166 return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage);
167 }
168
169 PHP_INI_BEGIN()
170 STD_PHP_INI_BOOLEAN("zend_test.zend_mm_custom_handlers.enabled", "0", PHP_INI_USER, OnUpdateZendTestMMCustomHandlersEnabled, zend_mm_custom_handlers_enabled, zend_zend_test_globals, zend_test_globals)
PHP_INI_END()171 PHP_INI_END()
172
173 void zend_test_mm_custom_handlers_minit(INIT_FUNC_ARGS)
174 {
175 if (type != MODULE_TEMPORARY) {
176 REGISTER_INI_ENTRIES();
177 } else {
178 (void)ini_entries;
179 }
180 }
181