diff options
author | Russell Belfer <arrbee@arrbee.com> | 2011-12-14 12:34:43 -0800 |
---|---|---|
committer | Russell Belfer <arrbee@arrbee.com> | 2011-12-14 14:31:06 -0800 |
commit | b5daae68a4ae859653141fb097e7b7c81b25530b (patch) | |
tree | 977115657e8b1690ea0a7d65ba49fc421b4cb392 /src/buffer.c | |
parent | d6ccedddd2f76d69b05ecfa45a93cde8682776e6 (diff) | |
download | libgit2-b5daae68a4ae859653141fb097e7b7c81b25530b.tar.gz |
Allow git_buf_joinpath to accept self-joins
It was not safe for git_buf_joinpath to be used with a pointer
into the buf itself because a reallocation could invalidate
the input parameter that pointed into the buffer. This patch
makes it safe to self join, at least for the leading input to
the join, which is the common "append" case for self joins.
Also added unit tests to explicitly cover this case.
This should actually fix #511
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/src/buffer.c b/src/buffer.c index 27e20d562..def3496ce 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -328,6 +328,10 @@ int git_buf_join( size_t strlen_a = strlen(str_a); size_t strlen_b = strlen(str_b); int need_sep = 0; + ssize_t offset_a = -1; + + /* not safe to have str_b point internally to the buffer */ + assert(str_b < buf->ptr || str_b > buf->ptr + buf->size); /* figure out if we need to insert a separator */ if (separator && strlen_a) { @@ -336,14 +340,24 @@ int git_buf_join( need_sep = 1; } + /* str_a could be part of the buffer */ + if (str_a >= buf->ptr && str_a < buf->ptr + buf->size) + offset_a = str_a - buf->ptr; + error = git_buf_grow(buf, strlen_a + strlen_b + need_sep + 1); if (error < GIT_SUCCESS) return error; - memmove(buf->ptr, str_a, strlen_a); + /* fix up internal pointers */ + if (offset_a >= 0) + str_a = buf->ptr + offset_a; + + /* do the actual copying */ + if (offset_a != 0) + memmove(buf->ptr, str_a, strlen_a); if (need_sep) buf->ptr[strlen_a] = separator; - memmove(buf->ptr + strlen_a + need_sep, str_b, strlen_b); + memcpy(buf->ptr + strlen_a + need_sep, str_b, strlen_b); buf->size = strlen_a + strlen_b + need_sep; buf->ptr[buf->size] = '\0'; |