summaryrefslogtreecommitdiff
path: root/src/index.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@github.com>2016-02-23 18:29:16 -0500
committerEdward Thomson <ethomson@github.com>2016-02-28 18:54:39 -0500
commit6ddf533afca5e25b7c532b4c164ae66e06f9c1c2 (patch)
tree8b712ec3334211e5d391b3933ce5897ebd627695 /src/index.c
parent2bbc7d3e564ed262e9555ea4fd081ece5ceb3bff (diff)
downloadlibgit2-6ddf533afca5e25b7c532b4c164ae66e06f9c1c2.tar.gz
git_index_add: validate objects in index entries (optionally)
When `GIT_OPT_ENABLE_STRICT_OBJECT_CREATION` is turned on, validate the index entries given to `git_index_add`.
Diffstat (limited to 'src/index.c')
-rw-r--r--src/index.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/src/index.c b/src/index.c
index 5704432ae..b97f8091d 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1245,17 +1245,22 @@ static void index_existing_and_best(
* it, then it will return an error **and also free the entry**. When
* it replaces an existing entry, it will update the entry_ptr with the
* actual entry in the index (and free the passed in one).
+ *
* trust_path is whether we use the given path, or whether (on case
* insensitive systems only) we try to canonicalize the given path to
* be within an existing directory.
+ *
* trust_mode is whether we trust the mode in entry_ptr.
+ *
+ * trust_id is whether we trust the id or it should be validated.
*/
static int index_insert(
git_index *index,
git_index_entry **entry_ptr,
int replace,
bool trust_path,
- bool trust_mode)
+ bool trust_mode,
+ bool trust_id)
{
int error = 0;
size_t path_length, position;
@@ -1288,6 +1293,15 @@ static int index_insert(
if (!trust_path)
error = canonicalize_directory_path(index, entry, best);
+ /* ensure that the given id exists (unless it's a submodule) */
+ if (!error && !trust_id && INDEX_OWNER(index) &&
+ (entry->mode & GIT_FILEMODE_COMMIT) != GIT_FILEMODE_COMMIT) {
+
+ if (!git_object__is_valid(INDEX_OWNER(index), &entry->id,
+ git_object__type_from_filemode(entry->mode)))
+ error = -1;
+ }
+
/* look for tree / blob name collisions, removing conflicts if requested */
if (!error)
error = check_file_directory_collision(index, entry, position, replace);
@@ -1395,7 +1409,7 @@ int git_index_add_frombuffer(
git_oid_cpy(&entry->id, &id);
entry->file_size = len;
- if ((error = index_insert(index, &entry, 1, true, true)) < 0)
+ if ((error = index_insert(index, &entry, 1, true, true, true)) < 0)
return error;
/* Adding implies conflict was resolved, move conflict entries to REUC */
@@ -1454,7 +1468,7 @@ int git_index_add_bypath(git_index *index, const char *path)
assert(index && path);
if ((ret = index_entry_init(&entry, index, path)) == 0)
- ret = index_insert(index, &entry, 1, false, false);
+ ret = index_insert(index, &entry, 1, false, false, true);
/* If we were given a directory, let's see if it's a submodule */
if (ret < 0 && ret != GIT_EDIRECTORY)
@@ -1480,7 +1494,7 @@ int git_index_add_bypath(git_index *index, const char *path)
if ((ret = add_repo_as_submodule(&entry, index, path)) < 0)
return ret;
- if ((ret = index_insert(index, &entry, 1, false, false)) < 0)
+ if ((ret = index_insert(index, &entry, 1, false, false, true)) < 0)
return ret;
} else if (ret < 0) {
return ret;
@@ -1569,7 +1583,7 @@ int git_index_add(git_index *index, const git_index_entry *source_entry)
}
if ((ret = index_entry_dup(&entry, index, source_entry)) < 0 ||
- (ret = index_insert(index, &entry, 1, true, true)) < 0)
+ (ret = index_insert(index, &entry, 1, true, true, false)) < 0)
return ret;
git_tree_cache_invalidate_path(index->tree, entry->path);
@@ -1731,7 +1745,7 @@ int git_index_conflict_add(git_index *index,
/* Make sure stage is correct */
GIT_IDXENTRY_STAGE_SET(entries[i], i + 1);
- if ((ret = index_insert(index, &entries[i], 1, true, true)) < 0)
+ if ((ret = index_insert(index, &entries[i], 1, true, true, false)) < 0)
goto on_error;
entries[i] = NULL; /* don't free if later entry fails */