mirror of
https://github.com/git/git.git
synced 2024-11-24 10:26:17 +08:00
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
This commit is contained in:
commit
2846ef3e27
@ -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);
|
||||
|
@ -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)
|
||||
|
2
cache.h
2
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);
|
||||
|
4
dir.c
4
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);
|
||||
|
@ -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)
|
||||
|
4
setup.c
4
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;
|
||||
}
|
||||
|
10
submodule.c
10
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);
|
||||
|
@ -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
|
||||
|
@ -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] == '/')
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user