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  * 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  */
 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 
 138 DECLARE_LHASH_OF(MEM);
 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;
 159         } APP_INFO;
 160 
 161 static void app_info_free(APP_INFO *);
 162 
 163 DECLARE_LHASH_OF(APP_INFO);
 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)
 186         V_CRYPTO_MDEBUG_TIME |
 187 #endif
 188 #if defined(CRYPTO_MDEBUG_THREAD) || defined(CRYPTO_MDEBUG_ALL)
 189         V_CRYPTO_MDEBUG_THREAD |
 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 
 220         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
 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() */
 226                 mh_mode = CRYPTO_MEM_CHECK_ON|CRYPTO_MEM_CHECK_ENABLE;
 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;
 240                         CRYPTO_THREADID_current(&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                                  */
 250                                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
 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. */
 256                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
 257                                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
 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;
 273                                         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
 274                                         }
 275                                 }
 276                         }
 277                 break;
 278 
 279         default:
 280                 break;
 281                 }
 282         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
 283         return(ret);
 284         }
 285 
 286 int CRYPTO_is_mem_check_on(void)
 287         {
 288         int ret = 0;
 289 
 290         if (mh_mode & CRYPTO_MEM_CHECK_ON)
 291                 {
 292                 CRYPTO_THREADID cur;
 293                 CRYPTO_THREADID_current(&cur);
 294                 CRYPTO_r_lock(CRYPTO_LOCK_MALLOC);
 295 
 296                 ret = (mh_mode & CRYPTO_MEM_CHECK_ENABLE)
 297                         || CRYPTO_THREADID_cmp(&disabling_threadid, &cur);
 298 
 299                 CRYPTO_r_unlock(CRYPTO_LOCK_MALLOC);
 300                 }
 301         return(ret);
 302         }
 303 
 304 
 305 void CRYPTO_dbg_set_options(long bits)
 306         {
 307         options = bits;
 308         }
 309 
 310 long CRYPTO_dbg_get_options(void)
 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 
 448 int CRYPTO_pop_info(void)
 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 
 463 int CRYPTO_remove_all_info(void)
 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         {
 659         BIO *bio;
 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)
 769                 lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK,
 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 
 798                 CRYPTO_w_lock(CRYPTO_LOCK_MALLOC);
 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;
 820                 CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC);
 821                 }
 822         MemCheck_on(); /* release MALLOC2 lock */
 823         }
 824 
 825 #ifndef OPENSSL_NO_FP_API
 826 void CRYPTO_mem_leaks_fp(FILE *fp)
 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 
 858 typedef CRYPTO_MEM_LEAK_CB *PCRYPTO_MEM_LEAK_CB;
 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 
 867 void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
 868         {
 869         if (mh == NULL) return;
 870         CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
 871         lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), PCRYPTO_MEM_LEAK_CB,
 872                          &cb);
 873         CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
 874         }