mem_dbg.c revision 296465
1/* crypto/mem_dbg.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#include <stdio.h>
60#include <stdlib.h>
61#include <time.h>
62#include "cryptlib.h"
63#include <openssl/crypto.h>
64#include <openssl/buffer.h>
65#include <openssl/bio.h>
66#include <openssl/lhash.h>
67
68static int mh_mode = CRYPTO_MEM_CHECK_OFF;
69/*
70 * The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE when
71 * the application asks for it (usually after library initialisation for
72 * which no book-keeping is desired). State CRYPTO_MEM_CHECK_ON exists only
73 * temporarily when the library thinks that certain allocations should not be
74 * checked (e.g. the data structures used for memory checking).  It is not
75 * suitable as an initial state: the library will unexpectedly enable memory
76 * checking when it executes one of those sections that want to disable
77 * checking temporarily. State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes
78 * no sense whatsoever.
79 */
80
81static unsigned long order = 0; /* number of memory requests */
82static LHASH *mh = NULL;        /* hash-table of memory requests (address as
83                                 * key); access requires MALLOC2 lock */
84
85typedef struct app_mem_info_st
86/*-
87 * For application-defined information (static C-string `info')
88 * to be displayed in memory leak list.
89 * Each thread has its own stack.  For applications, there is
90 *   CRYPTO_push_info("...")     to push an entry,
91 *   CRYPTO_pop_info()           to pop an entry,
92 *   CRYPTO_remove_all_info()    to pop all entries.
93 */
94{
95    unsigned long thread;
96    const char *file;
97    int line;
98    const char *info;
99    struct app_mem_info_st *next; /* tail of thread's stack */
100    int references;
101} APP_INFO;
102
103static void app_info_free(APP_INFO *);
104
105static LHASH *amih = NULL;      /* hash-table with those app_mem_info_st's
106                                 * that are at the top of their thread's
107                                 * stack (with `thread' as key); access
108                                 * requires MALLOC2 lock */
109
110typedef struct mem_st
111/* memory-block description */
112{
113    void *addr;
114    int num;
115    const char *file;
116    int line;
117    unsigned long thread;
118    unsigned long order;
119    time_t time;
120    APP_INFO *app_info;
121} MEM;
122
123static long options =           /* extra information to be recorded */
124#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
125    V_CRYPTO_MDEBUG_TIME |
126#endif
127#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
128    V_CRYPTO_MDEBUG_THREAD |
129#endif
130    0;
131
132static unsigned int num_disable = 0; /* num_disable > 0 iff mh_mode ==
133                                      * CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE) */
134static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
135                                            * CRYPTO_LOCK_MALLOC2 is locked
136                                            * exactly in this case (by the
137                                            * thread named in
138                                            * disabling_thread). */
139
140static void app_info_free(APP_INFO *inf)
141{
142    if (--(inf->references) <= 0) {
143        if (inf->next != NULL) {
144            app_info_free(inf->next);
145        }
146        OPENSSL_free(inf);
147    }
148}
149
150int CRYPTO_mem_ctrl(int mode)
151{
152    int ret = mh_mode;
153
154    CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
155    switch (mode) {
156        /*
157         * for applications (not to be called while multiple threads use the
158         * library):
159         */
160    case CRYPTO_MEM_CHECK_ON:  /* aka MemCheck_start() */
161        mh_mode = CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE;
162        num_disable = 0;
163        break;
164    case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
165        mh_mode = 0;
166        num_disable = 0;        /* should be true *before* MemCheck_stop is
167                                 * used, or there'll be a lot of confusion */
168        break;
169
170        /* switch off temporarily (for library-internal use): */
171    case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
172        if (mh_mode & CRYPTO_MEM_CHECK_ON) {
173            /* otherwise we already have the MALLOC2 lock */
174            if (!num_disable || (disabling_thread != CRYPTO_thread_id())) {
175                /*
176                 * Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed
177                 * while we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock
178                 * if somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot
179                 * release it because we block entry to this function). Give
180                 * them a chance, first, and then claim the locks in
181                 * appropriate order (long-time lock first).
182                 */
183                CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
184                /*
185                 * Note that after we have waited for CRYPTO_LOCK_MALLOC2 and
186                 * CRYPTO_LOCK_MALLOC, we'll still be in the right "case" and
187                 * "if" branch because MemCheck_start and MemCheck_stop may
188                 * never be used while there are multiple OpenSSL threads.
189                 */
190                CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
191                CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
192                mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
193                disabling_thread = CRYPTO_thread_id();
194            }
195            num_disable++;
196        }
197        break;
198    case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
199        if (mh_mode & CRYPTO_MEM_CHECK_ON) {
200            if (num_disable) {  /* always true, or something is going wrong */
201                num_disable--;
202                if (num_disable == 0) {
203                    mh_mode |= CRYPTO_MEM_CHECK_ENABLE;
204                    CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
205                }
206            }
207        }
208        break;
209
210    default:
211        break;
212    }
213    CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
214    return (ret);
215}
216
217int CRYPTO_is_mem_check_on(void)
218{
219    int ret = 0;
220
221    if (mh_mode & CRYPTO_MEM_CHECK_ON) {
222        CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
223
224        ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
225            || (disabling_thread != CRYPTO_thread_id());
226
227        CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
228    }
229    return (ret);
230}
231
232void CRYPTO_dbg_set_options(long bits)
233{
234    options = bits;
235}
236
237long CRYPTO_dbg_get_options(void)
238{
239    return options;
240}
241
242/* static int mem_cmp(MEM *a, MEM *b) */
243static int mem_cmp(const void *a_void, const void *b_void)
244{
245#ifdef _WIN64
246    const char *a = (const char *)((const MEM *)a_void)->addr,
247        *b = (const char *)((const MEM *)b_void)->addr;
248    if (a == b)
249        return 0;
250    else if (a > b)
251        return 1;
252    else
253        return -1;
254#else
255    return ((const char *)((const MEM *)a_void)->addr
256            - (const char *)((const MEM *)b_void)->addr);
257#endif
258}
259
260/* static unsigned long mem_hash(MEM *a) */
261static unsigned long mem_hash(const void *a_void)
262{
263    unsigned long ret;
264
265    ret = (unsigned long)((const MEM *)a_void)->addr;
266
267    ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
268    return (ret);
269}
270
271/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
272static int app_info_cmp(const void *a_void, const void *b_void)
273{
274    return (((const APP_INFO *)a_void)->thread
275            != ((const APP_INFO *)b_void)->thread);
276}
277
278/* static unsigned long app_info_hash(APP_INFO *a) */
279static unsigned long app_info_hash(const void *a_void)
280{
281    unsigned long ret;
282
283    ret = (unsigned long)((const APP_INFO *)a_void)->thread;
284
285    ret = ret * 17851 + (ret >> 14) * 7 + (ret >> 4) * 251;
286    return (ret);
287}
288
289static APP_INFO *pop_info(void)
290{
291    APP_INFO tmp;
292    APP_INFO *ret = NULL;
293
294    if (amih != NULL) {
295        tmp.thread = CRYPTO_thread_id();
296        if ((ret = (APP_INFO *)lh_delete(amih, &tmp)) != NULL) {
297            APP_INFO *next = ret->next;
298
299            if (next != NULL) {
300                next->references++;
301                lh_insert(amih, (char *)next);
302            }
303#ifdef LEVITTE_DEBUG_MEM
304            if (ret->thread != tmp.thread) {
305                fprintf(stderr,
306                        "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
307                        ret->thread, tmp.thread);
308                abort();
309            }
310#endif
311            if (--(ret->references) <= 0) {
312                ret->next = NULL;
313                if (next != NULL)
314                    next->references--;
315                OPENSSL_free(ret);
316            }
317        }
318    }
319    return (ret);
320}
321
322int CRYPTO_dbg_push_info(const char *info, const char *file, int line)
323{
324    APP_INFO *ami, *amim;
325    int ret = 0;
326
327    if (is_MemCheck_on()) {
328        MemCheck_off();         /* obtain MALLOC2 lock */
329
330        if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL) {
331            ret = 0;
332            goto err;
333        }
334        if (amih == NULL) {
335            if ((amih = lh_new(app_info_hash, app_info_cmp)) == NULL) {
336                OPENSSL_free(ami);
337                ret = 0;
338                goto err;
339            }
340        }
341
342        ami->thread = CRYPTO_thread_id();
343        ami->file = file;
344        ami->line = line;
345        ami->info = info;
346        ami->references = 1;
347        ami->next = NULL;
348
349        if ((amim = (APP_INFO *)lh_insert(amih, (char *)ami)) != NULL) {
350#ifdef LEVITTE_DEBUG_MEM
351            if (ami->thread != amim->thread) {
352                fprintf(stderr,
353                        "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
354                        amim->thread, ami->thread);
355                abort();
356            }
357#endif
358            ami->next = amim;
359        }
360 err:
361        MemCheck_on();          /* release MALLOC2 lock */
362    }
363
364    return (ret);
365}
366
367int CRYPTO_dbg_pop_info(void)
368{
369    int ret = 0;
370
371    if (is_MemCheck_on()) {     /* _must_ be true, or something went severely
372                                 * wrong */
373        MemCheck_off();         /* obtain MALLOC2 lock */
374
375        ret = (pop_info() != NULL);
376
377        MemCheck_on();          /* release MALLOC2 lock */
378    }
379    return (ret);
380}
381
382int CRYPTO_dbg_remove_all_info(void)
383{
384    int ret = 0;
385
386    if (is_MemCheck_on()) {     /* _must_ be true */
387        MemCheck_off();         /* obtain MALLOC2 lock */
388
389        while (pop_info() != NULL)
390            ret++;
391
392        MemCheck_on();          /* release MALLOC2 lock */
393    }
394    return (ret);
395}
396
397static unsigned long break_order_num = 0;
398void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
399                       int before_p)
400{
401    MEM *m, *mm;
402    APP_INFO tmp, *amim;
403
404    switch (before_p & 127) {
405    case 0:
406        break;
407    case 1:
408        if (addr == NULL)
409            break;
410
411        if (is_MemCheck_on()) {
412            MemCheck_off();     /* make sure we hold MALLOC2 lock */
413            if ((m = (MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL) {
414                OPENSSL_free(addr);
415                MemCheck_on();  /* release MALLOC2 lock if num_disabled drops
416                                 * to 0 */
417                return;
418            }
419            if (mh == NULL) {
420                if ((mh = lh_new(mem_hash, mem_cmp)) == NULL) {
421                    OPENSSL_free(addr);
422                    OPENSSL_free(m);
423                    addr = NULL;
424                    goto err;
425                }
426            }
427
428            m->addr = addr;
429            m->file = file;
430            m->line = line;
431            m->num = num;
432            if (options & V_CRYPTO_MDEBUG_THREAD)
433                m->thread = CRYPTO_thread_id();
434            else
435                m->thread = 0;
436
437            if (order == break_order_num) {
438                /* BREAK HERE */
439                m->order = order;
440            }
441            m->order = order++;
442#ifdef LEVITTE_DEBUG_MEM
443            fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
444                    m->order, (before_p & 128) ? '*' : '+', m->addr, m->num);
445#endif
446            if (options & V_CRYPTO_MDEBUG_TIME)
447                m->time = time(NULL);
448            else
449                m->time = 0;
450
451            tmp.thread = CRYPTO_thread_id();
452            m->app_info = NULL;
453            if (amih != NULL
454                && (amim =
455                    (APP_INFO *)lh_retrieve(amih, (char *)&tmp)) != NULL) {
456                m->app_info = amim;
457                amim->references++;
458            }
459
460            if ((mm = (MEM *)lh_insert(mh, (char *)m)) != NULL) {
461                /* Not good, but don't sweat it */
462                if (mm->app_info != NULL) {
463                    mm->app_info->references--;
464                }
465                OPENSSL_free(mm);
466            }
467 err:
468            MemCheck_on();      /* release MALLOC2 lock if num_disabled drops
469                                 * to 0 */
470        }
471        break;
472    }
473    return;
474}
475
476void CRYPTO_dbg_free(void *addr, int before_p)
477{
478    MEM m, *mp;
479
480    switch (before_p) {
481    case 0:
482        if (addr == NULL)
483            break;
484
485        if (is_MemCheck_on() && (mh != NULL)) {
486            MemCheck_off();     /* make sure we hold MALLOC2 lock */
487
488            m.addr = addr;
489            mp = (MEM *)lh_delete(mh, (char *)&m);
490            if (mp != NULL) {
491#ifdef LEVITTE_DEBUG_MEM
492                fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
493                        mp->order, mp->addr, mp->num);
494#endif
495                if (mp->app_info != NULL)
496                    app_info_free(mp->app_info);
497                OPENSSL_free(mp);
498            }
499
500            MemCheck_on();      /* release MALLOC2 lock if num_disabled drops
501                                 * to 0 */
502        }
503        break;
504    case 1:
505        break;
506    }
507}
508
509void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
510                        const char *file, int line, int before_p)
511{
512    MEM m, *mp;
513
514#ifdef LEVITTE_DEBUG_MEM
515    fprintf(stderr,
516            "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
517            addr1, addr2, num, file, line, before_p);
518#endif
519
520    switch (before_p) {
521    case 0:
522        break;
523    case 1:
524        if (addr2 == NULL)
525            break;
526
527        if (addr1 == NULL) {
528            CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
529            break;
530        }
531
532        if (is_MemCheck_on()) {
533            MemCheck_off();     /* make sure we hold MALLOC2 lock */
534
535            m.addr = addr1;
536            mp = (MEM *)lh_delete(mh, (char *)&m);
537            if (mp != NULL) {
538#ifdef LEVITTE_DEBUG_MEM
539                fprintf(stderr,
540                        "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
541                        mp->order, mp->addr, mp->num, addr2, num);
542#endif
543                mp->addr = addr2;
544                mp->num = num;
545                lh_insert(mh, (char *)mp);
546            }
547
548            MemCheck_on();      /* release MALLOC2 lock if num_disabled drops
549                                 * to 0 */
550        }
551        break;
552    }
553    return;
554}
555
556typedef struct mem_leak_st {
557    BIO *bio;
558    int chunks;
559    long bytes;
560} MEM_LEAK;
561
562static void print_leak(const MEM *m, MEM_LEAK *l)
563{
564    char buf[1024];
565    char *bufp = buf;
566    APP_INFO *amip;
567    int ami_cnt;
568    struct tm *lcl = NULL;
569    unsigned long ti;
570
571#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
572
573    if (m->addr == (char *)l->bio)
574        return;
575
576    if (options & V_CRYPTO_MDEBUG_TIME) {
577        lcl = localtime(&m->time);
578
579        BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
580                     lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
581        bufp += strlen(bufp);
582    }
583
584    BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
585                 m->order, m->file, m->line);
586    bufp += strlen(bufp);
587
588    if (options & V_CRYPTO_MDEBUG_THREAD) {
589        BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
590        bufp += strlen(bufp);
591    }
592
593    BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
594                 m->num, (unsigned long)m->addr);
595    bufp += strlen(bufp);
596
597    BIO_puts(l->bio, buf);
598
599    l->chunks++;
600    l->bytes += m->num;
601
602    amip = m->app_info;
603    ami_cnt = 0;
604    if (!amip)
605        return;
606    ti = amip->thread;
607
608    do {
609        int buf_len;
610        int info_len;
611
612        ami_cnt++;
613        memset(buf, '>', ami_cnt);
614        BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
615                     " thread=%lu, file=%s, line=%d, info=\"",
616                     amip->thread, amip->file, amip->line);
617        buf_len = strlen(buf);
618        info_len = strlen(amip->info);
619        if (128 - buf_len - 3 < info_len) {
620            memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
621            buf_len = 128 - 3;
622        } else {
623            BUF_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len);
624            buf_len = strlen(buf);
625        }
626        BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
627
628        BIO_puts(l->bio, buf);
629
630        amip = amip->next;
631    }
632    while (amip && amip->thread == ti);
633
634#ifdef LEVITTE_DEBUG_MEM
635    if (amip) {
636        fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
637        abort();
638    }
639#endif
640}
641
642static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
643
644void CRYPTO_mem_leaks(BIO *b)
645{
646    MEM_LEAK ml;
647
648    if (mh == NULL && amih == NULL)
649        return;
650
651    MemCheck_off();             /* obtain MALLOC2 lock */
652
653    ml.bio = b;
654    ml.bytes = 0;
655    ml.chunks = 0;
656    if (mh != NULL)
657        lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), (char *)&ml);
658    if (ml.chunks != 0) {
659        BIO_printf(b, "%ld bytes leaked in %d chunks\n", ml.bytes, ml.chunks);
660    } else {
661        /*
662         * Make sure that, if we found no leaks, memory-leak debugging itself
663         * does not introduce memory leaks (which might irritate external
664         * debugging tools). (When someone enables leak checking, but does not
665         * call this function, we declare it to be their fault.) XXX This
666         * should be in CRYPTO_mem_leaks_cb, and CRYPTO_mem_leaks should be
667         * implemented by using CRYPTO_mem_leaks_cb. (Also their should be a
668         * variant of lh_doall_arg that takes a function pointer instead of a
669         * void *; this would obviate the ugly and illegal void_fn_to_char
670         * kludge in CRYPTO_mem_leaks_cb. Otherwise the code police will come
671         * and get us.)
672         */
673        int old_mh_mode;
674
675        CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
676
677        /*
678         * avoid deadlock when lh_free() uses CRYPTO_dbg_free(), which uses
679         * CRYPTO_is_mem_check_on
680         */
681        old_mh_mode = mh_mode;
682        mh_mode = CRYPTO_MEM_CHECK_OFF;
683
684        if (mh != NULL) {
685            lh_free(mh);
686            mh = NULL;
687        }
688        if (amih != NULL) {
689            if (lh_num_items(amih) == 0) {
690                lh_free(amih);
691                amih = NULL;
692            }
693        }
694
695        mh_mode = old_mh_mode;
696        CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
697    }
698    MemCheck_on();              /* release MALLOC2 lock */
699}
700
701#ifndef OPENSSL_NO_FP_API
702void CRYPTO_mem_leaks_fp(FILE *fp)
703{
704    BIO *b;
705
706    if (mh == NULL)
707        return;
708    /*
709     * Need to turn off memory checking when allocated BIOs ... especially as
710     * we're creating them at a time when we're trying to check we've not
711     * left anything un-free()'d!!
712     */
713    MemCheck_off();
714    b = BIO_new(BIO_s_file());
715    MemCheck_on();
716    if (!b)
717        return;
718    BIO_set_fp(b, fp, BIO_NOCLOSE);
719    CRYPTO_mem_leaks(b);
720    BIO_free(b);
721}
722#endif
723
724/*
725 * FIXME: We really don't allow much to the callback.  For example, it has no
726 * chance of reaching the info stack for the item it processes.  Should it
727 * really be this way? -- Richard Levitte
728 */
729/*
730 * NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside
731 * crypto.h If this code is restructured, remove the callback type if it is
732 * no longer needed. -- Geoff Thorpe
733 */
734static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
735{
736    (**cb) (m->order, m->file, m->line, m->num, m->addr);
737}
738
739static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *,
740                                    CRYPTO_MEM_LEAK_CB **)
741
742void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
743{
744    if (mh == NULL)
745        return;
746    CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
747    lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
748    CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
749}
750
751void CRYPTO_malloc_debug_init(void)
752{
753    CRYPTO_set_mem_debug_functions(CRYPTO_dbg_malloc,
754                                   CRYPTO_dbg_realloc,
755                                   CRYPTO_dbg_free,
756                                   CRYPTO_dbg_set_options,
757                                   CRYPTO_dbg_get_options);
758    CRYPTO_set_mem_info_functions(CRYPTO_dbg_push_info,
759                                  CRYPTO_dbg_pop_info,
760                                  CRYPTO_dbg_remove_all_info);
761}
762
763char *CRYPTO_strdup(const char *str, const char *file, int line)
764{
765    char *ret = CRYPTO_malloc(strlen(str) + 1, file, line);
766
767    strcpy(ret, str);
768    return ret;
769}
770