Merge branch 'jc/exec-cmd-system-path-leak-fix'
authorJunio C Hamano <gitster@pobox.com>
Mon, 22 Dec 2014 20:27:01 +0000 (12:27 -0800)
committerJunio C Hamano <gitster@pobox.com>
Mon, 22 Dec 2014 20:27:01 +0000 (12:27 -0800)
The function sometimes returned a non-freeable memory and some
other times returned a piece of memory that must be freed.

* jc/exec-cmd-system-path-leak-fix:
system_path(): always return free'able memory to the caller

1  2 
builtin/help.c
builtin/init-db.c
exec_cmd.c
diff --combined builtin/help.c
index b3c818ee01b6f64c7cf00f2e58d372f4dc8f0250,76fbfe8b48467132347695efb4f2c1935198dc0a..e78c135e010afa3f9447992ae85a7cc404d0192b
@@@ -79,11 -79,12 +79,11 @@@ static const char *get_man_viewer_info(
  static int check_emacsclient_version(void)
  {
        struct strbuf buffer = STRBUF_INIT;
 -      struct child_process ec_process;
 +      struct child_process ec_process = CHILD_PROCESS_INIT;
        const char *argv_ec[] = { "emacsclient", "--version", NULL };
        int version;
  
        /* emacsclient prints its version number on stderr */
 -      memset(&ec_process, 0, sizeof(ec_process));
        ec_process.argv = argv_ec;
        ec_process.err = -1;
        ec_process.stdout_to_stderr = 1;
@@@ -321,16 -322,18 +321,18 @@@ static void setup_man_path(void
  {
        struct strbuf new_path = STRBUF_INIT;
        const char *old_path = getenv("MANPATH");
+       char *git_man_path = system_path(GIT_MAN_PATH);
  
        /* We should always put ':' after our path. If there is no
         * old_path, the ':' at the end will let 'man' to try
         * system-wide paths after ours to find the manual page. If
         * there is old_path, we need ':' as delimiter. */
-       strbuf_addstr(&new_path, system_path(GIT_MAN_PATH));
+       strbuf_addstr(&new_path, git_man_path);
        strbuf_addch(&new_path, ':');
        if (old_path)
                strbuf_addstr(&new_path, old_path);
  
+       free(git_man_path);
        setenv("MANPATH", new_path.buf, 1);
  
        strbuf_release(&new_path);
@@@ -380,8 -383,10 +382,10 @@@ static void show_info_page(const char *
  static void get_html_page_path(struct strbuf *page_path, const char *page)
  {
        struct stat st;
+       char *to_free = NULL;
        if (!html_path)
-               html_path = system_path(GIT_HTML_PATH);
+               html_path = to_free = system_path(GIT_HTML_PATH);
  
        /* Check that we have a git documentation directory. */
        if (!strstr(html_path, "://")) {
  
        strbuf_init(page_path, 0);
        strbuf_addf(page_path, "%s/%s.html", html_path, page);
+       free(to_free);
  }
  
  /*
@@@ -421,7 -427,6 +426,7 @@@ static struct 
        const char *help;
  } common_guides[] = {
        { "attributes", N_("Defining attributes per path") },
 +      { "everyday", N_("Everyday Git With 20 Commands Or So") },
        { "glossary", N_("A Git glossary") },
        { "ignore", N_("Specifies intentionally untracked files to ignore") },
        { "modules", N_("Defining submodule properties") },
diff --combined builtin/init-db.c
index 2619ca5881694b68e24ce13c41347829e4e7d7bb,86c8a30a3125d18ef8cf609ac6670bc5f10f5e51..9966522b4a97a0d1ae430e581125fbfd1d5609ac
@@@ -119,15 -119,18 +119,18 @@@ static void copy_templates(const char *
        DIR *dir;
        const char *git_dir = get_git_dir();
        int len = strlen(git_dir);
+       char *to_free = NULL;
  
        if (!template_dir)
                template_dir = getenv(TEMPLATE_DIR_ENVIRONMENT);
        if (!template_dir)
                template_dir = init_db_template_dir;
        if (!template_dir)
-               template_dir = system_path(DEFAULT_GIT_TEMPLATE_DIR);
-       if (!template_dir[0])
+               template_dir = to_free = system_path(DEFAULT_GIT_TEMPLATE_DIR);
+       if (!template_dir[0]) {
+               free(to_free);
                return;
+       }
        template_len = strlen(template_dir);
        if (PATH_MAX <= (template_len+strlen("/config")))
                die(_("insanely long template path %s"), template_dir);
        dir = opendir(template_path);
        if (!dir) {
                warning(_("templates not found %s"), template_dir);
-               return;
+               goto free_return;
        }
  
        /* Make sure that template is from the correct vintage */
                        "a wrong format version %d from '%s'"),
                        repository_format_version,
                        template_dir);
-               closedir(dir);
-               return;
+               goto close_free_return;
        }
  
        memcpy(path, git_dir, len);
        copy_templates_1(path, len,
                         template_path, template_len,
                         dir);
+ close_free_return:
        closedir(dir);
+ free_return:
+       free(to_free);
  }
  
  static int git_init_db_config(const char *k, const char *v, void *cb)
@@@ -254,10 -259,7 +259,10 @@@ static int create_default_files(const c
                struct stat st2;
                filemode = (!chmod(path, st1.st_mode ^ S_IXUSR) &&
                                !lstat(path, &st2) &&
 -                              st1.st_mode != st2.st_mode);
 +                              st1.st_mode != st2.st_mode &&
 +                              !chmod(path, st1.st_mode));
 +              if (filemode && !reinit && (st1.st_mode & S_IXUSR))
 +                      filemode = 0;
        }
        git_config_set("core.filemode", filemode ? "true" : "false");
  
@@@ -333,12 -335,12 +338,12 @@@ int set_git_dir_init(const char *git_di
                 * moving the target repo later on in separate_git_dir()
                 */
                git_link = xstrdup(real_path(git_dir));
 +              set_git_dir(real_path(real_git_dir));
        }
        else {
 -              real_git_dir = real_path(git_dir);
 +              set_git_dir(real_path(git_dir));
                git_link = NULL;
        }
 -      set_git_dir(real_path(real_git_dir));
        return 0;
  }
  
@@@ -429,9 -431,8 +434,9 @@@ int init_db(const char *template_dir, u
  
  static int guess_repository_type(const char *git_dir)
  {
 -      char cwd[PATH_MAX];
        const char *slash;
 +      char *cwd;
 +      int cwd_is_git_dir;
  
        /*
         * "GIT_DIR=. git init" is always bare.
         */
        if (!strcmp(".", git_dir))
                return 1;
 -      if (!getcwd(cwd, sizeof(cwd)))
 -              die_errno(_("cannot tell cwd"));
 -      if (!strcmp(git_dir, cwd))
 +      cwd = xgetcwd();
 +      cwd_is_git_dir = !strcmp(git_dir, cwd);
 +      free(cwd);
 +      if (cwd_is_git_dir)
                return 1;
        /*
         * "GIT_DIR=.git or GIT_DIR=something/.git is usually not.
@@@ -540,9 -540,10 +545,9 @@@ int cmd_init_db(int argc, const char **
                usage(init_db_usage[0]);
        }
        if (is_bare_repository_cfg == 1) {
 -              static char git_dir[PATH_MAX+1];
 -
 -              setenv(GIT_DIR_ENVIRONMENT,
 -                      getcwd(git_dir, sizeof(git_dir)), argc > 0);
 +              char *cwd = xgetcwd();
 +              setenv(GIT_DIR_ENVIRONMENT, cwd, argc > 0);
 +              free(cwd);
        }
  
        if (init_shared_repository != -1)
                        git_work_tree_cfg = xstrdup(real_path(rel));
                        free(rel);
                }
 -              if (!git_work_tree_cfg) {
 -                      git_work_tree_cfg = xcalloc(PATH_MAX, 1);
 -                      if (!getcwd(git_work_tree_cfg, PATH_MAX))
 -                              die_errno (_("Cannot access current working directory"));
 -              }
 +              if (!git_work_tree_cfg)
 +                      git_work_tree_cfg = xgetcwd();
                if (work_tree)
 -                      set_git_work_tree(real_path(work_tree));
 +                      set_git_work_tree(work_tree);
                else
                        set_git_work_tree(git_work_tree_cfg);
                if (access(get_git_work_tree(), X_OK))
        }
        else {
                if (work_tree)
 -                      set_git_work_tree(real_path(work_tree));
 +                      set_git_work_tree(work_tree);
        }
  
        set_git_dir_init(git_dir, real_git_dir, 1);
diff --combined exec_cmd.c
index 698e7526c40749fd333367018c192537cf6b4562,26ebef6686bec26ff28bbc1492f2af5362910703..8ab37b5f74f360abf8ff4d689b4ff4f3d29cf785
@@@ -6,7 -6,7 +6,7 @@@
  static const char *argv_exec_path;
  static const char *argv0_path;
  
- const char *system_path(const char *path)
+ char *system_path(const char *path)
  {
  #ifdef RUNTIME_PREFIX
        static const char *prefix;
@@@ -16,7 -16,7 +16,7 @@@
        struct strbuf d = STRBUF_INIT;
  
        if (is_absolute_path(path))
-               return path;
+               return xstrdup(path);
  
  #ifdef RUNTIME_PREFIX
        assert(argv0_path);
@@@ -34,8 -34,7 +34,7 @@@
  #endif
  
        strbuf_addf(&d, "%s/%s", prefix, path);
-       path = strbuf_detach(&d, NULL);
-       return path;
+       return strbuf_detach(&d, NULL);
  }
  
  const char *git_extract_argv0_path(const char *argv0)
@@@ -86,7 -85,11 +85,7 @@@ const char *git_exec_path(void
  static void add_path(struct strbuf *out, const char *path)
  {
        if (path && *path) {
 -              if (is_absolute_path(path))
 -                      strbuf_addstr(out, path);
 -              else
 -                      strbuf_addstr(out, absolute_path(path));
 -
 +              strbuf_add_absolute_path(out, path);
                strbuf_addch(out, PATH_SEP);
        }
  }