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