Merge pull request #4529 from libgit2/ethomson/index_add_requires_files git_index_add_frombuffer: only accept files/links
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
diff --git a/src/index.c b/src/index.c
index d782a08..d98872a 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1396,12 +1396,16 @@ static int index_conflict_to_reuc(git_index *index, const char *path)
return ret;
}
-static bool valid_filemode(const int filemode)
+GIT_INLINE(bool) is_file_or_link(const int filemode)
{
return (filemode == GIT_FILEMODE_BLOB ||
filemode == GIT_FILEMODE_BLOB_EXECUTABLE ||
- filemode == GIT_FILEMODE_LINK ||
- filemode == GIT_FILEMODE_COMMIT);
+ filemode == GIT_FILEMODE_LINK);
+}
+
+GIT_INLINE(bool) valid_filemode(const int filemode)
+{
+ return (is_file_or_link(filemode) || filemode == GIT_FILEMODE_COMMIT);
}
int git_index_add_frombuffer(
@@ -1419,7 +1423,7 @@ int git_index_add_frombuffer(
"could not initialize index entry. "
"Index is not backed up by an existing repository.");
- if (!valid_filemode(source_entry->mode)) {
+ if (!is_file_or_link(source_entry->mode)) {
giterr_set(GITERR_INDEX, "invalid filemode");
return -1;
}
@@ -1605,7 +1609,7 @@ int git_index_add(git_index *index, const git_index_entry *source_entry)
assert(index && source_entry && source_entry->path);
if (!valid_filemode(source_entry->mode)) {
- giterr_set(GITERR_INDEX, "invalid filemode");
+ giterr_set(GITERR_INDEX, "invalid entry mode");
return -1;
}
diff --git a/tests/index/filemodes.c b/tests/index/filemodes.c
index 2efad5b..f53414d 100644
--- a/tests/index/filemodes.c
+++ b/tests/index/filemodes.c
@@ -256,3 +256,64 @@ void test_index_filemodes__invalid(void)
git_index_free(index);
}
+
+void test_index_filemodes__frombuffer_requires_files(void)
+{
+ git_index *index;
+ git_index_entry new_entry;
+ const git_index_entry *ret_entry;
+ const char *content = "hey there\n";
+
+ cl_git_pass(git_repository_index(&index, g_repo));
+
+ /* regular blob */
+ new_entry.path = "dummy-file.txt";
+ new_entry.mode = GIT_FILEMODE_BLOB;
+
+ cl_git_pass(git_index_add_frombuffer(index,
+ &new_entry, content, strlen(content)));
+
+ cl_assert((ret_entry = git_index_get_bypath(index, "dummy-file.txt", 0)));
+ cl_assert_equal_s("dummy-file.txt", ret_entry->path);
+ cl_assert_equal_i(GIT_FILEMODE_BLOB, ret_entry->mode);
+
+ /* executable blob */
+ new_entry.path = "dummy-file.txt";
+ new_entry.mode = GIT_FILEMODE_BLOB_EXECUTABLE;
+
+ cl_git_pass(git_index_add_frombuffer(index,
+ &new_entry, content, strlen(content)));
+
+ cl_assert((ret_entry = git_index_get_bypath(index, "dummy-file.txt", 0)));
+ cl_assert_equal_s("dummy-file.txt", ret_entry->path);
+ cl_assert_equal_i(GIT_FILEMODE_BLOB_EXECUTABLE, ret_entry->mode);
+
+ /* links are also acceptable */
+ new_entry.path = "dummy-link.txt";
+ new_entry.mode = GIT_FILEMODE_LINK;
+
+ cl_git_pass(git_index_add_frombuffer(index,
+ &new_entry, content, strlen(content)));
+
+ cl_assert((ret_entry = git_index_get_bypath(index, "dummy-link.txt", 0)));
+ cl_assert_equal_s("dummy-link.txt", ret_entry->path);
+ cl_assert_equal_i(GIT_FILEMODE_LINK, ret_entry->mode);
+
+ /* trees are rejected */
+ new_entry.path = "invalid_mode.txt";
+ new_entry.mode = GIT_FILEMODE_TREE;
+
+ cl_git_fail(git_index_add_frombuffer(index,
+ &new_entry, content, strlen(content)));
+ cl_assert_equal_p(NULL, git_index_get_bypath(index, "invalid_mode.txt", 0));
+
+ /* submodules are rejected */
+ new_entry.path = "invalid_mode.txt";
+ new_entry.mode = GIT_FILEMODE_COMMIT;
+
+ cl_git_fail(git_index_add_frombuffer(index,
+ &new_entry, content, strlen(content)));
+ cl_assert_equal_p(NULL, git_index_get_bypath(index, "invalid_mode.txt", 0));
+
+ git_index_free(index);
+}