xref: /PHP-8.0/ext/mysqlnd/mysqlnd_alloc.c (revision 5d6e923d)
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   | http://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   | Authors: Andrey Hristov <andrey@php.net>                             |
14   |          Ulf Wendel <uw@php.net>                                     |
15   +----------------------------------------------------------------------+
16 */
17 
18 #include "php.h"
19 #include "mysqlnd.h"
20 #include "mysqlnd_priv.h"
21 #include "mysqlnd_debug.h"
22 #include "mysqlnd_wireprotocol.h"
23 #include "mysqlnd_statistics.h"
24 
25 #define MYSQLND_DEBUG_MEMORY 1
26 
27 static const char mysqlnd_emalloc_name[]	= "_mysqlnd_emalloc";
28 static const char mysqlnd_pemalloc_name[]	= "_mysqlnd_pemalloc";
29 static const char mysqlnd_ecalloc_name[]	= "_mysqlnd_ecalloc";
30 static const char mysqlnd_pecalloc_name[]	= "_mysqlnd_pecalloc";
31 static const char mysqlnd_erealloc_name[]	= "_mysqlnd_erealloc";
32 static const char mysqlnd_perealloc_name[]	= "_mysqlnd_perealloc";
33 static const char mysqlnd_efree_name[]		= "_mysqlnd_efree";
34 static const char mysqlnd_pefree_name[]		= "_mysqlnd_pefree";
35 static const char mysqlnd_malloc_name[]		= "_mysqlnd_malloc";
36 static const char mysqlnd_calloc_name[]		= "_mysqlnd_calloc";
37 static const char mysqlnd_realloc_name[]	= "_mysqlnd_realloc";
38 static const char mysqlnd_free_name[]		= "_mysqlnd_free";
39 static const char mysqlnd_pememdup_name[]	= "_mysqlnd_pememdup";
40 static const char mysqlnd_pestrndup_name[]	= "_mysqlnd_pestrndup";
41 static const char mysqlnd_pestrdup_name[]	= "_mysqlnd_pestrdup";
42 
43 PHPAPI const char * mysqlnd_debug_std_no_trace_funcs[] =
44 {
45 	mysqlnd_emalloc_name,
46 	mysqlnd_ecalloc_name,
47 	mysqlnd_efree_name,
48 	mysqlnd_erealloc_name,
49 	mysqlnd_pemalloc_name,
50 	mysqlnd_pecalloc_name,
51 	mysqlnd_pefree_name,
52 	mysqlnd_perealloc_name,
53 	mysqlnd_malloc_name,
54 	mysqlnd_calloc_name,
55 	mysqlnd_realloc_name,
56 	mysqlnd_free_name,
57 	mysqlnd_pestrndup_name,
58 	mysqlnd_read_header_name,
59 	mysqlnd_read_body_name,
60 	NULL /* must be always last */
61 };
62 
63 #if MYSQLND_DEBUG_MEMORY
64 
65 
66 #if ZEND_DEBUG
67 #else
68 #define __zend_orig_filename "/unknown/unknown"
69 #define __zend_orig_lineno   0
70 #endif
71 
72 #define REAL_SIZE(s) (collect_memory_statistics? (s) + sizeof(size_t) : (s))
73 #define REAL_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) - sizeof(size_t)) : (p))
74 #define FAKE_PTR(p) (collect_memory_statistics && (p)? (((char *)(p)) + sizeof(size_t)) : (p))
75 
76 /* {{{ _mysqlnd_emalloc */
_mysqlnd_emalloc(size_t size MYSQLND_MEM_D)77 static void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
78 {
79 	void *ret;
80 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
81 #if PHP_DEBUG
82 	zend_long * threshold = &MYSQLND_G(debug_emalloc_fail_threshold);
83 	TRACE_ALLOC_ENTER(mysqlnd_emalloc_name);
84 
85 	{
86 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
87 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
88 	}
89 
90 	if (*threshold == 0) {
91 		ret = NULL;
92 	} else {
93 		ret = emalloc_rel(REAL_SIZE(size));
94 		--*threshold;
95 	}
96 #else
97 	TRACE_ALLOC_ENTER(mysqlnd_emalloc_name);
98 	ret = emalloc_rel(REAL_SIZE(size));
99 #endif
100 
101 	TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
102 
103 	if (ret && collect_memory_statistics) {
104 		*(size_t *) ret = size;
105 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
106 	}
107 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
108 }
109 /* }}} */
110 
111 
112 /* {{{ _mysqlnd_pemalloc */
_mysqlnd_pemalloc(size_t size,zend_bool persistent MYSQLND_MEM_D)113 static void * _mysqlnd_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
114 {
115 	void *ret;
116 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
117 #if PHP_DEBUG
118 	zend_long * threshold = persistent? &MYSQLND_G(debug_malloc_fail_threshold):&MYSQLND_G(debug_emalloc_fail_threshold);
119 	TRACE_ALLOC_ENTER(mysqlnd_pemalloc_name);
120 
121 	{
122 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
123 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
124 	}
125 
126 	if (*threshold == 0) {
127 		ret = NULL;
128 	} else {
129 		ret = pemalloc_rel(REAL_SIZE(size), persistent);
130 		--*threshold;
131 	}
132 #else
133 	TRACE_ALLOC_ENTER(mysqlnd_pemalloc_name);
134 	ret = pemalloc_rel(REAL_SIZE(size), persistent);
135 #endif
136 
137 	TRACE_ALLOC_INF_FMT("size=%lu ptr=%p persistent=%u", size, ret, persistent);
138 
139 	if (ret && collect_memory_statistics) {
140 		enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_MALLOC_COUNT:STAT_MEM_EMALLOC_COUNT;
141 		enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_MALLOC_AMOUNT:STAT_MEM_EMALLOC_AMOUNT;
142 		*(size_t *) ret = size;
143 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
144 	}
145 
146 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
147 }
148 /* }}} */
149 
150 
151 /* {{{ _mysqlnd_ecalloc */
_mysqlnd_ecalloc(unsigned int nmemb,size_t size MYSQLND_MEM_D)152 static void * _mysqlnd_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
153 {
154 	void *ret;
155 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
156 #if PHP_DEBUG
157 	zend_long * threshold = &MYSQLND_G(debug_ecalloc_fail_threshold);
158 	TRACE_ALLOC_ENTER(mysqlnd_ecalloc_name);
159 
160 	{
161 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
162 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
163 	}
164 	TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(FALSE));
165 
166 	if (*threshold == 0) {
167 		ret = NULL;
168 	} else {
169 		ret = ecalloc_rel(nmemb, REAL_SIZE(size));
170 		--*threshold;
171 	}
172 #else
173 	TRACE_ALLOC_ENTER(mysqlnd_ecalloc_name);
174 	TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(FALSE));
175 	ret = ecalloc_rel(nmemb, REAL_SIZE(size));
176 #endif
177 
178 	TRACE_ALLOC_INF_FMT("after : %lu", zend_memory_usage(FALSE));
179 	TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
180 	if (ret && collect_memory_statistics) {
181 		*(size_t *) ret = size;
182 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_ECALLOC_COUNT, 1, STAT_MEM_ECALLOC_AMOUNT, size);
183 	}
184 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
185 }
186 /* }}} */
187 
188 
189 /* {{{ _mysqlnd_pecalloc */
_mysqlnd_pecalloc(unsigned int nmemb,size_t size,zend_bool persistent MYSQLND_MEM_D)190 static void * _mysqlnd_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
191 {
192 	void *ret;
193 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
194 #if PHP_DEBUG
195 	zend_long * threshold = persistent? &MYSQLND_G(debug_calloc_fail_threshold):&MYSQLND_G(debug_ecalloc_fail_threshold);
196 	TRACE_ALLOC_ENTER(mysqlnd_pecalloc_name);
197 	{
198 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
199 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
200 	}
201 
202 	if (*threshold == 0) {
203 		ret = NULL;
204 	} else {
205 		ret = pecalloc_rel(nmemb, REAL_SIZE(size), persistent);
206 		--*threshold;
207 	}
208 #else
209 	TRACE_ALLOC_ENTER(mysqlnd_pecalloc_name);
210 	ret = pecalloc_rel(nmemb, REAL_SIZE(size), persistent);
211 #endif
212 
213 	TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
214 
215 	if (ret && collect_memory_statistics) {
216 		enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_CALLOC_COUNT:STAT_MEM_ECALLOC_COUNT;
217 		enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_CALLOC_AMOUNT:STAT_MEM_ECALLOC_AMOUNT;
218 		*(size_t *) ret = size;
219 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, size);
220 	}
221 
222 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
223 }
224 /* }}} */
225 
226 
227 /* {{{ _mysqlnd_erealloc */
_mysqlnd_erealloc(void * ptr,size_t new_size MYSQLND_MEM_D)228 static void * _mysqlnd_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
229 {
230 	void *ret;
231 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
232 	size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
233 #if PHP_DEBUG
234 	zend_long * threshold = &MYSQLND_G(debug_erealloc_fail_threshold);
235 	TRACE_ALLOC_ENTER(mysqlnd_erealloc_name);
236 
237 	{
238 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
239 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
240 	}
241 	TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
242 
243 	if (*threshold == 0) {
244 		ret = NULL;
245 	} else {
246 		ret = erealloc_rel(REAL_PTR(ptr), REAL_SIZE(new_size));
247 		--*threshold;
248 	}
249 #else
250 	TRACE_ALLOC_ENTER(mysqlnd_erealloc_name);
251 	TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu, new_size=%lu", ptr, old_size, new_size);
252 	ret = erealloc_rel(REAL_PTR(ptr), REAL_SIZE(new_size));
253 #endif
254 
255 	TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret);
256 	if (ret && collect_memory_statistics) {
257 		*(size_t *) ret = new_size;
258 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EREALLOC_COUNT, 1, STAT_MEM_EREALLOC_AMOUNT, new_size);
259 	}
260 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
261 }
262 /* }}} */
263 
264 
265 /* {{{ _mysqlnd_perealloc */
_mysqlnd_perealloc(void * ptr,size_t new_size,zend_bool persistent MYSQLND_MEM_D)266 static void * _mysqlnd_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
267 {
268 	void *ret;
269 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
270 	size_t old_size = collect_memory_statistics && ptr? *(size_t *) (((char*)ptr) - sizeof(size_t)) : 0;
271 #if PHP_DEBUG
272 	zend_long * threshold = persistent? &MYSQLND_G(debug_realloc_fail_threshold):&MYSQLND_G(debug_erealloc_fail_threshold);
273 	TRACE_ALLOC_ENTER(mysqlnd_perealloc_name);
274 
275 	{
276 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
277 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
278 	}
279 	TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu new_size=%lu   persistent=%u", ptr, old_size, new_size, persistent);
280 
281 	if (*threshold == 0) {
282 		ret = NULL;
283 	} else {
284 		ret = perealloc_rel(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
285 		--*threshold;
286 	}
287 #else
288 	TRACE_ALLOC_ENTER(mysqlnd_perealloc_name);
289 	TRACE_ALLOC_INF_FMT("ptr=%p old_size=%lu new_size=%lu   persistent=%u", ptr, old_size, new_size, persistent);
290 	ret = perealloc_rel(REAL_PTR(ptr), REAL_SIZE(new_size), persistent);
291 #endif
292 
293 	TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret);
294 
295 	if (ret && collect_memory_statistics) {
296 		enum mysqlnd_collected_stats s1 = persistent? STAT_MEM_REALLOC_COUNT:STAT_MEM_EREALLOC_COUNT;
297 		enum mysqlnd_collected_stats s2 = persistent? STAT_MEM_REALLOC_AMOUNT:STAT_MEM_EREALLOC_AMOUNT;
298 		*(size_t *) ret = new_size;
299 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(s1, 1, s2, new_size);
300 	}
301 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
302 }
303 /* }}} */
304 
305 
306 /* {{{ _mysqlnd_efree */
_mysqlnd_efree(void * ptr MYSQLND_MEM_D)307 static void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
308 {
309 	size_t free_amount = 0;
310 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
311 	TRACE_ALLOC_ENTER(mysqlnd_efree_name);
312 
313 #if PHP_DEBUG
314 	{
315 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
316 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
317 	}
318 #endif
319 	TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
320 
321 	if (ptr) {
322 		if (collect_memory_statistics) {
323 			free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
324 			TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
325 		}
326 		efree_rel(REAL_PTR(ptr));
327 	}
328 
329 	if (collect_memory_statistics) {
330 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EFREE_COUNT, 1, STAT_MEM_EFREE_AMOUNT, free_amount);
331 	}
332 	TRACE_ALLOC_VOID_RETURN;
333 }
334 /* }}} */
335 
336 
337 /* {{{ _mysqlnd_pefree */
_mysqlnd_pefree(void * ptr,zend_bool persistent MYSQLND_MEM_D)338 static void _mysqlnd_pefree(void *ptr, zend_bool persistent MYSQLND_MEM_D)
339 {
340 	size_t free_amount = 0;
341 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
342 	TRACE_ALLOC_ENTER(mysqlnd_pefree_name);
343 
344 #if PHP_DEBUG
345 	{
346 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
347 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
348 	}
349 #endif
350 	TRACE_ALLOC_INF_FMT("ptr=%p persistent=%u", ptr, persistent);
351 
352 	if (ptr) {
353 		if (collect_memory_statistics) {
354 			free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
355 			TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
356 		}
357 		pefree_rel(REAL_PTR(ptr), persistent);
358 	}
359 
360 	if (collect_memory_statistics) {
361 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(persistent? STAT_MEM_FREE_COUNT:STAT_MEM_EFREE_COUNT, 1,
362 											  persistent? STAT_MEM_FREE_AMOUNT:STAT_MEM_EFREE_AMOUNT, free_amount);
363 	}
364 	TRACE_ALLOC_VOID_RETURN;
365 }
366 /* }}} */
367 
368 
369 /* {{{ _mysqlnd_malloc */
_mysqlnd_malloc(size_t size MYSQLND_MEM_D)370 static void * _mysqlnd_malloc(size_t size MYSQLND_MEM_D)
371 {
372 	void *ret;
373 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
374 #if PHP_DEBUG
375 	zend_long * threshold = &MYSQLND_G(debug_malloc_fail_threshold);
376 	TRACE_ALLOC_ENTER(mysqlnd_malloc_name);
377 
378 	{
379 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
380 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
381 	}
382 
383 	if (*threshold == 0) {
384 		ret = NULL;
385 	} else {
386 		ret = malloc(REAL_SIZE(size));
387 		--*threshold;
388 	}
389 #else
390 	TRACE_ALLOC_ENTER(mysqlnd_malloc_name);
391 	ret = malloc(REAL_SIZE(size));
392 #endif
393 
394 	TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
395 	if (ret && collect_memory_statistics) {
396 		*(size_t *) ret = size;
397 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_MALLOC_COUNT, 1, STAT_MEM_MALLOC_AMOUNT, size);
398 	}
399 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
400 }
401 /* }}} */
402 
403 
404 /* {{{ _mysqlnd_calloc */
_mysqlnd_calloc(unsigned int nmemb,size_t size MYSQLND_MEM_D)405 static void * _mysqlnd_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
406 {
407 	void *ret;
408 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
409 #if PHP_DEBUG
410 	zend_long * threshold = &MYSQLND_G(debug_calloc_fail_threshold);
411 	TRACE_ALLOC_ENTER(mysqlnd_calloc_name);
412 
413 	{
414 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
415 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
416 	}
417 
418 	if (*threshold == 0) {
419 		ret = NULL;
420 	} else {
421 		ret = calloc(nmemb, REAL_SIZE(size));
422 		--*threshold;
423 	}
424 #else
425 	TRACE_ALLOC_ENTER(mysqlnd_calloc_name);
426 	ret = calloc(nmemb, REAL_SIZE(size));
427 #endif
428 
429 	TRACE_ALLOC_INF_FMT("size=%lu ptr=%p", size, ret);
430 	if (ret && collect_memory_statistics) {
431 		*(size_t *) ret = size;
432 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_CALLOC_COUNT, 1, STAT_MEM_CALLOC_AMOUNT, size);
433 	}
434 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
435 }
436 /* }}} */
437 
438 
439 /* {{{ _mysqlnd_realloc */
_mysqlnd_realloc(void * ptr,size_t new_size MYSQLND_MEM_D)440 static void * _mysqlnd_realloc(void *ptr, size_t new_size MYSQLND_MEM_D)
441 {
442 	void *ret;
443 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
444 #if PHP_DEBUG
445 	zend_long * threshold = &MYSQLND_G(debug_realloc_fail_threshold);
446 	TRACE_ALLOC_ENTER(mysqlnd_realloc_name);
447 
448 	{
449 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
450 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
451 	}
452 	TRACE_ALLOC_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
453 	TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(TRUE));
454 
455 	if (*threshold == 0) {
456 		ret = NULL;
457 	} else {
458 		ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
459 		--*threshold;
460 	}
461 #else
462 	TRACE_ALLOC_ENTER(mysqlnd_realloc_name);
463 	TRACE_ALLOC_INF_FMT("ptr=%p new_size=%lu ", new_size, ptr);
464 	TRACE_ALLOC_INF_FMT("before: %lu", zend_memory_usage(TRUE));
465 	ret = realloc(REAL_PTR(ptr), REAL_SIZE(new_size));
466 #endif
467 
468 	TRACE_ALLOC_INF_FMT("new_ptr=%p", (char*)ret);
469 
470 	if (ret && collect_memory_statistics) {
471 		*(size_t *) ret = new_size;
472 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_REALLOC_COUNT, 1, STAT_MEM_REALLOC_AMOUNT, new_size);
473 	}
474 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
475 }
476 /* }}} */
477 
478 
479 /* {{{ _mysqlnd_free */
_mysqlnd_free(void * ptr MYSQLND_MEM_D)480 static void _mysqlnd_free(void *ptr MYSQLND_MEM_D)
481 {
482 	size_t free_amount = 0;
483 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
484 	TRACE_ALLOC_ENTER(mysqlnd_free_name);
485 
486 #if PHP_DEBUG
487 	{
488 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
489 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
490 	}
491 #endif
492 	TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
493 
494 	if (ptr) {
495 		if (collect_memory_statistics) {
496 			free_amount = *(size_t *)(((char*)ptr) - sizeof(size_t));
497 			TRACE_ALLOC_INF_FMT("ptr=%p size=%u", ((char*)ptr) - sizeof(size_t), (unsigned int) free_amount);
498 		}
499 		free(REAL_PTR(ptr));
500 	}
501 
502 	if (collect_memory_statistics) {
503 		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_FREE_COUNT, 1, STAT_MEM_FREE_AMOUNT, free_amount);
504 	}
505 	TRACE_ALLOC_VOID_RETURN;
506 }
507 /* }}} */
508 
509 
510 /* {{{ _mysqlnd_pememdup */
_mysqlnd_pememdup(const char * const ptr,size_t length,zend_bool persistent MYSQLND_MEM_D)511 static char * _mysqlnd_pememdup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
512 {
513 	char * ret;
514 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
515 	TRACE_ALLOC_ENTER(mysqlnd_pememdup_name);
516 
517 #if PHP_DEBUG
518 	{
519 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
520 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
521 	}
522 #endif
523 	TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
524 
525 	ret = pemalloc_rel(REAL_SIZE(length + 1), persistent);
526 	{
527 		char * dest = (char *) FAKE_PTR(ret);
528 		memcpy(dest, ptr, length);
529 	}
530 
531 	if (collect_memory_statistics) {
532 		*(size_t *) ret = length;
533 		MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_DUP_COUNT : STAT_MEM_EDUP_COUNT);
534 	}
535 
536 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
537 }
538 /* }}} */
539 
540 
541 /* {{{ _mysqlnd_pestrndup */
_mysqlnd_pestrndup(const char * const ptr,size_t length,zend_bool persistent MYSQLND_MEM_D)542 static char * _mysqlnd_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
543 {
544 	char * ret;
545 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
546 	TRACE_ALLOC_ENTER(mysqlnd_pestrndup_name);
547 
548 #if PHP_DEBUG
549 	{
550 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
551 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
552 	}
553 #endif
554 	TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
555 
556 	ret = pemalloc_rel(REAL_SIZE(length + 1), persistent);
557 	{
558 		size_t l = length;
559 		char * p = (char *) ptr;
560 		char * dest = (char *) FAKE_PTR(ret);
561 		while (*p && l--) {
562 			*dest++ = *p++;
563 		}
564 		*dest = '\0';
565 	}
566 
567 	if (collect_memory_statistics) {
568 		*(size_t *) ret = length;
569 		MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRNDUP_COUNT : STAT_MEM_ESTRNDUP_COUNT);
570 	}
571 
572 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
573 }
574 /* }}} */
575 
576 
577 #define SMART_STR_START_SIZE 2048
578 #define SMART_STR_PREALLOC 512
579 #include "zend_smart_str.h"
580 
581 
582 /* {{{ _mysqlnd_pestrdup */
_mysqlnd_pestrdup(const char * const ptr,zend_bool persistent MYSQLND_MEM_D)583 static char * _mysqlnd_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
584 {
585 	char * ret;
586 	smart_str tmp_str = {0, 0};
587 	const char * p = ptr;
588 	zend_bool collect_memory_statistics = MYSQLND_G(collect_memory_statistics);
589 	TRACE_ALLOC_ENTER(mysqlnd_pestrdup_name);
590 #if PHP_DEBUG
591 	{
592 		char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR);
593 		TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno);
594 	}
595 #endif
596 	TRACE_ALLOC_INF_FMT("ptr=%p", ptr);
597 	do {
598 		smart_str_appendc(&tmp_str, *p);
599 	} while (*p++);
600 
601 	ret = pemalloc_rel(ZSTR_LEN(tmp_str.s) + sizeof(size_t), persistent);
602 	memcpy(FAKE_PTR(ret), ZSTR_VAL(tmp_str.s), ZSTR_LEN(tmp_str.s));
603 
604 	if (ret && collect_memory_statistics) {
605 		*(size_t *) ret = ZSTR_LEN(tmp_str.s);
606 		MYSQLND_INC_GLOBAL_STATISTIC(persistent? STAT_MEM_STRDUP_COUNT : STAT_MEM_ESTRDUP_COUNT);
607 	}
608 	smart_str_free(&tmp_str);
609 
610 	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
611 }
612 /* }}} */
613 
614 
615 
616 
617 #endif /* MYSQLND_DEBUG_MEMORY */
618 
619 /* {{{ _mysqlnd_sprintf_free */
_mysqlnd_sprintf_free(char * p)620 static void _mysqlnd_sprintf_free(char * p)
621 {
622 	efree(p);
623 }
624 /* }}} */
625 
626 
627 /* {{{ _mysqlnd_sprintf */
_mysqlnd_sprintf(char ** pbuf,size_t max_len,const char * format,...)628 static int _mysqlnd_sprintf(char ** pbuf, size_t max_len, const char *format, ...)
629 {
630 	int len;
631 	va_list ap;
632 	va_start(ap, format);
633 	len = vspprintf(pbuf, max_len, format, ap);
634 	va_end(ap);
635 	return len;
636 }
637 /* }}} */
638 
639 /* {{{ _mysqlnd_vsprintf */
_mysqlnd_vsprintf(char ** pbuf,size_t max_len,const char * format,va_list ap)640 static int _mysqlnd_vsprintf(char ** pbuf, size_t max_len, const char * format, va_list ap)
641 {
642 	return vspprintf(pbuf, max_len, format, ap);
643 }
644 /* }}} */
645 
646 
647 
648 #if MYSQLND_DEBUG_MEMORY == 0
649 
650 /* {{{ mysqlnd_zend_mm_emalloc */
mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)651 static void * mysqlnd_zend_mm_emalloc(size_t size MYSQLND_MEM_D)
652 {
653 	return emalloc_rel(size);
654 }
655 /* }}} */
656 
657 
658 /* {{{ mysqlnd_zend_mm_pemalloc */
mysqlnd_zend_mm_pemalloc(size_t size,zend_bool persistent MYSQLND_MEM_D)659 static void * mysqlnd_zend_mm_pemalloc(size_t size, zend_bool persistent MYSQLND_MEM_D)
660 {
661 	return pemalloc_rel(size, persistent);
662 }
663 /* }}} */
664 
665 
666 /* {{{ mysqlnd_zend_mm_ecalloc */
mysqlnd_zend_mm_ecalloc(unsigned int nmemb,size_t size MYSQLND_MEM_D)667 static void * mysqlnd_zend_mm_ecalloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
668 {
669 	return ecalloc_rel(nmemb, size);
670 }
671 /* }}} */
672 
673 
674 /* {{{ mysqlnd_zend_mm_pecalloc */
mysqlnd_zend_mm_pecalloc(unsigned int nmemb,size_t size,zend_bool persistent MYSQLND_MEM_D)675 static void * mysqlnd_zend_mm_pecalloc(unsigned int nmemb, size_t size, zend_bool persistent MYSQLND_MEM_D)
676 {
677 	return pecalloc_rel(nmemb, size, persistent);
678 }
679 /* }}} */
680 
681 
682 /* {{{ mysqlnd_zend_mm_erealloc */
mysqlnd_zend_mm_erealloc(void * ptr,size_t new_size MYSQLND_MEM_D)683 static void * mysqlnd_zend_mm_erealloc(void *ptr, size_t new_size MYSQLND_MEM_D)
684 {
685 	return erealloc_rel(ptr, new_size);
686 }
687 /* }}} */
688 
689 
690 /* {{{ mysqlnd_zend_mm_perealloc */
mysqlnd_zend_mm_perealloc(void * ptr,size_t new_size,zend_bool persistent MYSQLND_MEM_D)691 static void * mysqlnd_zend_mm_perealloc(void *ptr, size_t new_size, zend_bool persistent MYSQLND_MEM_D)
692 {
693 	return perealloc_rel(ptr, new_size, persistent);
694 }
695 /* }}} */
696 
697 
698 /* {{{ mysqlnd_zend_mm_efree */
mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)699 static void mysqlnd_zend_mm_efree(void * ptr MYSQLND_MEM_D)
700 {
701 	efree_rel(ptr);
702 }
703 /* }}} */
704 
705 
706 /* {{{ mysqlnd_zend_mm_pefree */
mysqlnd_zend_mm_pefree(void * ptr,zend_bool persistent MYSQLND_MEM_D)707 static void mysqlnd_zend_mm_pefree(void * ptr, zend_bool persistent MYSQLND_MEM_D)
708 {
709 	pefree_rel(ptr, persistent);
710 }
711 /* }}} */
712 
713 
714 /* {{{ mysqlnd_zend_mm_malloc */
mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)715 static void * mysqlnd_zend_mm_malloc(size_t size MYSQLND_MEM_D)
716 {
717 	return malloc(size);
718 }
719 /* }}} */
720 
721 
722 /* {{{ mysqlnd_zend_mm_calloc */
mysqlnd_zend_mm_calloc(unsigned int nmemb,size_t size MYSQLND_MEM_D)723 static void * mysqlnd_zend_mm_calloc(unsigned int nmemb, size_t size MYSQLND_MEM_D)
724 {
725 	return calloc(nmemb, size);
726 }
727 /* }}} */
728 
729 
730 /* {{{ mysqlnd_zend_mm_realloc */
mysqlnd_zend_mm_realloc(void * ptr,size_t new_size MYSQLND_MEM_D)731 static void * mysqlnd_zend_mm_realloc(void * ptr, size_t new_size MYSQLND_MEM_D)
732 {
733 	return realloc(ptr, new_size);
734 }
735 /* }}} */
736 
737 
738 /* {{{ mysqlnd_zend_mm_free */
mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)739 static void mysqlnd_zend_mm_free(void * ptr MYSQLND_MEM_D)
740 {
741 	free(ptr);
742 }
743 /* }}} */
744 
745 
746 /* {{{ mysqlnd_zend_mm_pememdup */
mysqlnd_zend_mm_pememdup(const char * const ptr,size_t length,zend_bool persistent MYSQLND_MEM_D)747 static char * mysqlnd_zend_mm_pememdup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
748 {
749 	char * dest = pemalloc_rel(length, persistent);
750 	if (dest) {
751 		memcpy(dest, ptr, length);
752 	}
753 	return dest;
754 }
755 /* }}} */
756 
757 
758 /* {{{ mysqlnd_zend_mm_pestrndup */
mysqlnd_zend_mm_pestrndup(const char * const ptr,size_t length,zend_bool persistent MYSQLND_MEM_D)759 static char * mysqlnd_zend_mm_pestrndup(const char * const ptr, size_t length, zend_bool persistent MYSQLND_MEM_D)
760 {
761 	return persistent? zend_strndup(ptr, length ) : estrndup_rel(ptr, length);
762 }
763 /* }}} */
764 
765 
766 /* {{{ mysqlnd_zend_mm_pestrdup */
mysqlnd_zend_mm_pestrdup(const char * const ptr,zend_bool persistent MYSQLND_MEM_D)767 static char * mysqlnd_zend_mm_pestrdup(const char * const ptr, zend_bool persistent MYSQLND_MEM_D)
768 {
769 	return pestrdup_rel(ptr, persistent);
770 }
771 /* }}} */
772 
773 #endif
774 
775 
776 PHPAPI struct st_mysqlnd_allocator_methods mysqlnd_allocator =
777 {
778 #if MYSQLND_DEBUG_MEMORY == 1
779 	_mysqlnd_emalloc,
780 	_mysqlnd_pemalloc,
781 	_mysqlnd_ecalloc,
782 	_mysqlnd_pecalloc,
783 	_mysqlnd_erealloc,
784 	_mysqlnd_perealloc,
785 	_mysqlnd_efree,
786 	_mysqlnd_pefree,
787 	_mysqlnd_malloc,
788 	_mysqlnd_calloc,
789 	_mysqlnd_realloc,
790 	_mysqlnd_free,
791 	_mysqlnd_pememdup,
792 	_mysqlnd_pestrndup,
793 	_mysqlnd_pestrdup,
794 	_mysqlnd_sprintf,
795 	_mysqlnd_vsprintf,
796 	_mysqlnd_sprintf_free
797 #else
798 	mysqlnd_zend_mm_emalloc,
799 	mysqlnd_zend_mm_pemalloc,
800 	mysqlnd_zend_mm_ecalloc,
801 	mysqlnd_zend_mm_pecalloc,
802 	mysqlnd_zend_mm_erealloc,
803 	mysqlnd_zend_mm_perealloc,
804 	mysqlnd_zend_mm_efree,
805 	mysqlnd_zend_mm_pefree,
806 	mysqlnd_zend_mm_malloc,
807 	mysqlnd_zend_mm_calloc,
808 	mysqlnd_zend_mm_realloc,
809 	mysqlnd_zend_mm_free,
810 	mysqlnd_zend_mm_pememdup,
811 	mysqlnd_zend_mm_pestrndup,
812 	mysqlnd_zend_mm_pestrdup,
813 	_mysqlnd_sprintf,
814 	_mysqlnd_vsprintf,
815 	_mysqlnd_sprintf_free,
816 #endif
817 };
818