summaryrefslogtreecommitdiff
path: root/src/buffer.c
diff options
context:
space:
mode:
authorRussell Belfer <arrbee@arrbee.com>2011-12-14 12:34:43 -0800
committerRussell Belfer <arrbee@arrbee.com>2011-12-14 14:31:06 -0800
commitb5daae68a4ae859653141fb097e7b7c81b25530b (patch)
tree977115657e8b1690ea0a7d65ba49fc421b4cb392 /src/buffer.c
parentd6ccedddd2f76d69b05ecfa45a93cde8682776e6 (diff)
downloadlibgit2-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.c18
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';