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