Skip to content

Commit 4d0e899

Browse files
committed
Merge branch 'am/real-path-fix'
The real_path() convenience function can easily be misused; with a bit of code refactoring in the callers' side, its use has been eliminated. * am/real-path-fix: get_superproject_working_tree(): return strbuf real_path_if_valid(): remove unsafe API real_path: remove unsafe API set_git_dir: fix crash when used with real_path()
2 parents 38afd2d + 49d3c4b commit 4d0e899

File tree

16 files changed

+107
-75
lines changed

16 files changed

+107
-75
lines changed

abspath.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -202,22 +202,6 @@ char *strbuf_realpath(struct strbuf *resolved, const char *path,
202202
return retval;
203203
}
204204

205-
/*
206-
* Resolve `path` into an absolute, cleaned-up path. The return value
207-
* comes from a shared buffer.
208-
*/
209-
const char *real_path(const char *path)
210-
{
211-
static struct strbuf realpath = STRBUF_INIT;
212-
return strbuf_realpath(&realpath, path, 1);
213-
}
214-
215-
const char *real_path_if_valid(const char *path)
216-
{
217-
static struct strbuf realpath = STRBUF_INIT;
218-
return strbuf_realpath(&realpath, path, 0);
219-
}
220-
221205
char *real_pathdup(const char *path, int die_on_error)
222206
{
223207
struct strbuf realpath = STRBUF_INIT;
@@ -233,7 +217,7 @@ char *real_pathdup(const char *path, int die_on_error)
233217

234218
/*
235219
* Use this to get an absolute path from a relative one. If you want
236-
* to resolve links, you should use real_path.
220+
* to resolve links, you should use strbuf_realpath.
237221
*/
238222
const char *absolute_path(const char *path)
239223
{

builtin/clone.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
420420
struct dir_iterator *iter;
421421
int iter_status;
422422
unsigned int flags;
423+
struct strbuf realpath = STRBUF_INIT;
423424

424425
mkdir_if_missing(dest->buf, 0777);
425426

@@ -454,7 +455,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
454455
if (unlink(dest->buf) && errno != ENOENT)
455456
die_errno(_("failed to unlink '%s'"), dest->buf);
456457
if (!option_no_hardlinks) {
457-
if (!link(real_path(src->buf), dest->buf))
458+
strbuf_realpath(&realpath, src->buf, 1);
459+
if (!link(realpath.buf, dest->buf))
458460
continue;
459461
if (option_local > 0)
460462
die_errno(_("failed to create link '%s'"), dest->buf);
@@ -468,6 +470,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
468470
strbuf_setlen(src, src_len);
469471
die(_("failed to iterate over '%s'"), src->buf);
470472
}
473+
474+
strbuf_release(&realpath);
471475
}
472476

473477
static void clone_local(const char *src_repo, const char *dest_repo)

builtin/commit-graph.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,17 @@ static struct object_directory *find_odb(struct repository *r,
3939
{
4040
struct object_directory *odb;
4141
char *obj_dir_real = real_pathdup(obj_dir, 1);
42+
struct strbuf odb_path_real = STRBUF_INIT;
4243

4344
prepare_alt_odb(r);
4445
for (odb = r->objects->odb; odb; odb = odb->next) {
45-
if (!strcmp(obj_dir_real, real_path(odb->path)))
46+
strbuf_realpath(&odb_path_real, odb->path, 1);
47+
if (!strcmp(obj_dir_real, odb_path_real.buf))
4648
break;
4749
}
4850

4951
free(obj_dir_real);
52+
strbuf_release(&odb_path_real);
5053

5154
if (!odb)
5255
die(_("could not find object directory matching %s"), obj_dir);

builtin/init-db.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,12 @@ int init_db(const char *git_dir, const char *real_git_dir,
356356
if (!exist_ok && !stat(real_git_dir, &st))
357357
die(_("%s already exists"), real_git_dir);
358358

359-
set_git_dir(real_path(real_git_dir));
359+
set_git_dir(real_git_dir, 1);
360360
git_dir = get_git_dir();
361361
separate_git_dir(git_dir, original_git_dir);
362362
}
363363
else {
364-
set_git_dir(real_path(git_dir));
364+
set_git_dir(git_dir, 1);
365365
git_dir = get_git_dir();
366366
}
367367
startup_info->have_repository = 1;

builtin/rev-parse.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -808,9 +808,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
808808
continue;
809809
}
810810
if (!strcmp(arg, "--show-superproject-working-tree")) {
811-
const char *superproject = get_superproject_working_tree();
812-
if (superproject)
813-
puts(superproject);
811+
struct strbuf superproject = STRBUF_INIT;
812+
if (get_superproject_working_tree(&superproject))
813+
puts(superproject.buf);
814+
strbuf_release(&superproject);
814815
continue;
815816
}
816817
if (!strcmp(arg, "--show-prefix")) {
@@ -857,7 +858,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
857858
if (!gitdir && !prefix)
858859
gitdir = ".git";
859860
if (gitdir) {
860-
puts(real_path(gitdir));
861+
struct strbuf realpath = STRBUF_INIT;
862+
strbuf_realpath(&realpath, gitdir, 1);
863+
puts(realpath.buf);
864+
strbuf_release(&realpath);
861865
continue;
862866
}
863867
}

builtin/worktree.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static int add_worktree(const char *path, const char *refname,
258258
const struct add_opts *opts)
259259
{
260260
struct strbuf sb_git = STRBUF_INIT, sb_repo = STRBUF_INIT;
261-
struct strbuf sb = STRBUF_INIT;
261+
struct strbuf sb = STRBUF_INIT, realpath = STRBUF_INIT;
262262
const char *name;
263263
struct child_process cp = CHILD_PROCESS_INIT;
264264
struct argv_array child_env = ARGV_ARRAY_INIT;
@@ -330,9 +330,11 @@ static int add_worktree(const char *path, const char *refname,
330330

331331
strbuf_reset(&sb);
332332
strbuf_addf(&sb, "%s/gitdir", sb_repo.buf);
333-
write_file(sb.buf, "%s", real_path(sb_git.buf));
333+
strbuf_realpath(&realpath, sb_git.buf, 1);
334+
write_file(sb.buf, "%s", realpath.buf);
335+
strbuf_realpath(&realpath, get_git_common_dir(), 1);
334336
write_file(sb_git.buf, "gitdir: %s/worktrees/%s",
335-
real_path(get_git_common_dir()), name);
337+
realpath.buf, name);
336338
/*
337339
* This is to keep resolve_ref() happy. We need a valid HEAD
338340
* or is_git_directory() will reject the directory. Any value which
@@ -418,6 +420,7 @@ static int add_worktree(const char *path, const char *refname,
418420
strbuf_release(&sb_repo);
419421
strbuf_release(&sb_git);
420422
strbuf_release(&sb_name);
423+
strbuf_release(&realpath);
421424
return ret;
422425
}
423426

cache.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ const char *get_git_common_dir(void);
543543
char *get_object_directory(void);
544544
char *get_index_file(void);
545545
char *get_graft_file(struct repository *r);
546-
void set_git_dir(const char *path);
546+
void set_git_dir(const char *path, int make_realpath);
547547
int get_common_dir_noenv(struct strbuf *sb, const char *gitdir);
548548
int get_common_dir(struct strbuf *sb, const char *gitdir);
549549
const char *get_git_namespace(void);
@@ -1314,8 +1314,6 @@ static inline int is_absolute_path(const char *path)
13141314
int is_directory(const char *);
13151315
char *strbuf_realpath(struct strbuf *resolved, const char *path,
13161316
int die_on_error);
1317-
const char *real_path(const char *path);
1318-
const char *real_path_if_valid(const char *path);
13191317
char *real_pathdup(const char *path, int die_on_error);
13201318
const char *absolute_path(const char *path);
13211319
char *absolute_pathdup(const char *path);

editor.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ static int launch_specified_editor(const char *editor, const char *path,
5454
return error("Terminal is dumb, but EDITOR unset");
5555

5656
if (strcmp(editor, ":")) {
57-
const char *args[] = { editor, real_path(path), NULL };
57+
struct strbuf realpath = STRBUF_INIT;
58+
const char *args[] = { editor, NULL, NULL };
5859
struct child_process p = CHILD_PROCESS_INIT;
5960
int ret, sig;
6061
int print_waiting_for_editor = advice_waiting_for_editor && isatty(2);
@@ -75,16 +76,22 @@ static int launch_specified_editor(const char *editor, const char *path,
7576
fflush(stderr);
7677
}
7778

79+
strbuf_realpath(&realpath, path, 1);
80+
args[1] = realpath.buf;
81+
7882
p.argv = args;
7983
p.env = env;
8084
p.use_shell = 1;
8185
p.trace2_child_class = "editor";
82-
if (start_command(&p) < 0)
86+
if (start_command(&p) < 0) {
87+
strbuf_release(&realpath);
8388
return error("unable to start editor '%s'", editor);
89+
}
8490

8591
sigchain_push(SIGINT, SIG_IGN);
8692
sigchain_push(SIGQUIT, SIG_IGN);
8793
ret = finish_command(&p);
94+
strbuf_release(&realpath);
8895
sig = ret - 128;
8996
sigchain_pop(SIGINT);
9097
sigchain_pop(SIGQUIT);

environment.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,11 @@ static int git_work_tree_initialized;
254254
*/
255255
void set_git_work_tree(const char *new_work_tree)
256256
{
257+
struct strbuf realpath = STRBUF_INIT;
258+
257259
if (git_work_tree_initialized) {
258-
new_work_tree = real_path(new_work_tree);
260+
strbuf_realpath(&realpath, new_work_tree, 1);
261+
new_work_tree = realpath.buf;
259262
if (strcmp(new_work_tree, the_repository->worktree))
260263
die("internal error: work tree has already been set\n"
261264
"Current worktree: %s\nNew worktree: %s",
@@ -264,6 +267,8 @@ void set_git_work_tree(const char *new_work_tree)
264267
}
265268
git_work_tree_initialized = 1;
266269
repo_set_worktree(the_repository, new_work_tree);
270+
271+
strbuf_release(&realpath);
267272
}
268273

269274
const char *get_git_work_tree(void)
@@ -345,11 +350,20 @@ static void update_relative_gitdir(const char *name,
345350
free(path);
346351
}
347352

348-
void set_git_dir(const char *path)
353+
void set_git_dir(const char *path, int make_realpath)
349354
{
355+
struct strbuf realpath = STRBUF_INIT;
356+
357+
if (make_realpath) {
358+
strbuf_realpath(&realpath, path, 1);
359+
path = realpath.buf;
360+
}
361+
350362
set_git_dir_1(path);
351363
if (!is_absolute_path(path))
352364
chdir_notify_register(NULL, update_relative_gitdir, NULL);
365+
366+
strbuf_release(&realpath);
353367
}
354368

355369
const char *get_log_output_encoding(void)

path.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ static struct passwd *getpw_str(const char *username, size_t len)
723723
* then it is a newly allocated string. Returns NULL on getpw failure or
724724
* if path is NULL.
725725
*
726-
* If real_home is true, real_path($HOME) is used in the expansion.
726+
* If real_home is true, strbuf_realpath($HOME) is used in the expansion.
727727
*/
728728
char *expand_user_path(const char *path, int real_home)
729729
{
@@ -850,7 +850,7 @@ const char *enter_repo(const char *path, int strict)
850850
}
851851

852852
if (is_git_directory(".")) {
853-
set_git_dir(".");
853+
set_git_dir(".", 0);
854854
check_repository_format();
855855
return path;
856856
}

0 commit comments

Comments
 (0)