To secure Win64 API I'm throwing in this minimalistic Win64 support.
[openssl.git] / crypto / mem_dbg.c
index 5086bcde15c4457c1a525d58bf48ed9138087911..8316485217ac48847f59ce5ce8a51ba86df2ff97 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>      
+#include "cryptlib.h"
 #include <openssl/crypto.h>
 #include <openssl/buffer.h>
 #include <openssl/bio.h>
 #include <openssl/lhash.h>
-#include "cryptlib.h"
 
 static int mh_mode=CRYPTO_MEM_CHECK_OFF;
 /* The state changes to CRYPTO_MEM_CHECK_ON | CRYPTO_MEM_CHECK_ENABLE
@@ -102,6 +102,8 @@ typedef struct app_mem_info_st
        int references;
        } APP_INFO;
 
+static void app_info_free(APP_INFO *);
+
 static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
                           * that are at the top of their thread's stack
                           * (with `thread' as key);
@@ -140,6 +142,18 @@ static unsigned long disabling_thread = 0; /* Valid iff num_disable > 0.
                                             * thread named in disabling_thread).
                                             */
 
+static void app_info_free(APP_INFO *inf)
+       {
+       if (--(inf->references) <= 0)
+               {
+               if (inf->next != NULL)
+                       {
+                       app_info_free(inf->next);
+                       }
+               OPENSSL_free(inf);
+               }
+       }
+
 int CRYPTO_mem_ctrl(int mode)
        {
        int ret=mh_mode;
@@ -238,8 +252,16 @@ long CRYPTO_dbg_get_options(void)
 /* static int mem_cmp(MEM *a, MEM *b) */
 static int mem_cmp(const void *a_void, const void *b_void)
        {
-       return((const char *)((MEM *)a_void)->addr
-               - (const char *)((MEM *)b_void)->addr);
+#ifdef _WIN64
+       const char *a=(const char *)((const MEM *)a_void)->addr,
+                  *b=(const char *)((const MEM *)b_void)->addr;
+       if (a==b)       return 0;
+       else if (a>b)   return 1;
+       else            return -1;
+#else
+       return((const char *)((const MEM *)a_void)->addr
+               - (const char *)((const MEM *)b_void)->addr);
+#endif
        }
 
 /* static unsigned long mem_hash(MEM *a) */
@@ -502,9 +524,7 @@ void CRYPTO_dbg_free(void *addr, int before_p)
                                mp->order, mp->addr, mp->num);
 #endif
                                if (mp->app_info != NULL)
-                                       {
-                                       mp->app_info->references--;
-                                       }
+                                       app_info_free(mp->app_info);
                                OPENSSL_free(mp);
                                }
 
@@ -576,7 +596,7 @@ typedef struct mem_leak_st
        long bytes;
        } MEM_LEAK;
 
-static void print_leak(MEM *m, MEM_LEAK *l)
+static void print_leak(const MEM *m, MEM_LEAK *l)
        {
        char buf[1024];
        char *bufp = buf;
@@ -585,6 +605,8 @@ static void print_leak(MEM *m, MEM_LEAK *l)
        struct tm *lcl = NULL;
        unsigned long ti;
 
+#define BUF_REMAIN (sizeof buf - (size_t)(bufp - buf))
+
        if(m->addr == (char *)l->bio)
            return;
 
@@ -592,22 +614,22 @@ static void print_leak(MEM *m, MEM_LEAK *l)
                {
                lcl = localtime(&m->time);
        
-               sprintf(bufp, "[%02d:%02d:%02d] ",
+               BIO_snprintf(bufp, BUF_REMAIN, "[%02d:%02d:%02d] ",
                        lcl->tm_hour,lcl->tm_min,lcl->tm_sec);
                bufp += strlen(bufp);
                }
 
-       sprintf(bufp, "%5lu file=%s, line=%d, ",
+       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)
                {
-               sprintf(bufp, "thread=%lu, ", m->thread);
+               BIO_snprintf(bufp, BUF_REMAIN, "thread=%lu, ", m->thread);
                bufp += strlen(bufp);
                }
 
-       sprintf(bufp, "number=%d, address=%08lX\n",
+       BIO_snprintf(bufp, BUF_REMAIN, "number=%d, address=%08lX\n",
                m->num,(unsigned long)m->addr);
        bufp += strlen(bufp);
 
@@ -629,7 +651,7 @@ static void print_leak(MEM *m, MEM_LEAK *l)
 
                ami_cnt++;
                memset(buf,'>',ami_cnt);
-               sprintf(buf + ami_cnt,
+               BIO_snprintf(buf + ami_cnt, sizeof buf - ami_cnt,
                        " thread=%lu, file=%s, line=%d, info=\"",
                        amip->thread, amip->file, amip->line);
                buf_len=strlen(buf);
@@ -641,10 +663,11 @@ static void print_leak(MEM *m, MEM_LEAK *l)
                        }
                else
                        {
-                       strcpy(buf + buf_len, amip->info);
+                       BUF_strlcpy(buf + buf_len, amip->info,
+                                   sizeof buf - buf_len);
                        buf_len = strlen(buf);
                        }
-               sprintf(buf + buf_len, "\"\n");
+               BIO_snprintf(buf + buf_len, sizeof buf - buf_len, "\"\n");
                
                BIO_puts(l->bio,buf);
 
@@ -661,12 +684,11 @@ static void print_leak(MEM *m, MEM_LEAK *l)
 #endif
        }
 
-static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, MEM *, MEM_LEAK *)
+static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
 
 void CRYPTO_mem_leaks(BIO *b)
        {
        MEM_LEAK ml;
-       char buf[80];
 
        if (mh == NULL && amih == NULL)
                return;
@@ -681,9 +703,8 @@ void CRYPTO_mem_leaks(BIO *b)
                                (char *)&ml);
        if (ml.chunks != 0)
                {
-               sprintf(buf,"%ld bytes leaked in %d chunks\n",
-                       ml.bytes,ml.chunks);
-               BIO_puts(b,buf);
+               BIO_printf(b,"%ld bytes leaked in %d chunks\n",
+                          ml.bytes,ml.chunks);
                }
        else
                {
@@ -737,8 +758,13 @@ void CRYPTO_mem_leaks_fp(FILE *fp)
        BIO *b;
 
        if (mh == NULL) return;
-       if ((b=BIO_new(BIO_s_file())) == NULL)
-               return;
+       /* Need to turn off memory checking when allocated BIOs ... especially
+        * as we're creating them at a time when we're trying to check we've not
+        * left anything un-free()'d!! */
+       MemCheck_off();
+       b = BIO_new(BIO_s_file());
+       MemCheck_on();
+       if(!b) return;
        BIO_set_fp(b,fp,BIO_NOCLOSE);
        CRYPTO_mem_leaks(b);
        BIO_free(b);
@@ -753,12 +779,12 @@ void CRYPTO_mem_leaks_fp(FILE *fp)
 /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
  * If this code is restructured, remove the callback type if it is no longer
  * needed. -- Geoff Thorpe */
-static void cb_leak(MEM *m, CRYPTO_MEM_LEAK_CB **cb)
+static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
        {
        (**cb)(m->order,m->file,m->line,m->num,m->addr);
        }
 
-static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, MEM *, CRYPTO_MEM_LEAK_CB **)
+static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
 
 void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
        {