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