* ar/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 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
This commit is contained in:
Junio C Hamano 2008-11-05 11:35:53 -08:00
Родитель d95f91d9e4 98b35e2c74
Коммит a1a846a19e
14 изменённых файлов: 88 добавлений и 21 удалений

Просмотреть файл

@ -2841,8 +2841,8 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
unsigned int nr = getpid(); unsigned int nr = getpid();
for (;;) { for (;;) {
const char *newpath; char newpath[PATH_MAX];
newpath = mkpath("%s~%u", path, nr); mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
if (!try_create_file(newpath, mode, buf, size)) { if (!try_create_file(newpath, mode, buf, size)) {
if (!rename(newpath, path)) if (!rename(newpath, path))
return; return;

Просмотреть файл

@ -84,7 +84,7 @@ static int get_value(const char* key_, const char* regex_)
local = config_exclusive_filename; local = config_exclusive_filename;
if (!local) { if (!local) {
const char *home = getenv("HOME"); const char *home = getenv("HOME");
local = repo_config = xstrdup(git_path("config")); local = repo_config = git_pathdup("config");
if (git_config_global() && home) if (git_config_global() && home)
global = xstrdup(mkpath("%s/.gitconfig", home)); global = xstrdup(mkpath("%s/.gitconfig", home));
if (git_config_system()) if (git_config_system())

Просмотреть файл

@ -620,14 +620,16 @@ static char *get_short_ref(struct refinfo *ref)
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
const char *rule = ref_rev_parse_rules[j]; const char *rule = ref_rev_parse_rules[j];
unsigned char short_objectname[20]; unsigned char short_objectname[20];
char refname[PATH_MAX];
/* /*
* the short name is ambiguous, if it resolves * the short name is ambiguous, if it resolves
* (with this previous rule) to a valid ref * (with this previous rule) to a valid ref
* read_ref() returns 0 on success * read_ref() returns 0 on success
*/ */
if (!read_ref(mkpath(rule, short_name_len, short_name), mksnpath(refname, sizeof(refname),
short_objectname)) rule, short_name_len, short_name);
if (!read_ref(refname, short_objectname))
break; break;
} }

Просмотреть файл

@ -277,11 +277,11 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused,
lock = lock_any_ref_for_update(ref, sha1, 0); lock = lock_any_ref_for_update(ref, sha1, 0);
if (!lock) if (!lock)
return error("cannot lock ref '%s'", ref); return error("cannot lock ref '%s'", ref);
log_file = xstrdup(git_path("logs/%s", ref)); log_file = git_pathdup("logs/%s", ref);
if (!file_exists(log_file)) if (!file_exists(log_file))
goto finish; goto finish;
if (!cmd->dry_run) { if (!cmd->dry_run) {
newlog_path = xstrdup(git_path("logs/%s.lock", ref)); newlog_path = git_pathdup("logs/%s.lock", ref);
cb.newlog = fopen(newlog_path, "w"); cb.newlog = fopen(newlog_path, "w");
} }

Просмотреть файл

@ -251,7 +251,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
int i, index_fd, clean; int i, index_fd, clean;
char *oneline, *reencoded_message = NULL; char *oneline, *reencoded_message = NULL;
const char *message, *encoding; const char *message, *encoding;
char *defmsg = xstrdup(git_path("MERGE_MSG")); char *defmsg = git_pathdup("MERGE_MSG");
struct merge_options o; struct merge_options o;
struct tree *result, *next_tree, *base_tree, *head_tree; struct tree *result, *next_tree, *base_tree, *head_tree;
static struct lock_file index_lock; static struct lock_file index_lock;

Просмотреть файл

@ -283,7 +283,7 @@ static void create_tag(const unsigned char *object, const char *tag,
int fd; int fd;
/* write the template message before editing: */ /* write the template message before editing: */
path = xstrdup(git_path("TAG_EDITMSG")); path = git_pathdup("TAG_EDITMSG");
fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
if (fd < 0) if (fd < 0)
die("could not create file '%s': %s", die("could not create file '%s': %s",

Просмотреть файл

@ -495,6 +495,13 @@ extern int check_repository_format(void);
#define DATA_CHANGED 0x0020 #define DATA_CHANGED 0x0020
#define TYPE_CHANGED 0x0040 #define TYPE_CHANGED 0x0040
extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
__attribute__((format (printf, 3, 4)));
extern char *git_snpath(char *buf, size_t n, const char *fmt, ...)
__attribute__((format (printf, 3, 4)));
extern char *git_pathdup(const char *fmt, ...)
__attribute__((format (printf, 1, 2)));
/* Return a statically allocated filename matching the sha1 signature */ /* Return a statically allocated filename matching the sha1 signature */
extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));

Просмотреть файл

@ -649,7 +649,7 @@ int git_config(config_fn_t fn, void *data)
free(user_config); free(user_config);
} }
repo_config = xstrdup(git_path("config")); repo_config = git_pathdup("config");
ret += git_config_from_file(fn, repo_config, data); ret += git_config_from_file(fn, repo_config, data);
free(repo_config); free(repo_config);
return ret; return ret;
@ -889,7 +889,7 @@ int git_config_set_multivar(const char* key, const char* value,
if (config_exclusive_filename) if (config_exclusive_filename)
config_filename = xstrdup(config_exclusive_filename); config_filename = xstrdup(config_exclusive_filename);
else else
config_filename = xstrdup(git_path("config")); config_filename = git_pathdup("config");
/* /*
* Since "key" actually contains the section name and the real * Since "key" actually contains the section name and the real
@ -1149,7 +1149,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)
if (config_exclusive_filename) if (config_exclusive_filename)
config_filename = xstrdup(config_exclusive_filename); config_filename = xstrdup(config_exclusive_filename);
else else
config_filename = xstrdup(git_path("config")); config_filename = git_pathdup("config");
out_fd = hold_lock_file_for_update(lock, config_filename, 0); out_fd = hold_lock_file_for_update(lock, config_filename, 0);
if (out_fd < 0) { if (out_fd < 0) {
ret = error("could not lock config file %s", config_filename); ret = error("could not lock config file %s", config_filename);

Просмотреть файл

@ -71,7 +71,7 @@ static void setup_git_env(void)
} }
git_graft_file = getenv(GRAFT_ENVIRONMENT); git_graft_file = getenv(GRAFT_ENVIRONMENT);
if (!git_graft_file) if (!git_graft_file)
git_graft_file = xstrdup(git_path("info/grafts")); git_graft_file = git_pathdup("info/grafts");
} }
int is_bare_repository(void) int is_bare_repository(void)

54
path.c
Просмотреть файл

@ -32,6 +32,60 @@ static char *cleanup_path(char *path)
return path; return path;
} }
char *mksnpath(char *buf, size_t n, const char *fmt, ...)
{
va_list args;
unsigned len;
va_start(args, fmt);
len = vsnprintf(buf, n, fmt, args);
va_end(args);
if (len >= n) {
snprintf(buf, n, bad_path);
return buf;
}
return cleanup_path(buf);
}
static char *git_vsnpath(char *buf, size_t n, const char *fmt, va_list args)
{
const char *git_dir = get_git_dir();
size_t len;
len = strlen(git_dir);
if (n < len + 1)
goto bad;
memcpy(buf, git_dir, len);
if (len && !is_dir_sep(git_dir[len-1]))
buf[len++] = '/';
len += vsnprintf(buf + len, n - len, fmt, args);
if (len >= n)
goto bad;
return cleanup_path(buf);
bad:
snprintf(buf, n, bad_path);
return buf;
}
char *git_snpath(char *buf, size_t n, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
(void)git_vsnpath(buf, n, fmt, args);
va_end(args);
return buf;
}
char *git_pathdup(const char *fmt, ...)
{
char path[PATH_MAX];
va_list args;
va_start(args, fmt);
(void)git_vsnpath(path, sizeof(path), fmt, args);
va_end(args);
return xstrdup(path);
}
char *mkpath(const char *fmt, ...) char *mkpath(const char *fmt, ...)
{ {
va_list args; va_list args;

10
refs.c
Просмотреть файл

@ -413,7 +413,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
*flag = 0; *flag = 0;
for (;;) { for (;;) {
const char *path = git_path("%s", ref); char path[PATH_MAX];
struct stat st; struct stat st;
char *buf; char *buf;
int fd; int fd;
@ -421,6 +421,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
if (--depth < 0) if (--depth < 0)
return NULL; return NULL;
git_snpath(path, sizeof(path), "%s", ref);
/* Special case: non-existing file. */ /* Special case: non-existing file. */
if (lstat(path, &st) < 0) { if (lstat(path, &st) < 0) {
struct ref_list *list = get_packed_refs(); struct ref_list *list = get_packed_refs();
@ -1142,13 +1143,14 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
int logfd, written, oflags = O_APPEND | O_WRONLY; int logfd, written, oflags = O_APPEND | O_WRONLY;
unsigned maxlen, len; unsigned maxlen, len;
int msglen; int msglen;
char *log_file, *logrec; char log_file[PATH_MAX];
char *logrec;
const char *committer; const char *committer;
if (log_all_ref_updates < 0) if (log_all_ref_updates < 0)
log_all_ref_updates = !is_bare_repository(); log_all_ref_updates = !is_bare_repository();
log_file = git_path("logs/%s", ref_name); git_snpath(log_file, sizeof(log_file), "logs/%s", ref_name);
if (log_all_ref_updates && if (log_all_ref_updates &&
(!prefixcmp(ref_name, "refs/heads/") || (!prefixcmp(ref_name, "refs/heads/") ||
@ -1277,7 +1279,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
const char *lockpath; const char *lockpath;
char ref[1000]; char ref[1000];
int fd, len, written; int fd, len, written;
char *git_HEAD = xstrdup(git_path("%s", ref_target)); char *git_HEAD = git_pathdup("%s", ref_target);
unsigned char old_sha1[20], new_sha1[20]; unsigned char old_sha1[20], new_sha1[20];
if (logmsg && read_ref(ref_target, old_sha1)) if (logmsg && read_ref(ref_target, old_sha1))

Просмотреть файл

@ -351,7 +351,7 @@ int setup_rerere(struct string_list *merge_rr)
if (!is_rerere_enabled()) if (!is_rerere_enabled())
return -1; return -1;
merge_rr_path = xstrdup(git_path("MERGE_RR")); merge_rr_path = git_pathdup("MERGE_RR");
fd = hold_lock_file_for_update(&write_lock, merge_rr_path, fd = hold_lock_file_for_update(&write_lock, merge_rr_path,
LOCK_DIE_ON_ERROR); LOCK_DIE_ON_ERROR);
read_rr(merge_rr); read_rr(merge_rr);

Просмотреть файл

@ -25,7 +25,7 @@ static int add_info_ref(const char *path, const unsigned char *sha1, int flag, v
static int update_info_refs(int force) static int update_info_refs(int force)
{ {
char *path0 = xstrdup(git_path("info/refs")); char *path0 = git_pathdup("info/refs");
int len = strlen(path0); int len = strlen(path0);
char *path1 = xmalloc(len + 2); char *path1 = xmalloc(len + 2);

Просмотреть файл

@ -245,11 +245,13 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
*ref = NULL; *ref = NULL;
for (p = ref_rev_parse_rules; *p; p++) { for (p = ref_rev_parse_rules; *p; p++) {
char fullref[PATH_MAX];
unsigned char sha1_from_ref[20]; unsigned char sha1_from_ref[20];
unsigned char *this_result; unsigned char *this_result;
this_result = refs_found ? sha1_from_ref : sha1; this_result = refs_found ? sha1_from_ref : sha1;
r = resolve_ref(mkpath(*p, len, str), this_result, 1, NULL); mksnpath(fullref, sizeof(fullref), *p, len, str);
r = resolve_ref(fullref, this_result, 1, NULL);
if (r) { if (r) {
if (!refs_found++) if (!refs_found++)
*ref = xstrdup(r); *ref = xstrdup(r);
@ -272,7 +274,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
char path[PATH_MAX]; char path[PATH_MAX];
const char *ref, *it; const char *ref, *it;
strcpy(path, mkpath(*p, len, str)); mksnpath(path, sizeof(path), *p, len, str);
ref = resolve_ref(path, hash, 1, NULL); ref = resolve_ref(path, hash, 1, NULL);
if (!ref) if (!ref)
continue; continue;