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); +}