Verify we know how to read a pack before trying to using it.
[gitweb.git] / sha1_file.c
index 842a6f3ae86993ff877150ab92bbab7b4744b4ce..5f34c69d3a80167a8337b9c6a5382e78f857428f 100644 (file)
@@ -22,7 +22,7 @@
 #endif
 #endif
 
-const unsigned char null_sha1[20] = { 0, };
+const unsigned char null_sha1[20];
 
 static unsigned int sha1_file_open_flag = O_NOATIME;
 
@@ -463,6 +463,7 @@ int use_packed_git(struct packed_git *p)
                int fd;
                struct stat st;
                void *map;
+               struct pack_header *hdr;
 
                pack_mapped += p->pack_size;
                while (PACK_MAX_SZ < pack_mapped && unuse_one_packed_git())
@@ -482,13 +483,24 @@ int use_packed_git(struct packed_git *p)
                        die("packfile %s cannot be mapped.", p->pack_name);
                p->pack_base = map;
 
+               /* Check if we understand this pack file.  If we don't we're
+                * likely too old to handle it.
+                */
+               hdr = map;
+               if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
+                       die("packfile %s isn't actually a pack.", p->pack_name);
+               if (!pack_version_ok(hdr->hdr_version))
+                       die("packfile %s is version %i and not supported"
+                               " (try upgrading GIT to a newer version)",
+                               p->pack_name, ntohl(hdr->hdr_version));
+
                /* Check if the pack file matches with the index file.
                 * this is cheap.
                 */
-               if (memcmp((char*)(p->index_base) + p->index_size - 40,
-                          (char *) p->pack_base + p->pack_size - 20,
-                          20)) {
-
+               if (hashcmp((unsigned char *)(p->index_base) +
+                           p->index_size - 40,
+                           (unsigned char *)p->pack_base +
+                           p->pack_size - 20)) {
                        die("packfile %s does not match index.", p->pack_name);
                }
        }
@@ -643,7 +655,7 @@ int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long siz
        SHA1_Update(&c, header, 1+sprintf(header, "%s %lu", type, size));
        SHA1_Update(&c, map, size);
        SHA1_Final(real_sha1, &c);
-       return memcmp(sha1, real_sha1, 20) ? -1 : 0;
+       return hashcmp(sha1, real_sha1) ? -1 : 0;
 }
 
 void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
@@ -941,7 +953,7 @@ int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,
        ptr = unpack_object_header(p, ptr, kindp, sizep);
        if (*kindp != OBJ_DELTA)
                goto done;
-       memcpy(base, (char *) p->pack_base + ptr, 20);
+       memcpy(base, (unsigned char *) p->pack_base + ptr, 20);
        status = 0;
  done:
        unuse_packed_git(p);
@@ -1206,7 +1218,7 @@ int find_pack_entry_one(const unsigned char *sha1,
 
        do {
                int mi = (lo + hi) / 2;
-               int cmp = memcmp((char *) index + (24 * mi) + 4, sha1, 20);
+               int cmp = hashcmp((unsigned char *)index + (24 * mi) + 4, sha1);
                if (!cmp) {
                        e->offset = ntohl(*((unsigned int *) ((char *) index + (24 * mi))));
                        memcpy(e->sha1, sha1, 20);
@@ -1715,7 +1727,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer,
                unlink(tmpfile);
                return error("File %s corrupted", sha1_to_hex(sha1));
        }
-       if (memcmp(sha1, real_sha1, 20)) {
+       if (hashcmp(sha1, real_sha1)) {
                unlink(tmpfile);
                return error("File %s has bad hash", sha1_to_hex(sha1));
        }