summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2018-05-22 16:13:47 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2018-05-23 08:47:08 +0200
commita7168b47ee494c52ffe850784be9ad996f80441a (patch)
tree290ea63c787104e9bdc36eaf0d0ef0316f6e2abc /src
parent58ff913a13b840f1f6ee35e71e9d1de3470904ad (diff)
downloadlibgit2-a7168b47ee494c52ffe850784be9ad996f80441a.tar.gz
path: reject .gitmodules as a symlink
Any part of the library which asks the question can pass in the mode to have it checked against `.gitmodules` being a symlink. This is particularly relevant for adding entries to the index from the worktree and for checking out files.
Diffstat (limited to 'src')
-rw-r--r--src/checkout.c4
-rw-r--r--src/index.c9
-rw-r--r--src/path.c24
-rw-r--r--src/path.h1
-rw-r--r--src/refdb_fs.c4
-rw-r--r--src/submodule.c2
-rw-r--r--src/tree.c2
7 files changed, 28 insertions, 18 deletions
diff --git a/src/checkout.c b/src/checkout.c
index 8ff5d897b..debdbe95b 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -1276,14 +1276,14 @@ static int checkout_verify_paths(
unsigned int flags = GIT_PATH_REJECT_WORKDIR_DEFAULTS;
if (action & CHECKOUT_ACTION__REMOVE) {
- if (!git_path_isvalid(repo, delta->old_file.path, flags)) {
+ if (!git_path_isvalid(repo, delta->old_file.path, delta->old_file.mode, flags)) {
giterr_set(GITERR_CHECKOUT, "cannot remove invalid path '%s'", delta->old_file.path);
return -1;
}
}
if (action & ~CHECKOUT_ACTION__REMOVE) {
- if (!git_path_isvalid(repo, delta->new_file.path, flags)) {
+ if (!git_path_isvalid(repo, delta->new_file.path, delta->new_file.mode, flags)) {
giterr_set(GITERR_CHECKOUT, "cannot checkout to invalid path '%s'", delta->new_file.path);
return -1;
}
diff --git a/src/index.c b/src/index.c
index 4a087132a..09313ebed 100644
--- a/src/index.c
+++ b/src/index.c
@@ -890,8 +890,7 @@ static int index_entry_create(
size_t pathlen = strlen(path), alloclen;
struct entry_internal *entry;
unsigned int path_valid_flags = GIT_PATH_REJECT_INDEX_DEFAULTS;
-
- GIT_UNUSED(st);
+ uint16_t mode = 0;
/* always reject placing `.git` in the index and directory traversal.
* when requested, disallow platform-specific filenames and upgrade to
@@ -899,8 +898,10 @@ static int index_entry_create(
*/
if (from_workdir)
path_valid_flags |= GIT_PATH_REJECT_WORKDIR_DEFAULTS;
+ if (st)
+ mode = st->st_mode;
- if (!git_path_isvalid(repo, path, path_valid_flags)) {
+ if (!git_path_isvalid(repo, path, mode, path_valid_flags)) {
giterr_set(GITERR_INDEX, "invalid path: '%s'", path);
return -1;
}
@@ -925,7 +926,7 @@ static int index_entry_init(
{
int error = 0;
git_index_entry *entry = NULL;
- git_buf path;
+ git_buf path = GIT_BUF_INIT;
struct stat st;
git_oid oid;
git_repository *repo;
diff --git a/src/path.c b/src/path.c
index 0f410cba4..def669aeb 100644
--- a/src/path.c
+++ b/src/path.c
@@ -1712,6 +1712,7 @@ static bool verify_component(
git_repository *repo,
const char *component,
size_t len,
+ uint16_t mode,
unsigned int flags)
{
if (len == 0)
@@ -1744,13 +1745,19 @@ static bool verify_component(
return false;
}
- if (flags & GIT_PATH_REJECT_DOT_GIT_HFS &&
- !verify_dotgit_hfs(component, len))
- return false;
+ if (flags & GIT_PATH_REJECT_DOT_GIT_HFS) {
+ if (!verify_dotgit_hfs(component, len))
+ return false;
+ if (S_ISLNK(mode) && git_path_is_hfs_dotgit_modules(component, len))
+ return false;
+ }
- if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS &&
- !verify_dotgit_ntfs(repo, component, len))
- return false;
+ if (flags & GIT_PATH_REJECT_DOT_GIT_NTFS) {
+ if (!verify_dotgit_ntfs(repo, component, len))
+ return false;
+ if (S_ISLNK(mode) && git_path_is_ntfs_dotgit_modules(component, len))
+ return false;
+ }
/* don't bother rerunning the `.git` test if we ran the HFS or NTFS
* specific tests, they would have already rejected `.git`.
@@ -1801,6 +1808,7 @@ GIT_INLINE(unsigned int) dotgit_flags(
bool git_path_isvalid(
git_repository *repo,
const char *path,
+ uint16_t mode,
unsigned int flags)
{
const char *start, *c;
@@ -1814,14 +1822,14 @@ bool git_path_isvalid(
return false;
if (*c == '/') {
- if (!verify_component(repo, start, (c - start), flags))
+ if (!verify_component(repo, start, (c - start), mode, flags))
return false;
start = c+1;
}
}
- return verify_component(repo, start, (c - start), flags);
+ return verify_component(repo, start, (c - start), mode, flags);
}
int git_path_normalize_slashes(git_buf *out, const char *path)
diff --git a/src/path.h b/src/path.h
index 698cf4b55..fd515c8a2 100644
--- a/src/path.h
+++ b/src/path.h
@@ -637,6 +637,7 @@ extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or
extern bool git_path_isvalid(
git_repository *repo,
const char *path,
+ uint16_t mode,
unsigned int flags);
/**
diff --git a/src/refdb_fs.c b/src/refdb_fs.c
index 9432df8c9..83174e8cd 100644
--- a/src/refdb_fs.c
+++ b/src/refdb_fs.c
@@ -744,7 +744,7 @@ static int loose_lock(git_filebuf *file, refdb_fs_backend *backend, const char *
assert(file && backend && name);
- if (!git_path_isvalid(backend->repo, name, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
+ if (!git_path_isvalid(backend->repo, name, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
giterr_set(GITERR_INVALID, "invalid reference name '%s'", name);
return GIT_EINVALIDSPEC;
}
@@ -1742,7 +1742,7 @@ static int lock_reflog(git_filebuf *file, refdb_fs_backend *backend, const char
repo = backend->repo;
- if (!git_path_isvalid(backend->repo, refname, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
+ if (!git_path_isvalid(backend->repo, refname, 0, GIT_PATH_REJECT_FILESYSTEM_DEFAULTS)) {
giterr_set(GITERR_INVALID, "invalid reference name '%s'", refname);
return GIT_EINVALIDSPEC;
}
diff --git a/src/submodule.c b/src/submodule.c
index 233957e43..0bc580876 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -382,7 +382,7 @@ int git_submodule_name_is_valid(const git_repository *repo, const char *name, in
}
/* FIXME: Un-consting it to reduce the amount of diff */
- isvalid = git_path_isvalid((git_repository *)repo, buf.ptr, flags);
+ isvalid = git_path_isvalid((git_repository *)repo, buf.ptr, 0, flags);
git_buf_free(&buf);
return isvalid;
diff --git a/src/tree.c b/src/tree.c
index fdf36f850..12622975a 100644
--- a/src/tree.c
+++ b/src/tree.c
@@ -54,7 +54,7 @@ GIT_INLINE(git_filemode_t) normalize_filemode(git_filemode_t filemode)
static int valid_entry_name(git_repository *repo, const char *filename)
{
return *filename != '\0' &&
- git_path_isvalid(repo, filename,
+ git_path_isvalid(repo, filename, 0,
GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT | GIT_PATH_REJECT_SLASH);
}