Skip to content

Commit 8b1981d

Browse files
committed
Merge branch 'ar/maint-mksnpath' into maint
* ar/maint-mksnpath: Use git_pathdup instead of xstrdup(git_path(...)) git_pathdup: returns xstrdup-ed copy of the formatted path Fix potentially dangerous use of git_path in ref.c Add git_snpath: a .git path formatting routine with output buffer Fix potentially dangerous uses of mkpath and git_path Fix mkpath abuse in dwim_ref and dwim_log of sha1_name.c Add mksnpath which allows you to specify the output buffer Conflicts: builtin-revert.c rerere.c
2 parents 3b8572a + a4f34cb commit 8b1981d

13 files changed

+84
-19
lines changed

builtin-apply.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2850,8 +2850,8 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
28502850
unsigned int nr = getpid();
28512851

28522852
for (;;) {
2853-
const char *newpath;
2854-
newpath = mkpath("%s~%u", path, nr);
2853+
char newpath[PATH_MAX];
2854+
mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
28552855
if (!try_create_file(newpath, mode, buf, size)) {
28562856
if (!rename(newpath, path))
28572857
return;

builtin-config.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static int get_value(const char* key_, const char* regex_)
8484
local = config_exclusive_filename;
8585
if (!local) {
8686
const char *home = getenv("HOME");
87-
local = repo_config = xstrdup(git_path("config"));
87+
local = repo_config = git_pathdup("config");
8888
if (git_config_global() && home)
8989
global = xstrdup(mkpath("%s/.gitconfig", home));
9090
if (git_config_system())

builtin-reflog.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,11 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
277277
lock = lock_any_ref_for_update(ref, sha1, 0);
278278
if (!lock)
279279
return error("cannot lock ref '%s'", ref);
280-
log_file = xstrdup(git_path("logs/%s", ref));
280+
log_file = git_pathdup("logs/%s", ref);
281281
if (!file_exists(log_file))
282282
goto finish;
283283
if (!cmd->dry_run) {
284-
newlog_path = xstrdup(git_path("logs/%s.lock", ref));
284+
newlog_path = git_pathdup("logs/%s.lock", ref);
285285
cb.newlog = fopen(newlog_path, "w");
286286
}
287287

builtin-revert.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
269269
int i;
270270
char *oneline, *reencoded_message = NULL;
271271
const char *message, *encoding;
272-
char *defmsg = xstrdup(git_path("MERGE_MSG"));
272+
char *defmsg = git_pathdup("MERGE_MSG");
273273

274274
git_config(git_default_config, NULL);
275275
me = action == REVERT ? "revert" : "cherry-pick";

builtin-tag.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ static void create_tag(const unsigned char *object, const char *tag,
283283
int fd;
284284

285285
/* write the template message before editing: */
286-
path = xstrdup(git_path("TAG_EDITMSG"));
286+
path = git_pathdup("TAG_EDITMSG");
287287
fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
288288
if (fd < 0)
289289
die("could not create file '%s': %s",

cache.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,13 @@ extern int check_repository_format(void);
484484
#define DATA_CHANGED 0x0020
485485
#define TYPE_CHANGED 0x0040
486486

487+
extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
488+
__attribute__((format (printf, 3, 4)));
489+
extern char *git_snpath(char *buf, size_t n, const char *fmt, ...)
490+
__attribute__((format (printf, 3, 4)));
491+
extern char *git_pathdup(const char *fmt, ...)
492+
__attribute__((format (printf, 1, 2)));
493+
487494
/* Return a statically allocated filename matching the sha1 signature */
488495
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
489496
extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));

config.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ int git_config(config_fn_t fn, void *data)
630630
free(user_config);
631631
}
632632

633-
repo_config = xstrdup(git_path("config"));
633+
repo_config = git_pathdup("config");
634634
ret += git_config_from_file(fn, repo_config, data);
635635
free(repo_config);
636636
return ret;
@@ -872,7 +872,7 @@ int git_config_set_multivar(const char* key, const char* value,
872872
if (config_exclusive_filename)
873873
config_filename = xstrdup(config_exclusive_filename);
874874
else
875-
config_filename = xstrdup(git_path("config"));
875+
config_filename = git_pathdup("config");
876876

877877
/*
878878
* Since "key" actually contains the section name and the real
@@ -1132,7 +1132,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)
11321132
if (config_exclusive_filename)
11331133
config_filename = xstrdup(config_exclusive_filename);
11341134
else
1135-
config_filename = xstrdup(git_path("config"));
1135+
config_filename = git_pathdup("config");
11361136
out_fd = hold_lock_file_for_update(lock, config_filename, 0);
11371137
if (out_fd < 0) {
11381138
ret = error("could not lock config file %s", config_filename);

environment.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static void setup_git_env(void)
7171
}
7272
git_graft_file = getenv(GRAFT_ENVIRONMENT);
7373
if (!git_graft_file)
74-
git_graft_file = xstrdup(git_path("info/grafts"));
74+
git_graft_file = git_pathdup("info/grafts");
7575
}
7676

7777
int is_bare_repository(void)

path.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,60 @@ static char *cleanup_path(char *path)
3232
return path;
3333
}
3434

35+
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
36+
{
37+
va_list args;
38+
unsigned len;
39+
40+
va_start(args, fmt);
41+
len = vsnprintf(buf, n, fmt, args);
42+
va_end(args);
43+
if (len >= n) {
44+
snprintf(buf, n, bad_path);
45+
return buf;
46+
}
47+
return cleanup_path(buf);
48+
}
49+
50+
static char *git_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
51+
{
52+
const char *git_dir = get_git_dir();
53+
size_t len;
54+
55+
len = strlen(git_dir);
56+
if (n < len + 1)
57+
goto bad;
58+
memcpy(buf, git_dir, len);
59+
if (len && !is_dir_sep(git_dir[len-1]))
60+
buf[len++] = '/';
61+
len += vsnprintf(buf + len, n - len, fmt, args);
62+
if (len >= n)
63+
goto bad;
64+
return cleanup_path(buf);
65+
bad:
66+
snprintf(buf, n, bad_path);
67+
return buf;
68+
}
69+
70+
char *git_snpath(char *buf, size_t n, const char *fmt, ...)
71+
{
72+
va_list args;
73+
va_start(args, fmt);
74+
(void)git_vsnpath(buf, n, fmt, args);
75+
va_end(args);
76+
return buf;
77+
}
78+
79+
char *git_pathdup(const char *fmt, ...)
80+
{
81+
char path[PATH_MAX];
82+
va_list args;
83+
va_start(args, fmt);
84+
(void)git_vsnpath(path, sizeof(path), fmt, args);
85+
va_end(args);
86+
return xstrdup(path);
87+
}
88+
3589
char *mkpath(const char *fmt, ...)
3690
{
3791
va_list args;

refs.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -401,14 +401,15 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
401401
*flag = 0;
402402

403403
for (;;) {
404-
const char *path = git_path("%s", ref);
404+
char path[PATH_MAX];
405405
struct stat st;
406406
char *buf;
407407
int fd;
408408

409409
if (--depth < 0)
410410
return NULL;
411411

412+
git_snpath(path, sizeof(path), "%s", ref);
412413
/* Special case: non-existing file.
413414
* Not having the refs/heads/new-branch is OK
414415
* if we are writing into it, so is .git/HEAD
@@ -1136,13 +1137,14 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
11361137
int logfd, written, oflags = O_APPEND | O_WRONLY;
11371138
unsigned maxlen, len;
11381139
int msglen;
1139-
char *log_file, *logrec;
1140+
char log_file[PATH_MAX];
1141+
char *logrec;
11401142
const char *committer;
11411143

11421144
if (log_all_ref_updates < 0)
11431145
log_all_ref_updates = !is_bare_repository();
11441146

1145-
log_file = git_path("logs/%s", ref_name);
1147+
git_snpath(log_file, sizeof(log_file), "logs/%s", ref_name);
11461148

11471149
if (log_all_ref_updates &&
11481150
(!prefixcmp(ref_name, "refs/heads/") ||
@@ -1271,7 +1273,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
12711273
const char *lockpath;
12721274
char ref[1000];
12731275
int fd, len, written;
1274-
char *git_HEAD = xstrdup(git_path("%s", ref_target));
1276+
char *git_HEAD = git_pathdup("%s", ref_target);
12751277
unsigned char old_sha1[20], new_sha1[20];
12761278

12771279
if (logmsg && read_ref(ref_target, old_sha1))

0 commit comments

Comments
 (0)