Merge branch 'jc/verify-loose-object-header'
[gitweb.git] / sha1_file.c
index 66dccaaf149c45e40b0e642045ea88dab66b19f0..94daf31ec6b73f99c4e07ed3b6f9235c2f1baec8 100644 (file)
@@ -1646,7 +1646,9 @@ unsigned long unpack_object_header_buffer(const unsigned char *buf,
        return used;
 }
 
-int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
+static int unpack_sha1_short_header(git_zstream *stream,
+                                   unsigned char *map, unsigned long mapsize,
+                                   void *buffer, unsigned long bufsiz)
 {
        /* Get the data stream */
        memset(stream, 0, sizeof(*stream));
@@ -1659,13 +1661,31 @@ int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long ma
        return git_inflate(stream, 0);
 }
 
+int unpack_sha1_header(git_zstream *stream,
+                      unsigned char *map, unsigned long mapsize,
+                      void *buffer, unsigned long bufsiz)
+{
+       int status = unpack_sha1_short_header(stream, map, mapsize,
+                                             buffer, bufsiz);
+
+       if (status < Z_OK)
+               return status;
+
+       /* Make sure we have the terminating NUL */
+       if (!memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer))
+               return -1;
+       return 0;
+}
+
 static int unpack_sha1_header_to_strbuf(git_zstream *stream, unsigned char *map,
                                        unsigned long mapsize, void *buffer,
                                        unsigned long bufsiz, struct strbuf *header)
 {
        int status;
 
-       status = unpack_sha1_header(stream, map, mapsize, buffer, bufsiz);
+       status = unpack_sha1_short_header(stream, map, mapsize, buffer, bufsiz);
+       if (status < Z_OK)
+               return -1;
 
        /*
         * Check if entire header is unpacked in the first iteration.
@@ -1756,6 +1776,8 @@ static int parse_sha1_header_extended(const char *hdr, struct object_info *oi,
         */
        for (;;) {
                char c = *hdr++;
+               if (!c)
+                       return -1;
                if (c == ' ')
                        break;
                type_len++;
@@ -2260,11 +2282,11 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
        void *base, unsigned long base_size, enum object_type type)
 {
        struct delta_base_cache_entry *ent = xmalloc(sizeof(*ent));
-       struct list_head *lru;
+       struct list_head *lru, *tmp;
 
        delta_base_cached += base_size;
 
-       list_for_each(lru, &delta_base_cache_lru) {
+       list_for_each_safe(lru, tmp, &delta_base_cache_lru) {
                struct delta_base_cache_entry *f =
                        list_entry(lru, struct delta_base_cache_entry, lru);
                if (delta_base_cached <= delta_base_cache_limit)