malloc.cc revision d9e397b599b13d642138480a28c14db7a136bf0
1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (c) 2014, Google Inc.
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Permission to use, copy, modify, and/or distribute this software for any
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * purpose with or without fee is hereby granted, provided that the above
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copyright notice and this permission notice appear in all copies.
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/base.h>
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley// This file isn't built on ARM or Aarch64 because we link statically in those
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley// builds and trying to override malloc in a static link doesn't work.
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#if defined(__linux__) && !defined(OPENSSL_ARM) && !defined(OPENSSL_AARCH64)
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdint.h>
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdlib.h>
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <unistd.h>
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <unistd.h>
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <stdio.h>
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <new>
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* This file defines overrides for the standard allocation functions that allow
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * a given allocation to be made to fail for testing. If the program is run
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * return NULL. If MALLOC_ABORT_ON_FAIL is also defined then the allocation
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * will abort() rather than return NULL.
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This code is not thread safe. */
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint64_t current_malloc_count = 0;
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic uint64_t malloc_number_to_fail = 0;
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic char failure_enabled = 0, abort_on_fail = 0;
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int in_call = 0;
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern "C" {
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* These are other names for the standard allocation functions. */
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern void *__libc_malloc(size_t size);
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern void *__libc_calloc(size_t num_elems, size_t size);
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern void *__libc_realloc(void *ptr, size_t size);
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void exit_handler(void) {
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (failure_enabled && current_malloc_count > malloc_number_to_fail) {
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    _exit(88);
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic void cpp_new_handler() {
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  // Return to try again. It won't fail a second time.
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return;
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* should_fail_allocation returns true if the current allocation should fail. */
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int should_fail_allocation() {
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  static int init = 0;
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  char should_fail;
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (in_call) {
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  in_call = 1;
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!init) {
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (env != NULL && env[0] != 0) {
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      char *endptr;
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      malloc_number_to_fail = strtoull(env, &endptr, 10);
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      if (*endptr == 0) {
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        failure_enabled = 1;
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        atexit(exit_handler);
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley        std::set_new_handler(cpp_new_handler);
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      }
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    abort_on_fail = (NULL != getenv("MALLOC_ABORT_ON_FAIL"));
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    init = 1;
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  in_call = 0;
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (!failure_enabled) {
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return 0;
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  should_fail = (current_malloc_count == malloc_number_to_fail);
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  current_malloc_count++;
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (should_fail && abort_on_fail) {
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    abort();
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return should_fail;
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyextern "C" {
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *malloc(size_t size) {
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (should_fail_allocation()) {
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return __libc_malloc(size);
110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *calloc(size_t num_elems, size_t size) {
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (should_fail_allocation()) {
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return __libc_calloc(num_elems, size);
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyvoid *realloc(void *ptr, size_t size) {
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (should_fail_allocation()) {
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    return NULL;
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  return __libc_realloc(ptr, size);
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}  // extern "C"
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#endif  /* defined(linux) && !ARM && !AARCH64 */
131