Skip to content

Commit 9dd1bfe

Browse files
committed
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.
1 parent 9d41a3f commit 9dd1bfe

File tree

7 files changed

+101
-288
lines changed

7 files changed

+101
-288
lines changed

include/git2/sys/alloc.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,47 +24,13 @@ typedef struct {
2424
/** Allocate `n` bytes of memory */
2525
void * GIT_CALLBACK(gmalloc)(size_t n, const char *file, int line);
2626

27-
/**
28-
* Allocate memory for an array of `nelem` elements, where each element
29-
* has a size of `elsize`. Returned memory shall be initialized to
30-
* all-zeroes
31-
*/
32-
void * GIT_CALLBACK(gcalloc)(size_t nelem, size_t elsize, const char *file, int line);
33-
34-
/** Allocate memory for the string `str` and duplicate its contents. */
35-
char * GIT_CALLBACK(gstrdup)(const char *str, const char *file, int line);
36-
37-
/**
38-
* Equivalent to the `gstrdup` function, but only duplicating at most
39-
* `n + 1` bytes
40-
*/
41-
char * GIT_CALLBACK(gstrndup)(const char *str, size_t n, const char *file, int line);
42-
43-
/**
44-
* Equivalent to `gstrndup`, but will always duplicate exactly `n` bytes
45-
* of `str`. Thus, out of bounds reads at `str` may happen.
46-
*/
47-
char * GIT_CALLBACK(gsubstrdup)(const char *str, size_t n, const char *file, int line);
48-
4927
/**
5028
* This function shall deallocate the old object `ptr` and return a
5129
* pointer to a new object that has the size specified by `size`. In
5230
* case `ptr` is `NULL`, a new array shall be allocated.
5331
*/
5432
void * GIT_CALLBACK(grealloc)(void *ptr, size_t size, const char *file, int line);
5533

56-
/**
57-
* This function shall be equivalent to `grealloc`, but allocating
58-
* `neleme * elsize` bytes.
59-
*/
60-
void * GIT_CALLBACK(greallocarray)(void *ptr, size_t nelem, size_t elsize, const char *file, int line);
61-
62-
/**
63-
* This function shall allocate a new array of `nelem` elements, where
64-
* each element has a size of `elsize` bytes.
65-
*/
66-
void * GIT_CALLBACK(gmallocarray)(size_t nelem, size_t elsize, const char *file, int line);
67-
6834
/**
6935
* This function shall free the memory pointed to by `ptr`. In case
7036
* `ptr` is `NULL`, this shall be a no-op.

src/util/alloc.c

Lines changed: 65 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,75 @@
1515
/* Fail any allocation until git_libgit2_init is called. */
1616
git_allocator git__allocator = {
1717
git_failalloc_malloc,
18-
git_failalloc_calloc,
19-
git_failalloc_strdup,
20-
git_failalloc_strndup,
21-
git_failalloc_substrdup,
2218
git_failalloc_realloc,
23-
git_failalloc_reallocarray,
24-
git_failalloc_mallocarray,
2519
git_failalloc_free
2620
};
2721

22+
void *git__calloc(size_t nelem, size_t elsize)
23+
{
24+
size_t newsize;
25+
void *ptr;
26+
27+
if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
28+
return NULL;
29+
30+
if ((ptr = git__malloc(newsize)))
31+
memset(ptr, 0, newsize);
32+
33+
return ptr;
34+
}
35+
36+
void *git__reallocarray(void *ptr, size_t nelem, size_t elsize)
37+
{
38+
size_t newsize;
39+
40+
if (GIT_MULTIPLY_SIZET_OVERFLOW(&newsize, nelem, elsize))
41+
return NULL;
42+
43+
return git__realloc(ptr, newsize);
44+
}
45+
46+
void *git__mallocarray(size_t nelem, size_t elsize)
47+
{
48+
return git__reallocarray(NULL, nelem, elsize);
49+
}
50+
51+
char *git__strdup(const char *str)
52+
{
53+
size_t len = strlen(str) + 1;
54+
void *ptr = git__malloc(len);
55+
56+
if (ptr)
57+
memcpy(ptr, str, len);
58+
59+
return ptr;
60+
}
61+
62+
char *git__strndup(const char *str, size_t n)
63+
{
64+
size_t len = p_strnlen(str, n);
65+
char *ptr = git__malloc(len + 1);
66+
67+
if (ptr) {
68+
memcpy(ptr, str, len);
69+
ptr[len] = '\0';
70+
}
71+
72+
return ptr;
73+
}
74+
75+
char *git__substrdup(const char *str, size_t n)
76+
{
77+
char *ptr = git__malloc(n + 1);
78+
79+
if (ptr) {
80+
memcpy(ptr, str, n);
81+
ptr[n] = '\0';
82+
}
83+
84+
return ptr;
85+
}
86+
2887
static int setup_default_allocator(void)
2988
{
3089
#if defined(GIT_WIN32_LEAKCHECK)

src/util/alloc.h

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,42 @@
1010

1111
#include "git2/sys/alloc.h"
1212

13+
#include "git2_util.h"
14+
1315
extern git_allocator git__allocator;
1416

15-
#define git__malloc(len) git__allocator.gmalloc(len, __FILE__, __LINE__)
16-
#define git__calloc(nelem, elsize) git__allocator.gcalloc(nelem, elsize, __FILE__, __LINE__)
17-
#define git__strdup(str) git__allocator.gstrdup(str, __FILE__, __LINE__)
18-
#define git__strndup(str, n) git__allocator.gstrndup(str, n, __FILE__, __LINE__)
19-
#define git__substrdup(str, n) git__allocator.gsubstrdup(str, n, __FILE__, __LINE__)
20-
#define git__realloc(ptr, size) git__allocator.grealloc(ptr, size, __FILE__, __LINE__)
21-
#define git__reallocarray(ptr, nelem, elsize) git__allocator.greallocarray(ptr, nelem, elsize, __FILE__, __LINE__)
22-
#define git__mallocarray(nelem, elsize) git__allocator.gmallocarray(nelem, elsize, __FILE__, __LINE__)
23-
#define git__free git__allocator.gfree
17+
GIT_INLINE(void *) git__malloc(size_t len)
18+
{
19+
void *p = git__allocator.gmalloc(len, __FILE__, __LINE__);
20+
21+
if (!p)
22+
git_error_set_oom();
23+
24+
return p;
25+
}
26+
27+
GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
28+
{
29+
void *p = git__allocator.grealloc(ptr, size, __FILE__, __LINE__);
30+
31+
if (!p)
32+
git_error_set_oom();
33+
34+
return p;
35+
}
36+
37+
GIT_INLINE(void) git__free(void *ptr)
38+
{
39+
git__allocator.gfree(ptr);
40+
}
41+
42+
extern void *git__calloc(size_t nelem, size_t elsize);
43+
extern void *git__mallocarray(size_t nelem, size_t elsize);
44+
extern void *git__reallocarray(void *ptr, size_t nelem, size_t elsize);
45+
46+
extern char *git__strdup(const char *str);
47+
extern char *git__strndup(const char *str, size_t n);
48+
extern char *git__substrdup(const char *str, size_t n);
2449

2550
/**
2651
* This function is being called by our global setup routines to

src/util/allocators/failalloc.c

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,45 +16,6 @@ void *git_failalloc_malloc(size_t len, const char *file, int line)
1616
return NULL;
1717
}
1818

19-
void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line)
20-
{
21-
GIT_UNUSED(nelem);
22-
GIT_UNUSED(elsize);
23-
GIT_UNUSED(file);
24-
GIT_UNUSED(line);
25-
26-
return NULL;
27-
}
28-
29-
char *git_failalloc_strdup(const char *str, const char *file, int line)
30-
{
31-
GIT_UNUSED(str);
32-
GIT_UNUSED(file);
33-
GIT_UNUSED(line);
34-
35-
return NULL;
36-
}
37-
38-
char *git_failalloc_strndup(const char *str, size_t n, const char *file, int line)
39-
{
40-
GIT_UNUSED(str);
41-
GIT_UNUSED(n);
42-
GIT_UNUSED(file);
43-
GIT_UNUSED(line);
44-
45-
return NULL;
46-
}
47-
48-
char *git_failalloc_substrdup(const char *start, size_t n, const char *file, int line)
49-
{
50-
GIT_UNUSED(start);
51-
GIT_UNUSED(n);
52-
GIT_UNUSED(file);
53-
GIT_UNUSED(line);
54-
55-
return NULL;
56-
}
57-
5819
void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line)
5920
{
6021
GIT_UNUSED(ptr);
@@ -65,27 +26,6 @@ void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line)
6526
return NULL;
6627
}
6728

68-
void *git_failalloc_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line)
69-
{
70-
GIT_UNUSED(ptr);
71-
GIT_UNUSED(nelem);
72-
GIT_UNUSED(elsize);
73-
GIT_UNUSED(file);
74-
GIT_UNUSED(line);
75-
76-
return NULL;
77-
}
78-
79-
void *git_failalloc_mallocarray(size_t nelem, size_t elsize, const char *file, int line)
80-
{
81-
GIT_UNUSED(nelem);
82-
GIT_UNUSED(elsize);
83-
GIT_UNUSED(file);
84-
GIT_UNUSED(line);
85-
86-
return NULL;
87-
}
88-
8929
void git_failalloc_free(void *ptr)
9030
{
9131
GIT_UNUSED(ptr);

src/util/allocators/failalloc.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,7 @@
1111
#include "git2_util.h"
1212

1313
extern void *git_failalloc_malloc(size_t len, const char *file, int line);
14-
extern void *git_failalloc_calloc(size_t nelem, size_t elsize, const char *file, int line);
15-
extern char *git_failalloc_strdup(const char *str, const char *file, int line);
16-
extern char *git_failalloc_strndup(const char *str, size_t n, const char *file, int line);
17-
extern char *git_failalloc_substrdup(const char *start, size_t n, const char *file, int line);
1814
extern void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line);
19-
extern void *git_failalloc_reallocarray(void *ptr, size_t nelem, size_t elsize, const char *file, int line);
20-
extern void *git_failalloc_mallocarray(size_t nelem, size_t elsize, const char *file, int line);
2115
extern void git_failalloc_free(void *ptr);
2216

2317
#endif

0 commit comments

Comments
 (0)