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