Commit 08f28ff5 by Edward Thomson

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.)
parent 6c51014d
...@@ -8,10 +8,22 @@ ...@@ -8,10 +8,22 @@
#include "alloc.h" #include "alloc.h"
#include "runtime.h" #include "runtime.h"
#include "allocators/failalloc.h"
#include "allocators/stdalloc.h" #include "allocators/stdalloc.h"
#include "allocators/win32_leakcheck.h" #include "allocators/win32_leakcheck.h"
git_allocator git__allocator; /* 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
};
static int setup_default_allocator(void) static int setup_default_allocator(void)
{ {
...@@ -25,10 +37,10 @@ static int setup_default_allocator(void) ...@@ -25,10 +37,10 @@ static int setup_default_allocator(void)
int git_allocator_global_init(void) int git_allocator_global_init(void)
{ {
/* /*
* We don't want to overwrite any allocator which has been set before * We don't want to overwrite any allocator which has been set
* the init function is called. * before the init function is called.
*/ */
if (git__allocator.gmalloc != NULL) if (git__allocator.gmalloc != git_failalloc_malloc)
return 0; return 0;
return setup_default_allocator(); return setup_default_allocator();
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "failalloc.h"
void *git_failalloc_malloc(size_t len, const char *file, int line)
{
GIT_UNUSED(len);
GIT_UNUSED(file);
GIT_UNUSED(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);
GIT_UNUSED(size);
GIT_UNUSED(file);
GIT_UNUSED(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);
}
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_allocators_failalloc_h__
#define INCLUDE_allocators_failalloc_h__
#include "common.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
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "threadstate.h" #include "threadstate.h"
#include "posix.h" #include "posix.h"
#include "buffer.h" #include "buffer.h"
#include "libgit2.h"
/******************************************** /********************************************
* New error handling * New error handling
...@@ -20,6 +21,11 @@ static git_error g_git_oom_error = { ...@@ -20,6 +21,11 @@ static git_error g_git_oom_error = {
GIT_ERROR_NOMEMORY GIT_ERROR_NOMEMORY
}; };
static git_error g_git_uninitialized_error = {
"libgit2 has not been initialized; you must call git_libgit2_init",
GIT_ERROR_INVALID
};
static void set_error_from_buffer(int error_class) static void set_error_from_buffer(int error_class)
{ {
git_error *error = &GIT_THREADSTATE->error_t; git_error *error = &GIT_THREADSTATE->error_t;
...@@ -131,6 +137,10 @@ void git_error_clear(void) ...@@ -131,6 +137,10 @@ void git_error_clear(void)
const git_error *git_error_last(void) const git_error *git_error_last(void)
{ {
/* If the library is not initialized, return a static error. */
if (!git_libgit2_init_count())
return &g_git_uninitialized_error;
return GIT_THREADSTATE->last_error; return GIT_THREADSTATE->last_error;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment