Merge branch 'ar/maint-mksnpath' into maint
authorJunio C Hamano <gitster@pobox.com>
Sun, 9 Nov 2008 00:13:19 +0000 (16:13 -0800)
committerJunio C Hamano <gitster@pobox.com>
Sun, 9 Nov 2008 00:13:19 +0000 (16:13 -0800)
* 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

13 files changed:
builtin-apply.c
builtin-config.c
builtin-reflog.c
builtin-revert.c
builtin-tag.c
cache.h
config.c
environment.c
path.c
refs.c
rerere.c
server-info.c
sha1_name.c
index e9d49f133afd559d2df3f09997c08a61dfc2ff86..50b623e54c003fb5bbe183568d13f496c3c41c25 100644 (file)
@@ -2850,8 +2850,8 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
                unsigned int nr = getpid();
 
                for (;;) {
-                       const char *newpath;
-                       newpath = mkpath("%s~%u", path, nr);
+                       char newpath[PATH_MAX];
+                       mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
                        if (!try_create_file(newpath, mode, buf, size)) {
                                if (!rename(newpath, path))
                                        return;
index 91fdc4985d8e64fae12209174dd4aa2d887793e5..f71016204b540d0d935323c909a0ffccb1abdbe2 100644 (file)
@@ -84,7 +84,7 @@ static int get_value(const char* key_, const char* regex_)
        local = config_exclusive_filename;
        if (!local) {
                const char *home = getenv("HOME");
-               local = repo_config = xstrdup(git_path("config"));
+               local = repo_config = git_pathdup("config");
                if (git_config_global() && home)
                        global = xstrdup(mkpath("%s/.gitconfig", home));
                if (git_config_system())
index 196fa03b7fac795475a0e12f0fa3b443cb34bd1d..da96da317be01c24ae9711206976f48f33e39f97 100644 (file)
@@ -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);
        if (!lock)
                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))
                goto finish;
        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");
        }
 
index 786a956f26486856c97e15ce8ab464dfb25dcbc5..74845ef8e6f9c635bbafbf5dfea5e73cf6e11aa0 100644 (file)
@@ -269,7 +269,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
        int i;
        char *oneline, *reencoded_message = NULL;
        const char *message, *encoding;
-       char *defmsg = xstrdup(git_path("MERGE_MSG"));
+       char *defmsg = git_pathdup("MERGE_MSG");
 
        git_config(git_default_config, NULL);
        me = action == REVERT ? "revert" : "cherry-pick";
index 5b141c584680ecc2362fc0e036e01dbeefa4ee90..843e9ac056c88bb2c9a8c6ded464096a99f13aff 100644 (file)
@@ -283,7 +283,7 @@ static void create_tag(const unsigned char *object, const char *tag,
                int fd;
 
                /* 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);
                if (fd < 0)
                        die("could not create file '%s': %s",
diff --git a/cache.h b/cache.h
index 39f24ad827a419740e2c7515e0e8f294424cd9b0..a1e4982cd424ec5c3695c2221583bca1bd861614 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -484,6 +484,13 @@ extern int check_repository_format(void);
 #define DATA_CHANGED    0x0020
 #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 */
 extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
 extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
index 53f04a076a7275965090edd4ca2a34652c4f5679..82807c83b20ef8fbabfda7d476feff92f2dbb823 100644 (file)
--- a/config.c
+++ b/config.c
@@ -630,7 +630,7 @@ int git_config(config_fn_t fn, void *data)
                free(user_config);
        }
 
-       repo_config = xstrdup(git_path("config"));
+       repo_config = git_pathdup("config");
        ret += git_config_from_file(fn, repo_config, data);
        free(repo_config);
        return ret;
@@ -872,7 +872,7 @@ int git_config_set_multivar(const char* key, const char* value,
        if (config_exclusive_filename)
                config_filename = xstrdup(config_exclusive_filename);
        else
-               config_filename = xstrdup(git_path("config"));
+               config_filename = git_pathdup("config");
 
        /*
         * 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)
        if (config_exclusive_filename)
                config_filename = xstrdup(config_exclusive_filename);
        else
-               config_filename = xstrdup(git_path("config"));
+               config_filename = git_pathdup("config");
        out_fd = hold_lock_file_for_update(lock, config_filename, 0);
        if (out_fd < 0) {
                ret = error("could not lock config file %s", config_filename);
index 0c6d11f6a0c6fa5dbab2f36c4b4ad4de5aba4ac9..df4f03a95f0b2098e97d0410bbb0589ff887e9cb 100644 (file)
@@ -71,7 +71,7 @@ static void setup_git_env(void)
        }
        git_graft_file = getenv(GRAFT_ENVIRONMENT);
        if (!git_graft_file)
-               git_graft_file = xstrdup(git_path("info/grafts"));
+               git_graft_file = git_pathdup("info/grafts");
 }
 
 int is_bare_repository(void)
diff --git a/path.c b/path.c
index c1cb54b7b8b478c717861a0205e537ded3fbbfc9..eb24017535f944a2c5dbc46663c02937cff69cd3 100644 (file)
--- a/path.c
+++ b/path.c
@@ -32,6 +32,60 @@ static char *cleanup_path(char *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, ...)
 {
        va_list args;
diff --git a/refs.c b/refs.c
index 156714e54ee6c980a48f01610d78d10301e849b7..48271a99ab0a7616ff0ae990a166c4a19811ffc9 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -401,7 +401,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
                *flag = 0;
 
        for (;;) {
-               const char *path = git_path("%s", ref);
+               char path[PATH_MAX];
                struct stat st;
                char *buf;
                int fd;
@@ -409,6 +409,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
                if (--depth < 0)
                        return NULL;
 
+               git_snpath(path, sizeof(path), "%s", ref);
                /* Special case: non-existing file.
                 * Not having the refs/heads/new-branch is OK
                 * 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,
        int logfd, written, oflags = O_APPEND | O_WRONLY;
        unsigned maxlen, len;
        int msglen;
-       char *log_file, *logrec;
+       char log_file[PATH_MAX];
+       char *logrec;
        const char *committer;
 
        if (log_all_ref_updates < 0)
                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 &&
            (!prefixcmp(ref_name, "refs/heads/") ||
@@ -1271,7 +1273,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
        const char *lockpath;
        char ref[1000];
        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];
 
        if (logmsg && read_ref(ref_target, old_sha1))
index 2b7a99d729e13b09239f1d9175d3d6c0048821b0..a0d477aaca73ff7ec8b12dc6c8255b69dbd677a5 100644 (file)
--- a/rerere.c
+++ b/rerere.c
@@ -345,7 +345,7 @@ int setup_rerere(struct string_list *merge_rr)
        if (!is_rerere_enabled())
                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,
                                       LOCK_DIE_ON_ERROR);
        read_rr(merge_rr);
index c1c073b2f05a48772a45602cdc711eef6e211695..66b0d9d878a011393582b837301eb1fd5caf2e40 100644 (file)
@@ -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)
 {
-       char *path0 = xstrdup(git_path("info/refs"));
+       char *path0 = git_pathdup("info/refs");
        int len = strlen(path0);
        char *path1 = xmalloc(len + 2);
 
index 4fb77f8863ec075de38b84171d3ef039a00cee4c..75a5a7e96f292bed344a7609fca2f3a45ba4314e 100644 (file)
@@ -245,11 +245,13 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
 
        *ref = NULL;
        for (p = ref_rev_parse_rules; *p; p++) {
+               char fullref[PATH_MAX];
                unsigned char sha1_from_ref[20];
                unsigned char *this_result;
 
                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 (!refs_found++)
                                *ref = xstrdup(r);
@@ -272,7 +274,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
                char path[PATH_MAX];
                const char *ref, *it;
 
-               strcpy(path, mkpath(*p, len, str));
+               mksnpath(path, sizeof(path), *p, len, str);
                ref = resolve_ref(path, hash, 1, NULL);
                if (!ref)
                        continue;