~ubuntu-branches/ubuntu/precise/openssl098/precise

« back to all changes in this revision

Viewing changes to crypto/mem_dbg.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2011-03-23 19:50:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110323195031-6h9crj4bymhhr8b8
Tags: upstream-0.9.8o
ImportĀ upstreamĀ versionĀ 0.9.8o

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
68
static int mh_mode=CRYPTO_MEM_CHECK_OFF;
 
69
/* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
 
70
 * when the application asks for it (usually after library initialisation
 
71
 * for which no book-keeping is desired).
 
72
 *
 
73
 * State CRYPTO_MEM_CHECK_ON exists only temporarily when the library
 
74
 * thinks that certain allocations should not be checked (e.g. the data
 
75
 * structures used for memory checking).  It is not suitable as an initial
 
76
 * state: the library will unexpectedly enable memory checking when it
 
77
 * executes one of those sections that want to disable checking
 
78
 * temporarily.
 
79
 *
 
80
 * State CRYPTO_MEM_CHECK_ENABLE without ..._ON makes no sense whatsoever.
 
81
 */
 
82
 
 
83
static unsigned long order = 0; /* number of memory requests */
 
84
static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
 
85
                        * access requires MALLOC2 lock */
 
86
 
 
87
 
 
88
typedef struct app_mem_info_st
 
89
/* For application-defined information (static C-string `info')
 
90
 * to be displayed in memory leak list.
 
91
 * Each thread has its own stack.  For applications, there is
 
92
 *   CRYPTO_push_info("...")     to push an entry,
 
93
 *   CRYPTO_pop_info()           to pop an entry,
 
94
 *   CRYPTO_remove_all_info()    to pop all entries.
 
95
 */
 
96
        {       
 
97
        unsigned long thread;
 
98
        const char *file;
 
99
        int line;
 
100
        const char *info;
 
101
        struct app_mem_info_st *next; /* tail of thread's stack */
 
102
        int references;
 
103
        } APP_INFO;
 
104
 
 
105
static void app_info_free(APP_INFO *);
 
106
 
 
107
static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
 
108
                          * that are at the top of their thread's stack
 
109
                          * (with `thread' as key);
 
110
                          * access requires MALLOC2 lock */
 
111
 
 
112
typedef struct mem_st
 
113
/* memory-block description */
 
114
        {
 
115
        void *addr;
 
116
        int num;
 
117
        const char *file;
 
118
        int line;
 
119
        unsigned long thread;
 
120
        unsigned long order;
 
121
        time_t time;
 
122
        APP_INFO *app_info;
 
123
        } MEM;
 
124
 
 
125
static long options =             /* extra information to be recorded */
 
126
#if defined(CRYPTO_MDEBUG_TIME) || defined(CRYPTO_MDEBUG_ALL)
 
127
        V_CRYPTO_MDEBUG_TIME |
 
128
#endif
 
129
#if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
 
130
        V_CRYPTO_MDEBUG_THREAD |
 
131
#endif
 
132
        0;
 
133
 
 
134
 
 
135
static unsigned int num_disable = 0; /* num_disable > 0
 
136
                                      *     iff
 
137
                                      * mh_mode == CRYPTO_MEM_CHECK_ON (w/o ..._ENABLE)
 
138
                                      */
 
139
static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
 
140
                                            * CRYPTO_LOCK_MALLOC2 is locked
 
141
                                            * exactly in this case (by the
 
142
                                            * thread named in disabling_thread).
 
143
                                            */
 
144
 
 
145
static void app_info_free(APP_INFO *inf)
 
146
        {
 
147
        if (--(inf->references) <= 0)
 
148
                {
 
149
                if (inf->next != NULL)
 
150
                        {
 
151
                        app_info_free(inf->next);
 
152
                        }
 
153
                OPENSSL_free(inf);
 
154
                }
 
155
        }
 
156
 
 
157
int CRYPTO_mem_ctrl(int mode)
 
158
        {
 
159
        int ret=mh_mode;
 
160
 
 
161
        CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
 
162
        switch (mode)
 
163
                {
 
164
        /* for applications (not to be called while multiple threads
 
165
         * use the library): */
 
166
        case CRYPTO_MEM_CHECK_ON: /* aka MemCheck_start() */
 
167
                mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
 
168
                num_disable = 0;
 
169
                break;
 
170
        case CRYPTO_MEM_CHECK_OFF: /* aka MemCheck_stop() */
 
171
                mh_mode = 0;
 
172
                num_disable = 0; /* should be true *before* MemCheck_stop is used,
 
173
                                    or there'll be a lot of confusion */
 
174
                break;
 
175
 
 
176
        /* switch off temporarily (for library-internal use): */
 
177
        case CRYPTO_MEM_CHECK_DISABLE: /* aka MemCheck_off() */
 
178
                if (mh_mode & CRYPTO_MEM_CHECK_ON)
 
179
                        {
 
180
                        if (!num_disable || (disabling_thread != CRYPTO_thread_id())) /* otherwise we already have the MALLOC2 lock */
 
181
                                {
 
182
                                /* Long-time lock CRYPTO_LOCK_MALLOC2 must not be claimed while
 
183
                                 * we're holding CRYPTO_LOCK_MALLOC, or we'll deadlock if
 
184
                                 * somebody else holds CRYPTO_LOCK_MALLOC2 (and cannot release
 
185
                                 * it because we block entry to this function).
 
186
                                 * Give them a chance, first, and then claim the locks in
 
187
                                 * appropriate order (long-time lock first).
 
188
                                 */
 
189
                                CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
 
190
                                /* Note that after we have waited for CRYPTO_LOCK_MALLOC2
 
191
                                 * and CRYPTO_LOCK_MALLOC, we'll still be in the right
 
192
                                 * "case" and "if" branch because MemCheck_start and
 
193
                                 * MemCheck_stop may never be used while there are multiple
 
194
                                 * OpenSSL threads. */
 
195
                                CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
 
196
                                CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
 
197
                                mh_mode &= ~CRYPTO_MEM_CHECK_ENABLE;
 
198
                                disabling_thread=CRYPTO_thread_id();
 
199
                                }
 
200
                        num_disable++;
 
201
                        }
 
202
                break;
 
203
        case CRYPTO_MEM_CHECK_ENABLE: /* aka MemCheck_on() */
 
204
                if (mh_mode & CRYPTO_MEM_CHECK_ON)
 
205
                        {
 
206
                        if (num_disable) /* always true, or something is going wrong */
 
207
                                {
 
208
                                num_disable--;
 
209
                                if (num_disable == 0)
 
210
                                        {
 
211
                                        mh_mode|=CRYPTO_MEM_CHECK_ENABLE;
 
212
                                        CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
 
213
                                        }
 
214
                                }
 
215
                        }
 
216
                break;
 
217
 
 
218
        default:
 
219
                break;
 
220
                }
 
221
        CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
 
222
        return(ret);
 
223
        }
 
224
 
 
225
int CRYPTO_is_mem_check_on(void)
 
226
        {
 
227
        int ret = 0;
 
228
 
 
229
        if (mh_mode & CRYPTO_MEM_CHECK_ON)
 
230
                {
 
231
                CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
 
232
 
 
233
                ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
 
234
                        || (disabling_thread != CRYPTO_thread_id());
 
235
 
 
236
                CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
 
237
                }
 
238
        return(ret);
 
239
        }       
 
240
 
 
241
 
 
242
void CRYPTO_dbg_set_options(long bits)
 
243
        {
 
244
        options = bits;
 
245
        }
 
246
 
 
247
long CRYPTO_dbg_get_options(void)
 
248
        {
 
249
        return options;
 
250
        }
 
251
 
 
252
/* static int mem_cmp(MEM *a, MEM *b) */
 
253
static int mem_cmp(const void *a_void, const void *b_void)
 
254
        {
 
255
#ifdef _WIN64
 
256
        const char *a=(const char *)((const MEM *)a_void)->addr,
 
257
                   *b=(const char *)((const MEM *)b_void)->addr;
 
258
        if (a==b)       return 0;
 
259
        else if (a>b)   return 1;
 
260
        else            return -1;
 
261
#else
 
262
        return((const char *)((const MEM *)a_void)->addr
 
263
                - (const char *)((const MEM *)b_void)->addr);
 
264
#endif
 
265
        }
 
266
 
 
267
/* static unsigned long mem_hash(MEM *a) */
 
268
static unsigned long mem_hash(const void *a_void)
 
269
        {
 
270
        unsigned long ret;
 
271
 
 
272
        ret=(unsigned long)((const MEM *)a_void)->addr;
 
273
 
 
274
        ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
 
275
        return(ret);
 
276
        }
 
277
 
 
278
/* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
 
279
static int app_info_cmp(const void *a_void, const void *b_void)
 
280
        {
 
281
        return(((const APP_INFO *)a_void)->thread
 
282
                != ((const APP_INFO *)b_void)->thread);
 
283
        }
 
284
 
 
285
/* static unsigned long app_info_hash(APP_INFO *a) */
 
286
static unsigned long app_info_hash(const void *a_void)
 
287
        {
 
288
        unsigned long ret;
 
289
 
 
290
        ret=(unsigned long)((const APP_INFO *)a_void)->thread;
 
291
 
 
292
        ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
 
293
        return(ret);
 
294
        }
 
295
 
 
296
static APP_INFO *pop_info(void)
 
297
        {
 
298
        APP_INFO tmp;
 
299
        APP_INFO *ret = NULL;
 
300
 
 
301
        if (amih != NULL)
 
302
                {
 
303
                tmp.thread=CRYPTO_thread_id();
 
304
                if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
 
305
                        {
 
306
                        APP_INFO *next=ret->next;
 
307
 
 
308
                        if (next != NULL)
 
309
                                {
 
310
                                next->references++;
 
311
                                lh_insert(amih,(char *)next);
 
312
                                }
 
313
#ifdef LEVITTE_DEBUG_MEM
 
314
                        if (ret->thread != tmp.thread)
 
315
                                {
 
316
                                fprintf(stderr, "pop_info(): deleted info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
 
317
                                        ret->thread, tmp.thread);
 
318
                                abort();
 
319
                                }
 
320
#endif
 
321
                        if (--(ret->references) <= 0)
 
322
                                {
 
323
                                ret->next = NULL;
 
324
                                if (next != NULL)
 
325
                                        next->references--;
 
326
                                OPENSSL_free(ret);
 
327
                                }
 
328
                        }
 
329
                }
 
330
        return(ret);
 
331
        }
 
332
 
 
333
int CRYPTO_dbg_push_info(const char *info, const char *file, int line)
 
334
        {
 
335
        APP_INFO *ami, *amim;
 
336
        int ret=0;
 
337
 
 
338
        if (is_MemCheck_on())
 
339
                {
 
340
                MemCheck_off(); /* obtain MALLOC2 lock */
 
341
 
 
342
                if ((ami = (APP_INFO *)OPENSSL_malloc(sizeof(APP_INFO))) == NULL)
 
343
                        {
 
344
                        ret=0;
 
345
                        goto err;
 
346
                        }
 
347
                if (amih == NULL)
 
348
                        {
 
349
                        if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
 
350
                                {
 
351
                                OPENSSL_free(ami);
 
352
                                ret=0;
 
353
                                goto err;
 
354
                                }
 
355
                        }
 
356
 
 
357
                ami->thread=CRYPTO_thread_id();
 
358
                ami->file=file;
 
359
                ami->line=line;
 
360
                ami->info=info;
 
361
                ami->references=1;
 
362
                ami->next=NULL;
 
363
 
 
364
                if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
 
365
                        {
 
366
#ifdef LEVITTE_DEBUG_MEM
 
367
                        if (ami->thread != amim->thread)
 
368
                                {
 
369
                                fprintf(stderr, "CRYPTO_push_info(): previous info has other thread ID (%lu) than the current thread (%lu)!!!!\n",
 
370
                                        amim->thread, ami->thread);
 
371
                                abort();
 
372
                                }
 
373
#endif
 
374
                        ami->next=amim;
 
375
                        }
 
376
 err:
 
377
                MemCheck_on(); /* release MALLOC2 lock */
 
378
                }
 
379
 
 
380
        return(ret);
 
381
        }
 
382
 
 
383
int CRYPTO_dbg_pop_info(void)
 
384
        {
 
385
        int ret=0;
 
386
 
 
387
        if (is_MemCheck_on()) /* _must_ be true, or something went severely wrong */
 
388
                {
 
389
                MemCheck_off(); /* obtain MALLOC2 lock */
 
390
 
 
391
                ret=(pop_info() != NULL);
 
392
 
 
393
                MemCheck_on(); /* release MALLOC2 lock */
 
394
                }
 
395
        return(ret);
 
396
        }
 
397
 
 
398
int CRYPTO_dbg_remove_all_info(void)
 
399
        {
 
400
        int ret=0;
 
401
 
 
402
        if (is_MemCheck_on()) /* _must_ be true */
 
403
                {
 
404
                MemCheck_off(); /* obtain MALLOC2 lock */
 
405
 
 
406
                while(pop_info() != NULL)
 
407
                        ret++;
 
408
 
 
409
                MemCheck_on(); /* release MALLOC2 lock */
 
410
                }
 
411
        return(ret);
 
412
        }
 
413
 
 
414
 
 
415
static unsigned long break_order_num=0;
 
416
void CRYPTO_dbg_malloc(void *addr, int num, const char *file, int line,
 
417
        int before_p)
 
418
        {
 
419
        MEM *m,*mm;
 
420
        APP_INFO tmp,*amim;
 
421
 
 
422
        switch(before_p & 127)
 
423
                {
 
424
        case 0:
 
425
                break;
 
426
        case 1:
 
427
                if (addr == NULL)
 
428
                        break;
 
429
 
 
430
                if (is_MemCheck_on())
 
431
                        {
 
432
                        MemCheck_off(); /* make sure we hold MALLOC2 lock */
 
433
                        if ((m=(MEM *)OPENSSL_malloc(sizeof(MEM))) == NULL)
 
434
                                {
 
435
                                OPENSSL_free(addr);
 
436
                                MemCheck_on(); /* release MALLOC2 lock
 
437
                                                * if num_disabled drops to 0 */
 
438
                                return;
 
439
                                }
 
440
                        if (mh == NULL)
 
441
                                {
 
442
                                if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
 
443
                                        {
 
444
                                        OPENSSL_free(addr);
 
445
                                        OPENSSL_free(m);
 
446
                                        addr=NULL;
 
447
                                        goto err;
 
448
                                        }
 
449
                                }
 
450
 
 
451
                        m->addr=addr;
 
452
                        m->file=file;
 
453
                        m->line=line;
 
454
                        m->num=num;
 
455
                        if (options & V_CRYPTO_MDEBUG_THREAD)
 
456
                                m->thread=CRYPTO_thread_id();
 
457
                        else
 
458
                                m->thread=0;
 
459
 
 
460
                        if (order == break_order_num)
 
461
                                {
 
462
                                /* BREAK HERE */
 
463
                                m->order=order;
 
464
                                }
 
465
                        m->order=order++;
 
466
#ifdef LEVITTE_DEBUG_MEM
 
467
                        fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] %c 0x%p (%d)\n",
 
468
                                m->order,
 
469
                                (before_p & 128) ? '*' : '+',
 
470
                                m->addr, m->num);
 
471
#endif
 
472
                        if (options & V_CRYPTO_MDEBUG_TIME)
 
473
                                m->time=time(NULL);
 
474
                        else
 
475
                                m->time=0;
 
476
 
 
477
                        tmp.thread=CRYPTO_thread_id();
 
478
                        m->app_info=NULL;
 
479
                        if (amih != NULL
 
480
                                && (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
 
481
                                {
 
482
                                m->app_info = amim;
 
483
                                amim->references++;
 
484
                                }
 
485
 
 
486
                        if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
 
487
                                {
 
488
                                /* Not good, but don't sweat it */
 
489
                                if (mm->app_info != NULL)
 
490
                                        {
 
491
                                        mm->app_info->references--;
 
492
                                        }
 
493
                                OPENSSL_free(mm);
 
494
                                }
 
495
                err:
 
496
                        MemCheck_on(); /* release MALLOC2 lock
 
497
                                        * if num_disabled drops to 0 */
 
498
                        }
 
499
                break;
 
500
                }
 
501
        return;
 
502
        }
 
503
 
 
504
void CRYPTO_dbg_free(void *addr, int before_p)
 
505
        {
 
506
        MEM m,*mp;
 
507
 
 
508
        switch(before_p)
 
509
                {
 
510
        case 0:
 
511
                if (addr == NULL)
 
512
                        break;
 
513
 
 
514
                if (is_MemCheck_on() && (mh != NULL))
 
515
                        {
 
516
                        MemCheck_off(); /* make sure we hold MALLOC2 lock */
 
517
 
 
518
                        m.addr=addr;
 
519
                        mp=(MEM *)lh_delete(mh,(char *)&m);
 
520
                        if (mp != NULL)
 
521
                                {
 
522
#ifdef LEVITTE_DEBUG_MEM
 
523
                        fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] - 0x%p (%d)\n",
 
524
                                mp->order, mp->addr, mp->num);
 
525
#endif
 
526
                                if (mp->app_info != NULL)
 
527
                                        app_info_free(mp->app_info);
 
528
                                OPENSSL_free(mp);
 
529
                                }
 
530
 
 
531
                        MemCheck_on(); /* release MALLOC2 lock
 
532
                                        * if num_disabled drops to 0 */
 
533
                        }
 
534
                break;
 
535
        case 1:
 
536
                break;
 
537
                }
 
538
        }
 
539
 
 
540
void CRYPTO_dbg_realloc(void *addr1, void *addr2, int num,
 
541
        const char *file, int line, int before_p)
 
542
        {
 
543
        MEM m,*mp;
 
544
 
 
545
#ifdef LEVITTE_DEBUG_MEM
 
546
        fprintf(stderr, "LEVITTE_DEBUG_MEM: --> CRYPTO_dbg_malloc(addr1 = %p, addr2 = %p, num = %d, file = \"%s\", line = %d, before_p = %d)\n",
 
547
                addr1, addr2, num, file, line, before_p);
 
548
#endif
 
549
 
 
550
        switch(before_p)
 
551
                {
 
552
        case 0:
 
553
                break;
 
554
        case 1:
 
555
                if (addr2 == NULL)
 
556
                        break;
 
557
 
 
558
                if (addr1 == NULL)
 
559
                        {
 
560
                        CRYPTO_dbg_malloc(addr2, num, file, line, 128 | before_p);
 
561
                        break;
 
562
                        }
 
563
 
 
564
                if (is_MemCheck_on())
 
565
                        {
 
566
                        MemCheck_off(); /* make sure we hold MALLOC2 lock */
 
567
 
 
568
                        m.addr=addr1;
 
569
                        mp=(MEM *)lh_delete(mh,(char *)&m);
 
570
                        if (mp != NULL)
 
571
                                {
 
572
#ifdef LEVITTE_DEBUG_MEM
 
573
                                fprintf(stderr, "LEVITTE_DEBUG_MEM: [%5d] * 0x%p (%d) -> 0x%p (%d)\n",
 
574
                                        mp->order,
 
575
                                        mp->addr, mp->num,
 
576
                                        addr2, num);
 
577
#endif
 
578
                                mp->addr=addr2;
 
579
                                mp->num=num;
 
580
                                lh_insert(mh,(char *)mp);
 
581
                                }
 
582
 
 
583
                        MemCheck_on(); /* release MALLOC2 lock
 
584
                                        * if num_disabled drops to 0 */
 
585
                        }
 
586
                break;
 
587
                }
 
588
        return;
 
589
        }
 
590
 
 
591
 
 
592
typedef struct mem_leak_st
 
593
        {
 
594
        BIO *bio;
 
595
        int chunks;
 
596
        long bytes;
 
597
        } MEM_LEAK;
 
598
 
 
599
static void print_leak(const MEM *m, MEM_LEAK *l)
 
600
        {
 
601
        char buf[1024];
 
602
        char *bufp = buf;
 
603
        APP_INFO *amip;
 
604
        int ami_cnt;
 
605
        struct tm *lcl = NULL;
 
606
        unsigned long ti;
 
607
 
 
608
#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
 
609
 
 
610
        if(m->addr == (char *)l->bio)
 
611
            return;
 
612
 
 
613
        if (options & V_CRYPTO_MDEBUG_TIME)
 
614
                {
 
615
                lcl = localtime(&m->time);
 
616
        
 
617
                BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
 
618
                        lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
 
619
                bufp += strlen(bufp);
 
620
                }
 
621
 
 
622
        BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
 
623
                m->order,m->file,m->line);
 
624
        bufp += strlen(bufp);
 
625
 
 
626
        if (options & V_CRYPTO_MDEBUG_THREAD)
 
627
                {
 
628
                BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
 
629
                bufp += strlen(bufp);
 
630
                }
 
631
 
 
632
        BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
 
633
                m->num,(unsigned long)m->addr);
 
634
        bufp += strlen(bufp);
 
635
 
 
636
        BIO_puts(l->bio,buf);
 
637
        
 
638
        l->chunks++;
 
639
        l->bytes+=m->num;
 
640
 
 
641
        amip=m->app_info;
 
642
        ami_cnt=0;
 
643
        if (!amip)
 
644
                return;
 
645
        ti=amip->thread;
 
646
        
 
647
        do
 
648
                {
 
649
                int buf_len;
 
650
                int info_len;
 
651
 
 
652
                ami_cnt++;
 
653
                memset(buf,'>',ami_cnt);
 
654
                BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
 
655
                        " thread=%lu, file=%s, line=%d, info=\"",
 
656
                        amip->thread, amip->file, amip->line);
 
657
                buf_len=strlen(buf);
 
658
                info_len=strlen(amip->info);
 
659
                if (128 - buf_len - 3 < info_len)
 
660
                        {
 
661
                        memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
 
662
                        buf_len = 128 - 3;
 
663
                        }
 
664
                else
 
665
                        {
 
666
                        BUF_strlcpy(buf + buf_len, amip->info,
 
667
                                    sizeof buf - buf_len);
 
668
                        buf_len = strlen(buf);
 
669
                        }
 
670
                BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
 
671
                
 
672
                BIO_puts(l->bio,buf);
 
673
 
 
674
                amip = amip->next;
 
675
                }
 
676
        while(amip && amip->thread == ti);
 
677
                
 
678
#ifdef LEVITTE_DEBUG_MEM
 
679
        if (amip)
 
680
                {
 
681
                fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
 
682
                abort();
 
683
                }
 
684
#endif
 
685
        }
 
686
 
 
687
static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
 
688
 
 
689
void CRYPTO_mem_leaks(BIO *b)
 
690
        {
 
691
        MEM_LEAK ml;
 
692
 
 
693
        if (mh == NULL && amih == NULL)
 
694
                return;
 
695
 
 
696
        MemCheck_off(); /* obtain MALLOC2 lock */
 
697
 
 
698
        ml.bio=b;
 
699
        ml.bytes=0;
 
700
        ml.chunks=0;
 
701
        if (mh != NULL)
 
702
                lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
 
703
                                (char *)&ml);
 
704
        if (ml.chunks != 0)
 
705
                {
 
706
                BIO_printf(b,"%ld bytes leaked in %d chunks\n",
 
707
                           ml.bytes,ml.chunks);
 
708
                }
 
709
        else
 
710
                {
 
711
                /* Make sure that, if we found no leaks, memory-leak debugging itself
 
712
                 * does not introduce memory leaks (which might irritate
 
713
                 * external debugging tools).
 
714
                 * (When someone enables leak checking, but does not call
 
715
                 * this function, we declare it to be their fault.)
 
716
                 *
 
717
                 * XXX    This should be in CRYPTO_mem_leaks_cb,
 
718
                 * and CRYPTO_mem_leaks should be implemented by
 
719
                 * using CRYPTO_mem_leaks_cb.
 
720
                 * (Also their should be a variant of lh_doall_arg
 
721
                 * that takes a function pointer instead of a void *;
 
722
                 * this would obviate the ugly and illegal
 
723
                 * void_fn_to_char kludge in CRYPTO_mem_leaks_cb.
 
724
                 * Otherwise the code police will come and get us.)
 
725
                 */
 
726
                int old_mh_mode;
 
727
 
 
728
                CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
 
729
 
 
730
                /* avoid deadlock when lh_free() uses CRYPTO_dbg_free(),
 
731
                 * which uses CRYPTO_is_mem_check_on */
 
732
                old_mh_mode = mh_mode;
 
733
                mh_mode = CRYPTO_MEM_CHECK_OFF;
 
734
 
 
735
                if (mh != NULL)
 
736
                        {
 
737
                        lh_free(mh);
 
738
                        mh = NULL;
 
739
                        }
 
740
                if (amih != NULL)
 
741
                        {
 
742
                        if (lh_num_items(amih) == 0) 
 
743
                                {
 
744
                                lh_free(amih);
 
745
                                amih = NULL;
 
746
                                }
 
747
                        }
 
748
 
 
749
                mh_mode = old_mh_mode;
 
750
                CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
 
751
                }
 
752
        MemCheck_on(); /* release MALLOC2 lock */
 
753
        }
 
754
 
 
755
#ifndef OPENSSL_NO_FP_API
 
756
void CRYPTO_mem_leaks_fp(FILE *fp)
 
757
        {
 
758
        BIO *b;
 
759
 
 
760
        if (mh == NULL) return;
 
761
        /* Need to turn off memory checking when allocated BIOs ... especially
 
762
         * as we're creating them at a time when we're trying to check we've not
 
763
         * left anything un-free()'d!! */
 
764
        MemCheck_off();
 
765
        b = BIO_new(BIO_s_file());
 
766
        MemCheck_on();
 
767
        if(!b) return;
 
768
        BIO_set_fp(b,fp,BIO_NOCLOSE);
 
769
        CRYPTO_mem_leaks(b);
 
770
        BIO_free(b);
 
771
        }
 
772
#endif
 
773
 
 
774
 
 
775
 
 
776
/* FIXME: We really don't allow much to the callback.  For example, it has
 
777
   no chance of reaching the info stack for the item it processes.  Should
 
778
   it really be this way?  -- Richard Levitte */
 
779
/* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
 
780
 * If this code is restructured, remove the callback type if it is no longer
 
781
 * needed. -- Geoff Thorpe */
 
782
static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
 
783
        {
 
784
        (**cb)(m->order,m->file,m->line,m->num,m->addr);
 
785
        }
 
786
 
 
787
static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
 
788
 
 
789
void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
 
790
        {
 
791
        if (mh == NULL) return;
 
792
        CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
 
793
        lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
 
794
        CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
 
795
        }
 
796
 
 
797
void CRYPTO_malloc_debug_init(void)
 
798
        {
 
799
        CRYPTO_set_mem_debug_functions(
 
800
                CRYPTO_dbg_malloc,
 
801
                CRYPTO_dbg_realloc,
 
802
                CRYPTO_dbg_free,
 
803
                CRYPTO_dbg_set_options,
 
804
                CRYPTO_dbg_get_options);
 
805
        CRYPTO_set_mem_info_functions(
 
806
                CRYPTO_dbg_push_info,
 
807
                CRYPTO_dbg_pop_info,
 
808
                CRYPTO_dbg_remove_all_info);
 
809
        }
 
810
 
 
811
char *CRYPTO_strdup(const char *str, const char *file, int line)
 
812
        {
 
813
        char *ret = CRYPTO_malloc(strlen(str)+1, file, line);
 
814
 
 
815
        strcpy(ret, str);
 
816
        return ret;
 
817
        }