+ (void)lh_MEM_insert(mh, mp);
+ }
+
+ MemCheck_on(); /* release MALLOC2 lock if num_disabled drops
+ * to 0 */
+ }
+ break;
+ }
+ return;
+}
+
+typedef struct mem_leak_st {
+ BIO *bio;
+ int chunks;
+ int seen;
+ long bytes;
+} MEM_LEAK;
+
+static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
+{
+ char buf[1024];
+ char *bufp = buf;
+ APP_INFO *amip;
+ int ami_cnt;
+ struct tm *lcl = NULL;
+ CRYPTO_THREADID ti;
+
+#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
+
+ /* Is one "leak" the BIO we were given? */
+ if (m->addr == (char *)l->bio) {
+ l->seen = 1;
+ return;
+ }
+
+ if (options & V_CRYPTO_MDEBUG_TIME) {
+ lcl = localtime(&m->time);
+
+ BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
+ lcl->tm_hour, lcl->tm_min, lcl->tm_sec);
+ bufp += strlen(bufp);
+ }
+
+ BIO_snprintf(bufp, BUF_REMAIN, "%5lu file=%s, line=%d, ",
+ m->order, m->file, m->line);
+ bufp += strlen(bufp);
+
+ if (options & V_CRYPTO_MDEBUG_THREAD) {
+ BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ",
+ CRYPTO_THREADID_hash(&m->threadid));
+ bufp += strlen(bufp);
+ }
+
+ BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%p\n",
+ m->num, m->addr);
+ bufp += strlen(bufp);
+
+ BIO_puts(l->bio, buf);
+
+ l->chunks++;
+ l->bytes += m->num;
+
+ amip = m->app_info;
+ ami_cnt = 0;
+ if (amip) {
+ CRYPTO_THREADID_cpy(&ti, &amip->threadid);
+
+ do {
+ int buf_len;
+ int info_len;
+
+ ami_cnt++;
+ memset(buf, '>', ami_cnt);
+ BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
+ " thread=%lu, file=%s, line=%d, info=\"",
+ CRYPTO_THREADID_hash(&amip->threadid), amip->file,
+ amip->line);
+ buf_len = strlen(buf);
+ info_len = strlen(amip->info);
+ if (128 - buf_len - 3 < info_len) {
+ memcpy(buf + buf_len, amip->info, 128 - buf_len - 3);
+ buf_len = 128 - 3;
+ } else {
+ BUF_strlcpy(buf + buf_len, amip->info, sizeof buf - buf_len);
+ buf_len = strlen(buf);
+ }
+ BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
+
+ BIO_puts(l->bio, buf);
+
+ amip = amip->next;
+ }
+ while (amip && !CRYPTO_THREADID_cmp(&amip->threadid, &ti));
+ }
+
+#ifdef LEVITTE_DEBUG_MEM
+ if (amip) {
+ fprintf(stderr, "Thread switch detected in backtrace!!!!\n");
+ abort();
+ }
+#endif
+#if defined(CRYPTO_MDEBUG_BACKTRACE) && defined(__GNUC__)
+ {
+ size_t i;
+ char **strings = backtrace_symbols(m->array, m->array_siz);
+ for (i = 0; i < m->array_siz; i++)
+ fprintf(stderr, "##> %s\n", strings[i]);
+
+ free(strings);
+ }
+#endif
+}
+
+static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)