Commit e0482934e6187b2e76c0e44960bcbd3ce3795d0c

Edward Thomson 2014-11-21T13:16:42

Merge pull request #2725 from libgit2/vmg/attr-null Do not assume blob contents are NULL terminated

diff --git a/examples/blame.c b/examples/blame.c
index 9d38f25..b126c0d 100644
--- a/examples/blame.c
+++ b/examples/blame.c
@@ -38,6 +38,7 @@ static void parse_opts(struct opts *o, int argc, char *argv[]);
 int main(int argc, char *argv[])
 {
 	int i, line, break_on_null_hunk;
+	size_t rawsize;
 	char spec[1024] = {0};
 	struct opts o = {0};
 	const char *rawdata;
@@ -94,23 +95,24 @@ int main(int argc, char *argv[])
 	git_object_free(obj);
 
 	rawdata = git_blob_rawcontent(blob);
+	rawsize = git_blob_rawsize(blob);
 
 	/** Produce the output. */
 	line = 1;
 	i = 0;
 	break_on_null_hunk = 0;
-	while (i < git_blob_rawsize(blob)) {
-		const char *eol = strchr(rawdata+i, '\n');
+	while (i < rawsize) {
+		const char *eol = memchr(rawdata + i, '\n', rawsize - i);
 		char oid[10] = {0};
 		const git_blame_hunk *hunk = git_blame_get_hunk_byline(blame, line);
 
-		if (break_on_null_hunk && !hunk) break;
+		if (break_on_null_hunk && !hunk)
+			break;
 
 		if (hunk) {
 			char sig[128] = {0};
 			break_on_null_hunk = 1;
 			
-
 			git_oid_tostr(oid, 10, &hunk->final_commit_id);
 			snprintf(sig, 30, "%s <%s>", hunk->final_signature->name, hunk->final_signature->email);
 
@@ -118,8 +120,8 @@ int main(int argc, char *argv[])
 					oid,
 					sig,
 					line,
-					(int)(eol-rawdata-i),
-					rawdata+i);
+					(int)(eol - rawdata - i),
+					rawdata + i);
 		}
 
 		i = (int)(eol - rawdata + 1);
diff --git a/src/attr_file.c b/src/attr_file.c
index e3692ce..b3efeef 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -103,7 +103,6 @@ int git_attr_file__load(
 	int error = 0;
 	git_blob *blob = NULL;
 	git_buf content = GIT_BUF_INIT;
-	const char *data = NULL;
 	git_attr_file *file;
 	struct stat st;
 
@@ -120,7 +119,9 @@ int git_attr_file__load(
 			(error = git_blob_lookup(&blob, repo, &id)) < 0)
 			return error;
 
-		data = git_blob_rawcontent(blob);
+		/* Do not assume that data straight from the ODB is NULL-terminated;
+		 * copy the contents of a file to a buffer to work on */
+		git_buf_put(&content, git_blob_rawcontent(blob), git_blob_rawsize(blob));
 		break;
 	}
 	case GIT_ATTR_FILE__FROM_FILE: {
@@ -143,7 +144,6 @@ int git_attr_file__load(
 		if (error < 0)
 			return GIT_ENOTFOUND;
 
-		data = content.ptr;
 		break;
 	}
 	default:
@@ -154,7 +154,7 @@ int git_attr_file__load(
 	if ((error = git_attr_file__new(&file, entry, source)) < 0)
 		goto cleanup;
 
-	if (parser && (error = parser(repo, file, data)) < 0) {
+	if (parser && (error = parser(repo, file, git_buf_cstr(&content))) < 0) {
 		git_attr_file__free(file);
 		goto cleanup;
 	}
diff --git a/src/buf_text.c b/src/buf_text.c
index 8d2b141..cead599 100644
--- a/src/buf_text.c
+++ b/src/buf_text.c
@@ -143,6 +143,7 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
 		tgt->ptr[tgt->size++] = '\n';
 	}
 
+	tgt->ptr[tgt->size] = '\0';
 	return git_buf_put(tgt, scan, end - scan);
 }
 
diff --git a/src/buffer.c b/src/buffer.c
index e9c420e..7744d8f 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -176,10 +176,13 @@ int git_buf_putcn(git_buf *buf, char c, size_t len)
 
 int git_buf_put(git_buf *buf, const char *data, size_t len)
 {
-	ENSURE_SIZE(buf, buf->size + len + 1);
-	memmove(buf->ptr + buf->size, data, len);
-	buf->size += len;
-	buf->ptr[buf->size] = '\0';
+	if (len) {
+		assert(data);
+		ENSURE_SIZE(buf, buf->size + len + 1);
+		memmove(buf->ptr + buf->size, data, len);
+		buf->size += len;
+		buf->ptr[buf->size] = '\0';
+	}
 	return 0;
 }
 
diff --git a/src/notes.c b/src/notes.c
index 046a916..4b15925 100644
--- a/src/notes.c
+++ b/src/notes.c
@@ -323,11 +323,10 @@ static int note_new(
 		git_signature_dup(&note->committer, git_commit_committer(commit)) < 0)
 		return -1;
 
-	note->message = git__strdup((char *)git_blob_rawcontent(blob));
+	note->message = git__strndup(git_blob_rawcontent(blob), git_blob_rawsize(blob));
 	GITERR_CHECK_ALLOC(note->message);
 
 	*out = note;
-
 	return 0;
 }
 
diff --git a/tests/core/buffer.c b/tests/core/buffer.c
index 641fed6..87dec46 100644
--- a/tests/core/buffer.c
+++ b/tests/core/buffer.c
@@ -281,11 +281,10 @@ check_buf_append_abc(
 /* more variations on append tests */
 void test_core_buffer__5(void)
 {
-	check_buf_append("", "", "", 0, 8);
-	check_buf_append("a", "", "a", 1, 8);
+	check_buf_append("", "", "", 0, 0);
+	check_buf_append("a", "", "a", 1, 0);
 	check_buf_append("", "a", "a", 1, 8);
 	check_buf_append("", "a", "a", 1, 8);
-	check_buf_append("a", "", "a", 1, 8);
 	check_buf_append("a", "b", "ab", 2, 8);
 	check_buf_append("", "abcdefgh", "abcdefgh", 8, 16);
 	check_buf_append("abcdefgh", "", "abcdefgh", 8, 16);