summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2017-03-16 20:56:43 (GMT)
committerJunio C Hamano <gitster@pobox.com>2017-03-16 20:57:00 (GMT)
commit2846ef3e27ff0e34812dad788b706f0a1e5b5e80 (patch)
tree92b0e57a6b599bd3a4e255d6bb67b7eff2091681
parentf989ac276d310564364482979a78b83d113c4044 (diff)
parentce83eadd9a2c63db6263df91933da1b1b865d26a (diff)
downloadgit-2846ef3e27ff0e34812dad788b706f0a1e5b5e80.zip
git-2846ef3e27ff0e34812dad788b706f0a1e5b5e80.tar.gz
git-2846ef3e27ff0e34812dad788b706f0a1e5b5e80.tar.bz2
Merge branch 'js/realpath-pathdup-fix' into maint
Git v2.12 was shipped with an embarrassing breakage where various operations that verify paths given from the user stopped dying when seeing an issue, and instead later triggering segfault. ... and then to down to 'maint'. * js/realpath-pathdup-fix: real_pathdup(): fix callsites that wanted it to die on error t1501: demonstrate NULL pointer access with invalid GIT_WORK_TREE
-rw-r--r--abspath.c4
-rw-r--r--builtin/init-db.c6
-rw-r--r--cache.h2
-rw-r--r--dir.c4
-rw-r--r--environment.c2
-rw-r--r--setup.c4
-rw-r--r--submodule.c10
-rwxr-xr-xt/t1501-work-tree.sh8
-rw-r--r--transport.c2
-rw-r--r--worktree.c2
10 files changed, 26 insertions, 18 deletions
diff --git a/abspath.c b/abspath.c
index 2f0c26e..b02e068 100644
--- a/abspath.c
+++ b/abspath.c
@@ -214,12 +214,12 @@ const char *real_path_if_valid(const char *path)
return strbuf_realpath(&realpath, path, 0);
}
-char *real_pathdup(const char *path)
+char *real_pathdup(const char *path, int die_on_error)
{
struct strbuf realpath = STRBUF_INIT;
char *retval = NULL;
- if (strbuf_realpath(&realpath, path, 0))
+ if (strbuf_realpath(&realpath, path, die_on_error))
retval = strbuf_detach(&realpath, NULL);
strbuf_release(&realpath);
diff --git a/builtin/init-db.c b/builtin/init-db.c
index 1d4d6a0..8a6acb0 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -338,7 +338,7 @@ int init_db(const char *git_dir, const char *real_git_dir,
{
int reinit;
int exist_ok = flags & INIT_DB_EXIST_OK;
- char *original_git_dir = real_pathdup(git_dir);
+ char *original_git_dir = real_pathdup(git_dir, 1);
if (real_git_dir) {
struct stat st;
@@ -489,7 +489,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
if (real_git_dir && !is_absolute_path(real_git_dir))
- real_git_dir = real_pathdup(real_git_dir);
+ real_git_dir = real_pathdup(real_git_dir, 1);
if (argc == 1) {
int mkdir_tried = 0;
@@ -560,7 +560,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
const char *git_dir_parent = strrchr(git_dir, '/');
if (git_dir_parent) {
char *rel = xstrndup(git_dir, git_dir_parent - git_dir);
- git_work_tree_cfg = real_pathdup(rel);
+ git_work_tree_cfg = real_pathdup(rel, 1);
free(rel);
}
if (!git_work_tree_cfg)
diff --git a/cache.h b/cache.h
index 61fc86e..c26c45f 100644
--- a/cache.h
+++ b/cache.h
@@ -1109,7 +1109,7 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
int die_on_error);
const char *real_path(const char *path);
const char *real_path_if_valid(const char *path);
-char *real_pathdup(const char *path);
+char *real_pathdup(const char *path, int die_on_error);
const char *absolute_path(const char *path);
char *absolute_pathdup(const char *path);
const char *remove_leading_path(const char *in, const char *prefix);
diff --git a/dir.c b/dir.c
index 4541f9e..aeeb5ce 100644
--- a/dir.c
+++ b/dir.c
@@ -2730,8 +2730,8 @@ void connect_work_tree_and_git_dir(const char *work_tree_, const char *git_dir_)
{
struct strbuf file_name = STRBUF_INIT;
struct strbuf rel_path = STRBUF_INIT;
- char *git_dir = real_pathdup(git_dir_);
- char *work_tree = real_pathdup(work_tree_);
+ char *git_dir = real_pathdup(git_dir_, 1);
+ char *work_tree = real_pathdup(work_tree_, 1);
/* Update gitfile */
strbuf_addf(&file_name, "%s/.git", work_tree);
diff --git a/environment.c b/environment.c
index c07fb17..42dc310 100644
--- a/environment.c
+++ b/environment.c
@@ -259,7 +259,7 @@ void set_git_work_tree(const char *new_work_tree)
return;
}
git_work_tree_initialized = 1;
- work_tree = real_pathdup(new_work_tree);
+ work_tree = real_pathdup(new_work_tree, 1);
}
const char *get_git_work_tree(void)
diff --git a/setup.c b/setup.c
index 967f289..6b48cb9 100644
--- a/setup.c
+++ b/setup.c
@@ -698,7 +698,7 @@ static const char *setup_discovered_git_dir(const char *gitdir,
/* --work-tree is set without --git-dir; use discovered one */
if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
if (offset != cwd->len && !is_absolute_path(gitdir))
- gitdir = real_pathdup(gitdir);
+ gitdir = real_pathdup(gitdir, 1);
if (chdir(cwd->buf))
die_errno("Could not come back to cwd");
return setup_explicit_git_dir(gitdir, cwd, nongit_ok);
@@ -806,7 +806,7 @@ static int canonicalize_ceiling_entry(struct string_list_item *item,
/* Keep entry but do not canonicalize it */
return 1;
} else {
- char *real_path = real_pathdup(ceil);
+ char *real_path = real_pathdup(ceil, 0);
if (!real_path) {
return 0;
}
diff --git a/submodule.c b/submodule.c
index 3b98766..0a2831d 100644
--- a/submodule.c
+++ b/submodule.c
@@ -1403,7 +1403,7 @@ static void relocate_single_git_dir_into_superproject(const char *prefix,
/* If it is an actual gitfile, it doesn't need migration. */
return;
- real_old_git_dir = real_pathdup(old_git_dir);
+ real_old_git_dir = real_pathdup(old_git_dir, 1);
sub = submodule_from_path(null_sha1, path);
if (!sub)
@@ -1412,7 +1412,7 @@ static void relocate_single_git_dir_into_superproject(const char *prefix,
new_git_dir = git_path("modules/%s", sub->name);
if (safe_create_leading_directories_const(new_git_dir) < 0)
die(_("could not create directory '%s'"), new_git_dir);
- real_new_git_dir = real_pathdup(new_git_dir);
+ real_new_git_dir = real_pathdup(new_git_dir, 1);
if (!prefix)
prefix = get_super_prefix();
@@ -1472,14 +1472,14 @@ void absorb_git_dir_into_superproject(const char *prefix,
new_git_dir = git_path("modules/%s", sub->name);
if (safe_create_leading_directories_const(new_git_dir) < 0)
die(_("could not create directory '%s'"), new_git_dir);
- real_new_git_dir = real_pathdup(new_git_dir);
+ real_new_git_dir = real_pathdup(new_git_dir, 1);
connect_work_tree_and_git_dir(path, real_new_git_dir);
free(real_new_git_dir);
} else {
/* Is it already absorbed into the superprojects git dir? */
- char *real_sub_git_dir = real_pathdup(sub_git_dir);
- char *real_common_git_dir = real_pathdup(get_git_common_dir());
+ char *real_sub_git_dir = real_pathdup(sub_git_dir, 1);
+ char *real_common_git_dir = real_pathdup(get_git_common_dir(), 1);
if (!starts_with(real_sub_git_dir, real_common_git_dir))
relocate_single_git_dir_into_superproject(prefix, path);
diff --git a/t/t1501-work-tree.sh b/t/t1501-work-tree.sh
index cc5b870..b06210e 100755
--- a/t/t1501-work-tree.sh
+++ b/t/t1501-work-tree.sh
@@ -423,4 +423,12 @@ test_expect_success '$GIT_WORK_TREE overrides $GIT_DIR/common' '
)
'
+test_expect_success 'error out gracefully on invalid $GIT_WORK_TREE' '
+ (
+ GIT_WORK_TREE=/.invalid/work/tree &&
+ export GIT_WORK_TREE &&
+ test_expect_code 128 git rev-parse
+ )
+'
+
test_done
diff --git a/transport.c b/transport.c
index d72e089..b6c5652 100644
--- a/transport.c
+++ b/transport.c
@@ -1221,7 +1221,7 @@ static int refs_from_alternate_cb(struct alternate_object_database *e,
const struct ref *extra;
struct alternate_refs_data *cb = data;
- other = real_pathdup(e->path);
+ other = real_pathdup(e->path, 1);
len = strlen(other);
while (other[len-1] == '/')
diff --git a/worktree.c b/worktree.c
index d633761..0486e31 100644
--- a/worktree.c
+++ b/worktree.c
@@ -255,7 +255,7 @@ struct worktree *find_worktree(struct worktree **list,
return wt;
arg = prefix_filename(prefix, strlen(prefix), arg);
- path = real_pathdup(arg);
+ path = real_pathdup(arg, 1);
for (; *list; list++)
if (!fspathcmp(path, real_path((*list)->path)))
break;