mem_dbg.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:20k
源码类别:

其他游戏

开发平台:

Visual C++

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