summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/buffer.c3
-rw-r--r--tests/buf/oom.c31
2 files changed, 33 insertions, 1 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 7744d8f49..8013457c5 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -67,7 +67,8 @@ int git_buf_try_grow(
if (!new_ptr) {
if (mark_oom) {
- if (buf->ptr) git__free(buf->ptr);
+ if (buf->ptr && (buf->ptr != git_buf__initbuf))
+ git__free(buf->ptr);
buf->ptr = git_buf__oom;
}
return -1;
diff --git a/tests/buf/oom.c b/tests/buf/oom.c
new file mode 100644
index 000000000..709439aa5
--- /dev/null
+++ b/tests/buf/oom.c
@@ -0,0 +1,31 @@
+#include "clar_libgit2.h"
+#include "buffer.h"
+
+#if defined(GIT_ARCH_64)
+#define TOOBIG 0xffffffffffffff00
+#else
+#define TOOBIG 0xffffff00
+#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.
+ */
+void test_buf_oom__grow(void)
+{
+ git_buf buf = GIT_BUF_INIT;
+
+ git_buf_clear(&buf);
+
+ cl_assert(git_buf_grow(&buf, TOOBIG) == -1);
+ cl_assert(git_buf_oom(&buf));
+
+ git_buf_free(&buf);
+}