Code

"git -p cmd" to page anywhere
[git.git] / read-cache.c
index 2512565260f7664b08b0dc772a67cb26ac01f81f..3c32aae7e8ae63bccad83a603f2b86c66965cd26 100644 (file)
@@ -346,6 +346,70 @@ int ce_path_match(const struct cache_entry *ce, const char **pathspec)
        return 0;
 }
 
+/*
+ * 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?
@@ -487,6 +551,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)) {
@@ -640,7 +706,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
        SHA1_Init(&c);
        SHA1_Update(&c, hdr, size - 20);
        SHA1_Final(sha1, &c);
-       if (memcmp(sha1, (void *)hdr + size - 20, 20))
+       if (memcmp(sha1, (char *) hdr + size - 20, 20))
                return error("bad index file sha1 signature");
        return 0;
 }
@@ -704,7 +770,7 @@ int read_cache(void)
 
        offset = sizeof(*hdr);
        for (i = 0; i < active_nr; i++) {
-               struct cache_entry *ce = map + offset;
+               struct cache_entry *ce = (struct cache_entry *) ((char *) map + offset);
                offset = offset + ce_size(ce);
                active_cache[i] = ce;
        }
@@ -717,10 +783,11 @@ int read_cache(void)
                 * in 4-byte network byte order.
                 */
                unsigned long extsize;
-               memcpy(&extsize, map + offset + 4, 4);
+               memcpy(&extsize, (char *) map + offset + 4, 4);
                extsize = ntohl(extsize);
-               if (read_index_extension(map + offset,
-                                        map + offset + 8, extsize) < 0)
+               if (read_index_extension(((const char *) map) + offset,
+                                        (char *) map + offset + 8,
+                                        extsize) < 0)
                        goto unmap;
                offset += 8;
                offset += extsize;
@@ -754,13 +821,13 @@ static int ce_write(SHA_CTX *context, int fd, void *data, unsigned int len)
                }
                write_buffer_len = buffered;
                len -= partial;
-               data += partial;
+               data = (char *) data + partial;
        }
        return 0;
 }
 
 static int write_index_ext_header(SHA_CTX *context, int fd,
-                                 unsigned long ext, unsigned long sz)
+                                 unsigned int ext, unsigned int sz)
 {
        ext = htonl(ext);
        sz = htonl(sz);