Prevent bogus paths from being added to the index.
authorLinus Torvalds <torvalds@osdl.org>
Thu, 18 May 2006 19:07:31 +0000 (12:07 -0700)
committerJunio C Hamano <junkio@cox.net>
Thu, 18 May 2006 19:07:31 +0000 (12:07 -0700)
With this one, it's now a fatal error to try to add a pathname
that cannot be added with "git add", i.e.

[torvalds@g5 git]$ git add .git/config
fatal: unable to add .git/config to index

and

[torvalds@g5 git]$ git add foo/../bar
fatal: unable to add foo/../bar to index

instead of the old "Ignoring path xyz" warning that would end up
silently succeeding on any other paths.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
cache.h
read-cache.c
update-index.c

diff --git a/cache.h b/cache.h
index 4b7a439..89aa4f6 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -142,6 +142,7 @@ extern void verify_non_filename(const char *prefix, const char *name);
 /* Initialize and use the cache information */
 extern int read_cache(void);
 extern int write_cache(int newfd, struct cache_entry **cache, int entries);
+extern int verify_path(const char *path);
 extern int cache_name_pos(const char *name, int namelen);
 #define ADD_CACHE_OK_TO_ADD 1          /* Ok to add */
 #define ADD_CACHE_OK_TO_REPLACE 2      /* Ok to replace file/directory */
index a917ab0..e8fa6d0 100644 (file)
@@ -332,6 +332,70 @@ int ce_path_match(const struct cache_entry *ce, const char **pathspec)
 }
 
 /*
+ * We fundamentally don't like some paths: we don't want
+ * dot or dot-dot anywhere, and for obvious reasons don't
+ * want to recurse into ".git" either.
+ *
+ * Also, we don't want double slashes or slashes at the
+ * end that can make pathnames ambiguous.
+ */
+static int verify_dotfile(const char *rest)
+{
+       /*
+        * The first character was '.', but that
+        * has already been discarded, we now test
+        * the rest.
+        */
+       switch (*rest) {
+       /* "." is not allowed */
+       case '\0': case '/':
+               return 0;
+
+       /*
+        * ".git" followed by  NUL or slash is bad. This
+        * shares the path end test with the ".." case.
+        */
+       case 'g':
+               if (rest[1] != 'i')
+                       break;
+               if (rest[2] != 't')
+                       break;
+               rest += 2;
+       /* fallthrough */
+       case '.':
+               if (rest[1] == '\0' || rest[1] == '/')
+                       return 0;
+       }
+       return 1;
+}
+
+int verify_path(const char *path)
+{
+       char c;
+
+       goto inside;
+       for (;;) {
+               if (!c)
+                       return 1;
+               if (c == '/') {
+inside:
+                       c = *path++;
+                       switch (c) {
+                       default:
+                               continue;
+                       case '/': case '\0':
+                               break;
+                       case '.':
+                               if (verify_dotfile(path))
+                                       continue;
+                       }
+                       return 0;
+               }
+               c = *path++;
+       }
+}
+
+/*
  * Do we have another file that has the beginning components being a
  * proper superset of the name we're trying to add?
  */
@@ -472,6 +536,8 @@ int add_cache_entry(struct cache_entry *ce, int option)
 
        if (!ok_to_add)
                return -1;
+       if (!verify_path(ce->name))
+               return -1;
 
        if (!skip_df_check &&
            check_file_directory_conflict(ce, pos, ok_to_replace)) {
index 3d7e02d..859efc7 100644 (file)
@@ -237,70 +237,6 @@ static int refresh_cache(int really)
        return has_errors;
 }
 
-/*
- * We fundamentally don't like some paths: we don't want
- * dot or dot-dot anywhere, and for obvious reasons don't
- * want to recurse into ".git" either.
- *
- * Also, we don't want double slashes or slashes at the
- * end that can make pathnames ambiguous.
- */
-static int verify_dotfile(const char *rest)
-{
-       /*
-        * The first character was '.', but that
-        * has already been discarded, we now test
-        * the rest.
-        */
-       switch (*rest) {
-       /* "." is not allowed */
-       case '\0': case '/':
-               return 0;
-
-       /*
-        * ".git" followed by  NUL or slash is bad. This
-        * shares the path end test with the ".." case.
-        */
-       case 'g':
-               if (rest[1] != 'i')
-                       break;
-               if (rest[2] != 't')
-                       break;
-               rest += 2;
-       /* fallthrough */
-       case '.':
-               if (rest[1] == '\0' || rest[1] == '/')
-                       return 0;
-       }
-       return 1;
-}
-
-static int verify_path(const char *path)
-{
-       char c;
-
-       goto inside;
-       for (;;) {
-               if (!c)
-                       return 1;
-               if (c == '/') {
-inside:
-                       c = *path++;
-                       switch (c) {
-                       default:
-                               continue;
-                       case '/': case '\0':
-                               break;
-                       case '.':
-                               if (verify_dotfile(path))
-                                       continue;
-                       }
-                       return 0;
-               }
-               c = *path++;
-       }
-}
-
 static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
                         const char *path, int stage)
 {