Skip to content

Commit 58be98b

Browse files
authored
Merge pull request libgit2#6563 from libgit2/pks/test-allocator
tests: add allocator with limited number of bytes
2 parents 47dcc4b + 2757641 commit 58be98b

File tree

12 files changed

+318
-290
lines changed

12 files changed

+318
-290
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/libgit2/threadstate.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,23 @@ git_threadstate *git_threadstate_get(void)
7575
if ((threadstate = git_tlsdata_get(tls_key)) != NULL)
7676
return threadstate;
7777

78-
if ((threadstate = git__calloc(1, sizeof(git_threadstate))) == NULL ||
79-
git_str_init(&threadstate->error_buf, 0) < 0)
78+
/*
79+
* Avoid git__malloc here, since if it fails, it sets an error
80+
* message, which requires thread state, which would allocate
81+
* here, which would fail, which would set an error message...
82+
*/
83+
84+
if ((threadstate = git__allocator.gmalloc(sizeof(git_threadstate),
85+
__FILE__, __LINE__)) == NULL)
8086
return NULL;
8187

88+
memset(threadstate, 0, sizeof(git_threadstate));
89+
90+
if (git_str_init(&threadstate->error_buf, 0) < 0) {
91+
git__allocator.gfree(threadstate);
92+
return NULL;
93+
}
94+
8295
git_tlsdata_set(tls_key, threadstate);
8396
return threadstate;
8497
}

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)