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