Skip to content

Commit ce488be

Browse files
committed
errors: don't rely on tls data working
Thread-local storage data may fail to initialize; in this case, do not try to set the error message into it. When the thread state has not been initialized, return a hardcoded message to that affect.
1 parent 4be63a6 commit ce488be

File tree

1 file changed

+68
-13
lines changed

1 file changed

+68
-13
lines changed

src/libgit2/errors.c

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,41 @@ static git_error uninitialized_error = {
2626
GIT_ERROR_INVALID
2727
};
2828

29+
static git_error tlsdata_error = {
30+
"thread-local data initialization failure",
31+
GIT_ERROR
32+
};
33+
2934
static void set_error_from_buffer(int error_class)
3035
{
31-
git_error *error = &GIT_THREADSTATE->error_t;
32-
git_str *buf = &GIT_THREADSTATE->error_buf;
36+
git_threadstate *threadstate = GIT_THREADSTATE;
37+
git_error *error;
38+
git_str *buf;
39+
40+
if (!threadstate)
41+
return;
42+
43+
error = &threadstate->error_t;
44+
buf = &threadstate->error_buf;
3345

3446
error->message = buf->ptr;
3547
error->klass = error_class;
3648

37-
GIT_THREADSTATE->last_error = error;
49+
threadstate->last_error = error;
3850
}
3951

4052
static void set_error(int error_class, char *string)
4153
{
42-
git_str *buf = &GIT_THREADSTATE->error_buf;
54+
git_threadstate *threadstate = GIT_THREADSTATE;
55+
git_str *buf;
56+
57+
if (!threadstate)
58+
return;
59+
60+
buf = &threadstate->error_buf;
4361

4462
git_str_clear(buf);
63+
4564
if (string) {
4665
git_str_puts(buf, string);
4766
git__free(string);
@@ -52,7 +71,12 @@ static void set_error(int error_class, char *string)
5271

5372
void git_error_set_oom(void)
5473
{
55-
GIT_THREADSTATE->last_error = &oom_error;
74+
git_threadstate *threadstate = GIT_THREADSTATE;
75+
76+
if (!threadstate)
77+
return;
78+
79+
threadstate->last_error = &oom_error;
5680
}
5781

5882
void git_error_set(int error_class, const char *fmt, ...)
@@ -69,10 +93,18 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
6993
#ifdef GIT_WIN32
7094
DWORD win32_error_code = (error_class == GIT_ERROR_OS) ? GetLastError() : 0;
7195
#endif
96+
97+
git_threadstate *threadstate = GIT_THREADSTATE;
7298
int error_code = (error_class == GIT_ERROR_OS) ? errno : 0;
73-
git_str *buf = &GIT_THREADSTATE->error_buf;
99+
git_str *buf;
100+
101+
if (!threadstate)
102+
return;
103+
104+
buf = &threadstate->error_buf;
74105

75106
git_str_clear(buf);
107+
76108
if (fmt) {
77109
git_str_vprintf(buf, fmt, ap);
78110
if (error_class == GIT_ERROR_OS)
@@ -81,7 +113,7 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
81113

82114
if (error_class == GIT_ERROR_OS) {
83115
#ifdef GIT_WIN32
84-
char * win32_error = git_win32_get_error_message(win32_error_code);
116+
char *win32_error = git_win32_get_error_message(win32_error_code);
85117
if (win32_error) {
86118
git_str_puts(buf, win32_error);
87119
git__free(win32_error);
@@ -103,10 +135,16 @@ void git_error_vset(int error_class, const char *fmt, va_list ap)
103135

104136
int git_error_set_str(int error_class, const char *string)
105137
{
106-
git_str *buf = &GIT_THREADSTATE->error_buf;
138+
git_threadstate *threadstate = GIT_THREADSTATE;
139+
git_str *buf;
107140

108141
GIT_ASSERT_ARG(string);
109142

143+
if (!threadstate)
144+
return -1;
145+
146+
buf = &threadstate->error_buf;
147+
110148
git_str_clear(buf);
111149
git_str_puts(buf, string);
112150

@@ -119,9 +157,14 @@ int git_error_set_str(int error_class, const char *string)
119157

120158
void git_error_clear(void)
121159
{
122-
if (GIT_THREADSTATE->last_error != NULL) {
160+
git_threadstate *threadstate = GIT_THREADSTATE;
161+
162+
if (!threadstate)
163+
return;
164+
165+
if (threadstate->last_error != NULL) {
123166
set_error(0, NULL);
124-
GIT_THREADSTATE->last_error = NULL;
167+
threadstate->last_error = NULL;
125168
}
126169

127170
errno = 0;
@@ -132,17 +175,29 @@ void git_error_clear(void)
132175

133176
const git_error *git_error_last(void)
134177
{
178+
git_threadstate *threadstate;
179+
135180
/* If the library is not initialized, return a static error. */
136181
if (!git_libgit2_init_count())
137182
return &uninitialized_error;
138183

139-
return GIT_THREADSTATE->last_error;
184+
if ((threadstate = GIT_THREADSTATE) == NULL)
185+
return &tlsdata_error;
186+
187+
return threadstate->last_error;
140188
}
141189

142190
int git_error_state_capture(git_error_state *state, int error_code)
143191
{
144-
git_error *error = GIT_THREADSTATE->last_error;
145-
git_str *error_buf = &GIT_THREADSTATE->error_buf;
192+
git_threadstate *threadstate = GIT_THREADSTATE;
193+
git_error *error;
194+
git_str *error_buf;
195+
196+
if (!threadstate)
197+
return -1;
198+
199+
error = threadstate->last_error;
200+
error_buf = &threadstate->error_buf;
146201

147202
memset(state, 0, sizeof(git_error_state));
148203

0 commit comments

Comments
 (0)