alloc: add GIT_DEBUG_STRICT_ALLOC Add `GIT_DEBUG_STRICT_ALLOC` to help identify problematic callers of allocation code that pass a `0` size to the allocators and then expect a non-`NULL` return. When given a 0-size allocation, `malloc` _may_ return either a `NULL` _or_ a pointer that is not writeable. Most systems return a non-`NULL` pointer; AIX is an outlier. We should be able to cope with this AIXy behavior, so this adds an option to emulate it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6556979..58214fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,6 +49,7 @@ OPTION(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF)
OPTION(USE_STANDALONE_FUZZERS "Enable standalone fuzzers (compatible with gcc)" OFF)
OPTION(USE_LEAK_CHECKER "Run tests with leak checker" OFF)
OPTION(DEBUG_POOL "Enable debug pool allocator" OFF)
+OPTION(DEBUG_STRICT_ALLOC "Enable strict allocator behavior" OFF)
OPTION(ENABLE_WERROR "Enable compilation with -Werror" OFF)
OPTION(USE_BUNDLED_ZLIB "Use the bundled version of zlib. Can be set to one of Bundled(ON)/Chromium. The Chromium option requires a x86_64 processor with SSE4.2 and CLMUL" OFF)
SET(USE_HTTP_PARSER "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 4fde16d..8d15595 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -6,6 +6,11 @@ IF(DEBUG_POOL)
ENDIF()
ADD_FEATURE_INFO(debugpool GIT_DEBUG_POOL "debug pool allocator")
+IF(DEBUG_STRICT_ALLOC)
+ SET(GIT_DEBUG_STRICT_ALLOC 1)
+ENDIF()
+ADD_FEATURE_INFO(debugalloc GIT_DEBUG_STRICT_ALLOC "debug strict allocators")
+
INCLUDE(PkgBuildConfig)
INCLUDE(SanitizeBool)
diff --git a/src/allocators/stdalloc.c b/src/allocators/stdalloc.c
index c4938e3..7215468 100644
--- a/src/allocators/stdalloc.c
+++ b/src/allocators/stdalloc.c
@@ -9,34 +9,56 @@
static void *stdalloc__malloc(size_t len, const char *file, int line)
{
- void *ptr = malloc(len);
+ void *ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!ptr) git_error_set_oom();
+#ifdef GIT_DEBUG_STRICT_ALLOC
+ if (!len)
+ return NULL;
+#endif
+
+ ptr = malloc(len);
+
+ if (!ptr)
+ git_error_set_oom();
+
return ptr;
}
static void *stdalloc__calloc(size_t nelem, size_t elsize, const char *file, int line)
{
- void *ptr = calloc(nelem, elsize);
+ void *ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!ptr) git_error_set_oom();
+#ifdef GIT_DEBUG_STRICT_ALLOC
+ if (!elsize)
+ return NULL;
+#endif
+
+ ptr = calloc(nelem, elsize);
+
+ if (!ptr)
+ git_error_set_oom();
+
return ptr;
}
static char *stdalloc__strdup(const char *str, const char *file, int line)
{
- char *ptr = strdup(str);
+ char *ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!ptr) git_error_set_oom();
+ ptr = strdup(str);
+
+ if (!ptr)
+ git_error_set_oom();
+
return ptr;
}
@@ -48,7 +70,7 @@ static char *stdalloc__strndup(const char *str, size_t n, const char *file, int
length = p_strnlen(str, n);
if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
- !(ptr = stdalloc__malloc(alloclength, file, line)))
+ !(ptr = stdalloc__malloc(alloclength, file, line)))
return NULL;
if (length)
@@ -65,7 +87,7 @@ static char *stdalloc__substrdup(const char *start, size_t n, const char *file,
size_t alloclen;
if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
- !(ptr = stdalloc__malloc(alloclen, file, line)))
+ !(ptr = stdalloc__malloc(alloclen, file, line)))
return NULL;
memcpy(ptr, start, n);
@@ -75,12 +97,21 @@ static char *stdalloc__substrdup(const char *start, size_t n, const char *file,
static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int line)
{
- void *new_ptr = realloc(ptr, size);
+ void *new_ptr;
GIT_UNUSED(file);
GIT_UNUSED(line);
- if (!new_ptr) git_error_set_oom();
+#ifdef GIT_DEBUG_STRICT_ALLOC
+ if (!size)
+ return NULL;
+#endif
+
+ new_ptr = realloc(ptr, size);
+
+ if (!new_ptr)
+ git_error_set_oom();
+
return new_ptr;
}
diff --git a/src/features.h.in b/src/features.h.in
index c8d0180..ab523f9 100644
--- a/src/features.h.in
+++ b/src/features.h.in
@@ -2,6 +2,8 @@
#define INCLUDE_features_h__
#cmakedefine GIT_DEBUG_POOL 1
+#cmakedefine GIT_DEBUG_STRICT_ALLOC 1
+
#cmakedefine GIT_TRACE 1
#cmakedefine GIT_THREADS 1
#cmakedefine GIT_WIN32_LEAKCHECK 1