Skip to content

Commit 08f28ff

Browse files
committed
alloc: set up an allocator that fails before library init
We require the library to be initialized with git_libgit2_init before it is functional. However, if a user tries to uses the library without doing so - as they might when getting started with the library for the first time - we will likely crash. This commit introduces some guard rails - now instead of having _no_ allocator by default, we'll have an allocator that always fails, and never tries to set an error message (since the thread-local state is set up by git_libgit2_init). We've modified the error retrieval function to (try to) ensure that the library has been initialized before getting the thread-local error message. (Unfortunately, we cannot determine if the thread local storage has actually been configured, this does require initialization by git_libgit2_init. But a naive attempt should be good enough for most cases.)
1 parent 6c51014 commit 08f28ff

File tree

4 files changed

+141
-4
lines changed

4 files changed

+141
-4
lines changed

src/alloc.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,22 @@
88
#include "alloc.h"
99
#include "runtime.h"
1010

11+
#include "allocators/failalloc.h"
1112
#include "allocators/stdalloc.h"
1213
#include "allocators/win32_leakcheck.h"
1314

14-
git_allocator git__allocator;
15+
/* Fail any allocation until git_libgit2_init is called. */
16+
git_allocator git__allocator = {
17+
git_failalloc_malloc,
18+
git_failalloc_calloc,
19+
git_failalloc_strdup,
20+
git_failalloc_strndup,
21+
git_failalloc_substrdup,
22+
git_failalloc_realloc,
23+
git_failalloc_reallocarray,
24+
git_failalloc_mallocarray,
25+
git_failalloc_free
26+
};
1527

1628
static int setup_default_allocator(void)
1729
{
@@ -25,10 +37,10 @@ static int setup_default_allocator(void)
2537
int git_allocator_global_init(void)
2638
{
2739
/*
28-
* We don't want to overwrite any allocator which has been set before
29-
* the init function is called.
40+
* We don't want to overwrite any allocator which has been set
41+
* before the init function is called.
3042
*/
31-
if (git__allocator.gmalloc != NULL)
43+
if (git__allocator.gmalloc != git_failalloc_malloc)
3244
return 0;
3345

3446
return setup_default_allocator();

src/allocators/failalloc.c

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
#include "failalloc.h"
9+
10+
void *git_failalloc_malloc(size_t len, const char *file, int line)
11+
{
12+
GIT_UNUSED(len);
13+
GIT_UNUSED(file);
14+
GIT_UNUSED(line);
15+
16+
return NULL;
17+
}
18+
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+
58+
void *git_failalloc_realloc(void *ptr, size_t size, const char *file, int line)
59+
{
60+
GIT_UNUSED(ptr);
61+
GIT_UNUSED(size);
62+
GIT_UNUSED(file);
63+
GIT_UNUSED(line);
64+
65+
return NULL;
66+
}
67+
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+
89+
void git_failalloc_free(void *ptr)
90+
{
91+
GIT_UNUSED(ptr);
92+
}

src/allocators/failalloc.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (C) the libgit2 contributors. All rights reserved.
3+
*
4+
* This file is part of libgit2, distributed under the GNU GPL v2 with
5+
* a Linking Exception. For full terms see the included COPYING file.
6+
*/
7+
8+
#ifndef INCLUDE_allocators_failalloc_h__
9+
#define INCLUDE_allocators_failalloc_h__
10+
11+
#include "common.h"
12+
13+
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);
18+
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);
21+
extern void git_failalloc_free(void *ptr);
22+
23+
#endif

src/errors.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "threadstate.h"
1111
#include "posix.h"
1212
#include "buffer.h"
13+
#include "libgit2.h"
1314

1415
/********************************************
1516
* New error handling
@@ -20,6 +21,11 @@ static git_error g_git_oom_error = {
2021
GIT_ERROR_NOMEMORY
2122
};
2223

24+
static git_error g_git_uninitialized_error = {
25+
"libgit2 has not been initialized; you must call git_libgit2_init",
26+
GIT_ERROR_INVALID
27+
};
28+
2329
static void set_error_from_buffer(int error_class)
2430
{
2531
git_error *error = &GIT_THREADSTATE->error_t;
@@ -131,6 +137,10 @@ void git_error_clear(void)
131137

132138
const git_error *git_error_last(void)
133139
{
140+
/* If the library is not initialized, return a static error. */
141+
if (!git_libgit2_init_count())
142+
return &g_git_uninitialized_error;
143+
134144
return GIT_THREADSTATE->last_error;
135145
}
136146

0 commit comments

Comments
 (0)