Merge pull request #2725 from libgit2/vmg/attr-null Do not assume blob contents are NULL terminated
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
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(¬e->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);