Code

Fix work-tree related breakages
authorJunio C Hamano <gitster@pobox.com>
Thu, 2 Aug 2007 22:10:56 +0000 (15:10 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 3 Aug 2007 00:26:26 +0000 (17:26 -0700)
In set_work_tree(), variable rel needs to be reinitialized to
NULL on every call (it should not be static).

Make sure the incoming dir variable is not too long before
copying to the temporary buffer, and make sure chdir to the
resulting directory succeeds.

This was spotted and fixed by Alex and Johannes in a handful
patch exchanges.  Here is the final version.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
Acked-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
setup.c

diff --git a/setup.c b/setup.c
index 3653092ab657942639b6183fb04b3af783b77e7a..4945eb3134c3e047f54e51db25cd0aa81d9c47d7 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -201,26 +201,32 @@ int is_inside_work_tree(void)
  */
 const char *set_work_tree(const char *dir)
 {
-       char dir_buffer[PATH_MAX];
-       static char buffer[PATH_MAX + 1], *rel = NULL;
-       int len, postfix_len = strlen(DEFAULT_GIT_DIR_ENVIRONMENT) + 1;
+       char dir_buffer[PATH_MAX], *rel = NULL;
+       static char buffer[PATH_MAX + 1];
+       int len, suffix_len = strlen(DEFAULT_GIT_DIR_ENVIRONMENT) + 1;
 
        /* strip the variable 'dir' of the postfix "/.git" if it has it */
        len = strlen(dir);
-       if (len > postfix_len && !strcmp(dir + len - postfix_len,
-                               "/" DEFAULT_GIT_DIR_ENVIRONMENT)) {
-                       strncpy(dir_buffer, dir, len - postfix_len);
+       if (len > suffix_len &&
+           !strcmp(dir + len - suffix_len, "/" DEFAULT_GIT_DIR_ENVIRONMENT)) {
+               if ((len - suffix_len) >= sizeof(dir_buffer))
+                       die("directory name too long");
+               memcpy(dir_buffer, dir, len - suffix_len);
+               dir_buffer[len - suffix_len] = '\0';
 
                /* are we inside the default work tree? */
                rel = get_relative_cwd(buffer, sizeof(buffer), dir_buffer);
        }
+
        /* if rel is set, the cwd is _not_ the current working tree */
        if (rel && *rel) {
                if (!is_absolute_path(dir))
                        set_git_dir(make_absolute_path(dir));
                dir = dir_buffer;
-               chdir(dir);
-               strcat(rel, "/");
+               if (chdir(dir))
+                       die("cannot chdir to %s: %s", dir, strerror(errno));
+               else
+                       strcat(rel, "/");
                inside_git_dir = 0;
        } else {
                rel = NULL;