s390x assembly pack: update perlasm module
[openssl.git] / crypto / mem.c
index 947c50ed21dcbb4c5da9c280cb6da0bc23762d05..562d6b51e2b34511111517036da876ca2545c5b9 100644 (file)
@@ -1,19 +1,20 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
 
+#include "e_os.h"
+#include "internal/cryptlib.h"
+#include "internal/cryptlib_int.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <limits.h>
 #include <openssl/crypto.h>
-#include "internal/cryptlib.h"
-#include "internal/cryptlib_int.h"
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE) && !defined(FIPS_MODE)
 # include <execinfo.h>
 #endif
 
@@ -29,7 +30,15 @@ static void *(*realloc_impl)(void *, size_t, const char *, int)
 static void (*free_impl)(void *, const char *, int)
     = CRYPTO_free;
 
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODE)
+# include "internal/tsan_assist.h"
+
+static TSAN_QUALIFIER int malloc_count;
+static TSAN_QUALIFIER int realloc_count;
+static TSAN_QUALIFIER int free_count;
+
+# define INCREMENT(x) tsan_counter(&(x))
+
 static char *md_failstring;
 static long md_count;
 static int md_fail_percent = 0;
@@ -44,6 +53,7 @@ static int shouldfail(void);
 #else
 static int call_malloc_debug = 0;
 
+# define INCREMENT(x) /* empty */
 # define FAILTEST() /* empty */
 #endif
 
@@ -84,7 +94,17 @@ void CRYPTO_get_mem_functions(
         *f = free_impl;
 }
 
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODE)
+void CRYPTO_get_alloc_counts(int *mcount, int *rcount, int *fcount)
+{
+    if (mcount != NULL)
+        *mcount = tsan_load(&malloc_count);
+    if (rcount != NULL)
+        *rcount = tsan_load(&realloc_count);
+    if (fcount != NULL)
+        *fcount = tsan_load(&free_count);
+}
+
 /*
  * Parse a "malloc failure spec" string.  This likes like a set of fields
  * separated by semicolons.  Each field has a count and an optional failure
@@ -116,9 +136,9 @@ static void parseit(void)
  * Some rand() implementations aren't good, but we're not
  * dealing with secure randomness here.
  */
-#ifdef _WIN32
-# define random() rand()
-#endif
+# ifdef _WIN32
+#  define random() rand()
+# endif
 /*
  * See if the current malloc should fail.
  */
@@ -126,6 +146,8 @@ static int shouldfail(void)
 {
     int roll = (int)(random() % 100);
     int shoulditfail = roll < md_fail_percent;
+# ifndef _WIN32
+/* suppressed on Windows as POSIX-like file descriptors are non-inheritable */
     int len;
     char buff[80];
 
@@ -136,15 +158,16 @@ static int shouldfail(void)
         len = strlen(buff);
         if (write(md_tracefd, buff, len) != len)
             perror("shouldfail write failed");
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
+#  ifndef OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
         if (shoulditfail) {
             void *addrs[30];
             int num = backtrace(addrs, OSSL_NELEM(addrs));
 
             backtrace_symbols_fd(addrs, num, md_tracefd);
         }
-#endif
+#  endif
     }
+# endif
 
     if (md_count) {
         /* If we used up this one, go to the next. */
@@ -170,6 +193,7 @@ void *CRYPTO_malloc(size_t num, const char *file, int line)
 {
     void *ret = NULL;
 
+    INCREMENT(malloc_count);
     if (malloc_impl != NULL && malloc_impl != CRYPTO_malloc)
         return malloc_impl(num, file, line);
 
@@ -177,8 +201,15 @@ void *CRYPTO_malloc(size_t num, const char *file, int line)
         return NULL;
 
     FAILTEST();
-    allow_customize = 0;
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+    if (allow_customize) {
+        /*
+         * Disallow customization after the first allocation. We only set this
+         * if necessary to avoid a store to the same cache line on every
+         * allocation.
+         */
+        allow_customize = 0;
+    }
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODE)
     if (call_malloc_debug) {
         CRYPTO_mem_debug_malloc(NULL, num, 0, file, line);
         ret = malloc(num);
@@ -206,6 +237,7 @@ void *CRYPTO_zalloc(size_t num, const char *file, int line)
 
 void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
 {
+    INCREMENT(realloc_count);
     if (realloc_impl != NULL && realloc_impl != &CRYPTO_realloc)
         return realloc_impl(str, num, file, line);
 
@@ -218,8 +250,7 @@ void *CRYPTO_realloc(void *str, size_t num, const char *file, int line)
         return NULL;
     }
 
-    allow_customize = 0;
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODE)
     if (call_malloc_debug) {
         void *ret;
         CRYPTO_mem_debug_realloc(str, NULL, num, 0, file, line);
@@ -263,12 +294,13 @@ void *CRYPTO_clear_realloc(void *str, size_t old_len, size_t num,
 
 void CRYPTO_free(void *str, const char *file, int line)
 {
+    INCREMENT(free_count);
     if (free_impl != NULL && free_impl != &CRYPTO_free) {
         free_impl(str, file, line);
         return;
     }
 
-#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+#if !defined(OPENSSL_NO_CRYPTO_MDEBUG) && !defined(FIPS_MODE)
     if (call_malloc_debug) {
         CRYPTO_mem_debug_free(str, 0, file, line);
         free(str);