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