summaryrefslogtreecommitdiff
path: root/src/reader.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2018-11-04 11:26:42 +0000
committerEdward Thomson <ethomson@edwardthomson.com>2018-11-05 15:53:59 +0000
commit12f9ac17a63986f64799098bfd3b18c91b9c08a1 (patch)
tree9e07f6e28cc2e1c3717d8ad66a543781c258839c /src/reader.c
parentb73a42f6aabe3f00ac01d9843c053c2393573d2b (diff)
downloadlibgit2-12f9ac17a63986f64799098bfd3b18c91b9c08a1.tar.gz
apply: validate unchanged mode when applying both
When applying to both the index and the working directory, ensure that the working directory's mode matches the index's mode. It's not sufficient to look only at the hashed object id to determine that the file is unchanged, git also takes the mode into account.
Diffstat (limited to 'src/reader.c')
-rw-r--r--src/reader.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/src/reader.c b/src/reader.c
index 5de731bea..026bc2b51 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -79,6 +79,8 @@ static int workdir_reader_read(
{
workdir_reader *reader = (workdir_reader *)_reader;
git_buf path = GIT_BUF_INIT;
+ struct stat st;
+ git_filemode_t filemode;
git_filter_list *filters = NULL;
const git_index_entry *idx_entry;
git_oid id;
@@ -88,6 +90,16 @@ static int workdir_reader_read(
git_repository_workdir(reader->repo), filename)) < 0)
goto done;
+ if ((error = p_lstat(path.ptr, &st)) < 0) {
+ if (error == -1 && errno == ENOENT)
+ error = GIT_ENOTFOUND;
+
+ giterr_set(GITERR_OS, "could not stat '%s'", path.ptr);
+ goto done;
+ }
+
+ filemode = git_futils_canonical_mode(st.st_mode);
+
/*
* Patch application - for example - uses the filtered version of
* the working directory data to match git. So we will run the
@@ -108,6 +120,7 @@ static int workdir_reader_read(
if (reader->index) {
if (!(idx_entry = git_index_get_bypath(reader->index, filename, 0)) ||
+ filemode != idx_entry->mode ||
!git_oid_equal(&id, &idx_entry->id)) {
error = GIT_READER_MISMATCH;
goto done;