Merge pull request #4854 from libgit2/ethomson/buf_oom_test buf::oom tests: use custom allocator for oom failures
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
diff --git a/include/git2/common.h b/include/git2/common.h
index a14e096..152e23a 100644
--- a/include/git2/common.h
+++ b/include/git2/common.h
@@ -364,7 +364,8 @@ typedef enum {
*
* > Set the memory allocator to a different memory allocator. This
* > allocator will then be used to make all memory allocations for
- * > libgit2 operations.
+ * > libgit2 operations. If the given `allocator` is NULL, then the
+ * > system default will be restored.
*
* opts(GIT_OPT_ENABLE_UNSAVED_INDEX_SAFETY, int enabled)
*
diff --git a/src/alloc.c b/src/alloc.c
index d4e6f1e..0cac457 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -15,6 +15,15 @@
git_allocator git__allocator;
+static int setup_default_allocator(void)
+{
+#if defined(GIT_MSVC_CRTDBG)
+ return git_win32_crtdbg_init_allocator(&git__allocator);
+#else
+ return git_stdalloc_init_allocator(&git__allocator);
+#endif
+}
+
int git_allocator_global_init(void)
{
/*
@@ -24,15 +33,14 @@ int git_allocator_global_init(void)
if (git__allocator.gmalloc != NULL)
return 0;
-#if defined(GIT_MSVC_CRTDBG)
- return git_win32_crtdbg_init_allocator(&git__allocator);
-#else
- return git_stdalloc_init_allocator(&git__allocator);
-#endif
+ return setup_default_allocator();
}
int git_allocator_setup(git_allocator *allocator)
{
+ if (!allocator)
+ return setup_default_allocator();
+
memcpy(&git__allocator, allocator, sizeof(*allocator));
return 0;
}
diff --git a/tests/buf/oom.c b/tests/buf/oom.c
index ec3bad9..726234e 100644
--- a/tests/buf/oom.c
+++ b/tests/buf/oom.c
@@ -1,57 +1,59 @@
#include "clar_libgit2.h"
#include "buffer.h"
-/*
- * We want to use some ridiculous size that `malloc` will fail with
- * but that does not otherwise interfere with testing. On Linux, choose
- * a number that is large enough to fail immediately but small enough
- * that valgrind doesn't believe it to erroneously be a negative number.
- * On macOS, choose a number that is large enough to fail immediately
- * without having libc print warnings to stderr.
- */
-#if defined(GIT_ARCH_64) && defined(__linux__)
-# define TOOBIG 0x0fffffffffffffff
-#elif defined(GIT_ARCH_64)
-# define TOOBIG 0xffffffffffffff00
-#endif
-
-/**
- * If we make a ridiculously large request the first time we
- * actually allocate some space in the git_buf, the realloc()
- * will fail. And because the git_buf_grow() wrapper always
- * sets mark_oom, the code in git_buf_try_grow() will free
- * the internal buffer and set it to git_buf__oom.
- *
- * We initialized the internal buffer to (the static variable)
- * git_buf__initbuf. The purpose of this test is to make sure
- * that we don't try to free the static buffer.
- *
- * Skip this test entirely on 32-bit platforms; a buffer large enough
- * to guarantee malloc failures is so large that valgrind considers
- * it likely to be an error.
- */
+/* Override default allocators with ones that will fail predictably. */
+
+static git_allocator std_alloc;
+static git_allocator oom_alloc;
+
+static void *oom_malloc(size_t n, const char *file, int line)
+{
+ /* Reject any allocation of more than 100 bytes */
+ return (n > 100) ? NULL : std_alloc.gmalloc(n, file, line);
+}
+
+static void *oom_realloc(void *p, size_t n, const char *file, int line)
+{
+ /* Reject any allocation of more than 100 bytes */
+ return (n > 100) ? NULL : std_alloc.grealloc(p, n, file, line);
+}
+
+void test_buf_oom__initialize(void)
+{
+ git_stdalloc_init_allocator(&std_alloc);
+ git_stdalloc_init_allocator(&oom_alloc);
+
+ oom_alloc.gmalloc = oom_malloc;
+ oom_alloc.grealloc = oom_realloc;
+
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ALLOCATOR, &oom_alloc));
+}
+
+void test_buf_oom__cleanup(void)
+{
+ cl_git_pass(git_libgit2_opts(GIT_OPT_SET_ALLOCATOR, NULL));
+}
+
void test_buf_oom__grow(void)
{
-#ifdef GIT_ARCH_64
git_buf buf = GIT_BUF_INIT;
- git_buf_clear(&buf);
+ cl_git_pass(git_buf_grow(&buf, 42));
+ cl_assert(!git_buf_oom(&buf));
- cl_assert(git_buf_grow(&buf, TOOBIG) == -1);
+ cl_assert(git_buf_grow(&buf, 101) == -1);
cl_assert(git_buf_oom(&buf));
git_buf_dispose(&buf);
-#else
- cl_skip();
-#endif
}
void test_buf_oom__grow_by(void)
{
git_buf buf = GIT_BUF_INIT;
- buf.size = SIZE_MAX-10;
+ cl_git_pass(git_buf_grow_by(&buf, 42));
+ cl_assert(!git_buf_oom(&buf));
- cl_assert(git_buf_grow_by(&buf, 50) == -1);
+ cl_assert(git_buf_grow_by(&buf, 101) == -1);
cl_assert(git_buf_oom(&buf));
}