summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2023-05-14 14:07:59 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2023-05-14 14:52:15 +0100
commit9dd1bfe81c3aba6ce35ed85bf62fa75d9c61e1a6 (patch)
tree020f4f5a701b8f577c2127954b1de4b164fe15b6
parent9d41a3fd694d983ade53fb602a58f6df25ce0656 (diff)
downloadlibgit2-9dd1bfe81c3aba6ce35ed85bf62fa75d9c61e1a6.tar.gz
alloc: simplify pluggable allocators
Remove the number of functions that custom allocator users need to provide; nobody should need to implement `substrdup`. Keep it to the basics that are actually _needed_ for allocation (malloc, realloc, free) and reimplement the rest ourselves. In addition, move the failure check and error setting _out_ of the custom allocators and into a wrapper so that users don't need to deal with this. This also allows us to call our allocator (without the wrapper) early so that it does not try to set an error on failure, which may be important for bootstrapping.
-rw-r--r--include/git2/sys/alloc.h34
-rw-r--r--src/util/alloc.c71
-rw-r--r--src/util/alloc.h43
-rw-r--r--src/util/allocators/failalloc.c60
-rw-r--r--src/util/allocators/failalloc.h6
-rw-r--r--src/util/allocators/stdalloc.c107
-rw-r--r--src/util/allocators/win32_leakcheck.c68
7 files changed, 101 insertions, 288 deletions
diff --git a/include/git2/sys/alloc.h b/include/git2/sys/alloc.h
index c295807bc..e7f85b890 100644
--- a/include/git2/sys/alloc.h
+++ b/include/git2/sys/alloc.h
@@ -25,28 +25,6 @@ typedef struct {
void * GIT_CALLBACK(gmalloc)(size_t n, const char *file, int line);
/**
- * Allocate memory for an array of `nelem` elements, where each element
- * has a size of `elsize`. Returned memory shall be initialized to
- * all-zeroes
- */
- void * GIT_CALLBACK(gcalloc)(size_t nelem, size_t elsize, const char *file, int line);
-
- /** Allocate memory for the string `str` and duplicate its contents. */
- char * GIT_CALLBACK(gstrdup)(const char *str, const char *file, int line);
-
- /**
- * Equivalent to the `gstrdup` function, but only duplicating at most
- * `n + 1` bytes
- */
- char * GIT_CALLBACK(gstrndup)(const char *str, size_t n, const char *file, int line);
-
- /**
- * Equivalent to `gstrndup`, but will always duplicate exactly `n` bytes
- * of `str`. Thus, out of bounds reads at `str` may happen.
- */
- char * GIT_CALLBACK(gsubstrdup)(const char *str, size_t n, const char *file, int line);
-
- /**
* This function shall deallocate the old object `ptr` and return a
* pointer to a new object that has the size specified by `size`. In
* case `ptr` is `NULL`, a new array shall be allocated.
@@ -54,18 +32,6 @@ typedef struct {
void * GIT_CALLBACK(grealloc)(void *ptr, size_t size, const char *file, int line);
/**
- * This function shall be equivalent to `grealloc`, but allocating
- * `neleme * elsize` bytes.
- */
- void * GIT_CALLBACK(greallocarray)(void *ptr, size_t nelem, size_t elsize, const char *file, int line);
-
- /**
- * This function shall allocate a new array of `nelem` elements, where
- * each element has a size of `elsize` bytes.
- */
- void * GIT_CALLBACK(gmallocarray)(size_t nelem, size_t elsize, const char *file, int line);
-
- /**
* This function shall free the memory pointed to by `ptr`. In case
* `ptr` is `NULL`, this shall be a no-op.
*/
diff --git a/src/util/alloc.c b/src/util/alloc.c
index 2820d84a2..6ec173d04 100644
--- a/src/util/alloc.c
+++ b/src/util/alloc.c
@@ -15,16 +15,75 @@
/* Fail any allocation until git_libgit2_init is called. */
git_allocator git__allocator = {
git_failalloc_malloc,
- git_failalloc_calloc,
- git_failalloc_strdup,
- git_failalloc_strndup,
- git_failalloc_substrdup,
git_failalloc_realloc,
- git_failalloc_reallocarray,
- git_failalloc_mallocarray,
git_failalloc_free
};
+void *git__calloc(size_t nelem, size_t elsize)
+{
+ size_t newsize;
+ void *ptr;
+
+ if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
+ return NULL;
+
+ if ((ptr = git__malloc(newsize)))
+ memset(ptr, 0, newsize);
+
+ return ptr;
+}
+
+void *git__reallocarray(void *ptr, size_t nelem, size_t elsize)
+{
+ size_t newsize;
+
+ if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
+ return NULL;
+
+ return git__realloc(ptr, newsize);
+}
+
+void *git__mallocarray(size_t nelem, size_t elsize)
+{
+ return git__reallocarray(NULL, nelem, elsize);
+}
+
+char *git__strdup(const char *str)
+{
+ size_t len = strlen(str) + 1;
+ void *ptr = git__malloc(len);
+
+ if (ptr)
+ memcpy(ptr, str, len);
+
+ return ptr;
+}
+
+char *git__strndup(const char *str, size_t n)
+{
+ size_t len = p_strnlen(str, n);
+ char *ptr = git__malloc(len + 1);
+
+ if (ptr) {
+ memcpy(ptr, str, len);
+ ptr[len] = '\0';
+ }
+
+ return ptr;
+}
+
+char *git__substrdup(const char *str, size_t n)
+{
+ char *ptr = git__malloc(n + 1);
+
+ if (ptr) {
+ memcpy(ptr, str, n);
+ ptr[n] = '\0';
+ }
+
+ return ptr;
+}
+
static int setup_default_allocator(void)
{
#if defined(GIT_WIN32_LEAKCHECK)
diff --git a/src/util/alloc.h b/src/util/alloc.h
index 04fb7e101..32b614b25 100644
--- a/src/util/alloc.h
+++ b/src/util/alloc.h
@@ -10,17 +10,42 @@
#include "git2/sys/alloc.h"
+#include "git2_util.h"
+
extern git_allocator git__allocator;
-#define git__malloc(len) git__allocator.gmalloc(len, __FILE__, __LINE__)
-#define git__calloc(nelem, elsize) git__allocator.gcalloc(nelem, elsize, __FILE__, __LINE__)
-#define git__strdup(str) git__allocator.gstrdup(str, __FILE__, __LINE__)
-#define git__strndup(str, n) git__allocator.gstrndup(str, n, __FILE__, __LINE__)
-#define git__substrdup(str, n) git__allocator.gsubstrdup(str, n, __FILE__, __LINE__)
-#define git__realloc(ptr, size) git__allocator.grealloc(ptr, size, __FILE__, __LINE__)
-#define git__reallocarray(ptr, nelem, elsize) git__allocator.greallocarray(ptr, nelem, elsize, __FILE__, __LINE__)
-#define git__mallocarray(nelem, elsize) git__allocator.gmallocarray(nelem, elsize, __FILE__, __LINE__)
-#define git__free git__allocator.gfree
+GIT_INLINE(void *) git__malloc(size_t len)
+{
+ void *p = git__allocator.gmalloc(len, __FILE__, __LINE__);
+
+ if (!p)
+ git_error_set_oom();
+
+ return p;
+}
+
+GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
+{
+ void *p = git__allocator.grealloc(ptr, size, __FILE__, __LINE__);
+
+ if (!p)
+ git_error_set_oom();
+
+ return p;
+}
+
+GIT_INLINE(void) git__free(void *ptr)
+{
+ git__allocator.gfree(ptr);
+}
+
+extern void *git__calloc(size_t nelem, size_t elsize);
+extern void *git__mallocarray(size_t nelem, size_t elsize);
+extern void *git__reallocarray(void *ptr, size_t nelem, size_t elsize);
+
+extern char *git__strdup(const char *str);
+extern char *git__strndup(const char *str, size_t n);
+extern char *git__substrdup(const char *str, size_t n);
/**
* This function is being called by our global setup routines to
diff --git a/src/util/allocators/failalloc.c b/src/util/allocators/failalloc.c
index 5257d1dec..c1025e32f 100644
--- a/src/util/allocators/failalloc.c
+++ b/src/util/allocators/failalloc.c
@@ -16,45 +16,6 @@ void *git_failalloc_malloc(size_t len, const char *file, int line)
return NULL;
}
-void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line)
-{
- GIT_UNUSED(nelem);
- GIT_UNUSED(elsize);
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- return NULL;
-}
-
-char *git_failalloc_strdup(const char *str, const char *file, int line)
-{
- GIT_UNUSED(str);
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- return NULL;
-}
-
-char *git_failalloc_strndup(const char *str, size_t n, const char *file, int line)
-{
- GIT_UNUSED(str);
- GIT_UNUSED(n);
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- return NULL;
-}
-
-char *git_failalloc_substrdup(const char *start, size_t n, const char *file, int line)
-{
- GIT_UNUSED(start);
- GIT_UNUSED(n);
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- return NULL;
-}
-
void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line)
{
GIT_UNUSED(ptr);
@@ -65,27 +26,6 @@ void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line)
return NULL;
}
-void *git_failalloc_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
-{
- GIT_UNUSED(ptr);
- GIT_UNUSED(nelem);
- GIT_UNUSED(elsize);
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- return NULL;
-}
-
-void *git_failalloc_mallocarray(size_t nelem, size_t elsize, const char *file, int line)
-{
- GIT_UNUSED(nelem);
- GIT_UNUSED(elsize);
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- return NULL;
-}
-
void git_failalloc_free(void *ptr)
{
GIT_UNUSED(ptr);
diff --git a/src/util/allocators/failalloc.h b/src/util/allocators/failalloc.h
index 91264a0bb..a3788e634 100644
--- a/src/util/allocators/failalloc.h
+++ b/src/util/allocators/failalloc.h
@@ -11,13 +11,7 @@
#include "git2_util.h"
extern void *git_failalloc_malloc(size_t len, const char *file, int line);
-extern void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line);
-extern char *git_failalloc_strdup(const char *str, const char *file, int line);
-extern char *git_failalloc_strndup(const char *str, size_t n, const char *file, int line);
-extern char *git_failalloc_substrdup(const char *start, size_t n, const char *file, int line);
extern void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line);
-extern void *git_failalloc_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line);
-extern void *git_failalloc_mallocarray(size_t nelem, size_t elsize, const char *file, int line);
extern void git_failalloc_free(void *ptr);
#endif
diff --git a/src/util/allocators/stdalloc.c b/src/util/allocators/stdalloc.c
index 2b36d9f3d..f2d72a7e6 100644
--- a/src/util/allocators/stdalloc.c
+++ b/src/util/allocators/stdalloc.c
@@ -9,8 +9,6 @@
static void *stdalloc__malloc(size_t len, const char *file, int line)
{
- void *ptr;
-
GIT_UNUSED(file);
GIT_UNUSED(line);
@@ -19,86 +17,11 @@ static void *stdalloc__malloc(size_t len, const char *file, int line)
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;
-
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
-#ifdef GIT_DEBUG_STRICT_ALLOC
- if (!elsize || !nelem)
- 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;
-
- GIT_UNUSED(file);
- GIT_UNUSED(line);
-
- ptr = strdup(str);
-
- if (!ptr)
- git_error_set_oom();
-
- return ptr;
-}
-
-static char *stdalloc__strndup(const char *str, size_t n, const char *file, int line)
-{
- size_t length = 0, alloclength;
- char *ptr;
-
- length = p_strnlen(str, n);
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
- !(ptr = stdalloc__malloc(alloclength, file, line)))
- return NULL;
-
- if (length)
- memcpy(ptr, str, length);
-
- ptr[length] = '\0';
-
- return ptr;
-}
-
-static char *stdalloc__substrdup(const char *start, size_t n, const char *file, int line)
-{
- char *ptr;
- size_t alloclen;
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
- !(ptr = stdalloc__malloc(alloclen, file, line)))
- return NULL;
-
- memcpy(ptr, start, n);
- ptr[n] = '\0';
- return ptr;
+ return malloc(len);
}
static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int line)
{
- void *new_ptr;
-
GIT_UNUSED(file);
GIT_UNUSED(line);
@@ -107,27 +30,7 @@ static void *stdalloc__realloc(void *ptr, size_t size, const char *file, int lin
return NULL;
#endif
- new_ptr = realloc(ptr, size);
-
- if (!new_ptr)
- git_error_set_oom();
-
- return new_ptr;
-}
-
-static void *stdalloc__reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
-{
- size_t newsize;
-
- if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
- return NULL;
-
- return stdalloc__realloc(ptr, newsize, file, line);
-}
-
-static void *stdalloc__mallocarray(size_t nelem, size_t elsize, const char *file, int line)
-{
- return stdalloc__reallocarray(NULL, nelem, elsize, file, line);
+ return realloc(ptr, size);
}
static void stdalloc__free(void *ptr)
@@ -138,13 +41,7 @@ static void stdalloc__free(void *ptr)
int git_stdalloc_init_allocator(git_allocator *allocator)
{
allocator->gmalloc = stdalloc__malloc;
- allocator->gcalloc = stdalloc__calloc;
- allocator->gstrdup = stdalloc__strdup;
- allocator->gstrndup = stdalloc__strndup;
- allocator->gsubstrdup = stdalloc__substrdup;
allocator->grealloc = stdalloc__realloc;
- allocator->greallocarray = stdalloc__reallocarray;
- allocator->gmallocarray = stdalloc__mallocarray;
allocator->gfree = stdalloc__free;
return 0;
}
diff --git a/src/util/allocators/win32_leakcheck.c b/src/util/allocators/win32_leakcheck.c
index fe06a14af..cdf16d348 100644
--- a/src/util/allocators/win32_leakcheck.c
+++ b/src/util/allocators/win32_leakcheck.c
@@ -18,53 +18,6 @@ static void *leakcheck_malloc(size_t len, const char *file, int line)
return ptr;
}
-static void *leakcheck_calloc(size_t nelem, size_t elsize, const char *file, int line)
-{
- void *ptr = _calloc_dbg(nelem, elsize, _NORMAL_BLOCK, git_win32_leakcheck_stacktrace(1,file), line);
- if (!ptr) git_error_set_oom();
- return ptr;
-}
-
-static char *leakcheck_strdup(const char *str, const char *file, int line)
-{
- char *ptr = _strdup_dbg(str, _NORMAL_BLOCK, git_win32_leakcheck_stacktrace(1,file), line);
- if (!ptr) git_error_set_oom();
- return ptr;
-}
-
-static char *leakcheck_strndup(const char *str, size_t n, const char *file, int line)
-{
- size_t length = 0, alloclength;
- char *ptr;
-
- length = p_strnlen(str, n);
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclength, length, 1) ||
- !(ptr = leakcheck_malloc(alloclength, file, line)))
- return NULL;
-
- if (length)
- memcpy(ptr, str, length);
-
- ptr[length] = '\0';
-
- return ptr;
-}
-
-static char *leakcheck_substrdup(const char *start, size_t n, const char *file, int line)
-{
- char *ptr;
- size_t alloclen;
-
- if (GIT_ADD_SIZET_OVERFLOW(&alloclen, n, 1) ||
- !(ptr = leakcheck_malloc(alloclen, file, line)))
- return NULL;
-
- memcpy(ptr, start, n);
- ptr[n] = '\0';
- return ptr;
-}
-
static void *leakcheck_realloc(void *ptr, size_t size, const char *file, int line)
{
void *new_ptr = _realloc_dbg(ptr, size, _NORMAL_BLOCK, git_win32_leakcheck_stacktrace(1,file), line);
@@ -72,21 +25,6 @@ static void *leakcheck_realloc(void *ptr, size_t size, const char *file, int lin
return new_ptr;
}
-static void *leakcheck_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
-{
- size_t newsize;
-
- if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
- return NULL;
-
- return leakcheck_realloc(ptr, newsize, file, line);
-}
-
-static void *leakcheck_mallocarray(size_t nelem, size_t elsize, const char *file, int line)
-{
- return leakcheck_reallocarray(NULL, nelem, elsize, file, line);
-}
-
static void leakcheck_free(void *ptr)
{
free(ptr);
@@ -95,13 +33,7 @@ static void leakcheck_free(void *ptr)
int git_win32_leakcheck_init_allocator(git_allocator *allocator)
{
allocator->gmalloc = leakcheck_malloc;
- allocator->gcalloc = leakcheck_calloc;
- allocator->gstrdup = leakcheck_strdup;
- allocator->gstrndup = leakcheck_strndup;
- allocator->gsubstrdup = leakcheck_substrdup;
allocator->grealloc = leakcheck_realloc;
- allocator->greallocarray = leakcheck_reallocarray;
- allocator->gmallocarray = leakcheck_mallocarray;
allocator->gfree = leakcheck_free;
return 0;
}