]> asedeno.scripts.mit.edu Git - git.git/blobdiff - sha1_file.c
apply --unidiff-zero: loosen sanity checks for --unidiff=0 patches
[git.git] / sha1_file.c
index ce90e200cbfdf265b91a9434f911ee06bd2c263a..b64b92de4e7a6c59edfb3e60ff1440a98cacdeea 100644 (file)
@@ -26,15 +26,43 @@ const unsigned char null_sha1[20];
 
 static unsigned int sha1_file_open_flag = O_NOATIME;
 
-static unsigned hexval(char c)
-{
-       if (c >= '0' && c <= '9')
-               return c - '0';
-       if (c >= 'a' && c <= 'f')
-               return c - 'a' + 10;
-       if (c >= 'A' && c <= 'F')
-               return c - 'A' + 10;
-       return ~0;
+static inline unsigned int hexval(unsigned int c)
+{
+       static signed char val[256] = {
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 00-07 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 08-0f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 10-17 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 18-1f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 20-27 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 28-2f */
+                 0,  1,  2,  3,  4,  5,  6,  7,                /* 30-37 */
+                 8,  9, -1, -1, -1, -1, -1, -1,                /* 38-3f */
+                -1, 10, 11, 12, 13, 14, 15, -1,                /* 40-47 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 48-4f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 50-57 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 58-5f */
+                -1, 10, 11, 12, 13, 14, 15, -1,                /* 60-67 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 68-67 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 70-77 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 78-7f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 80-87 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 88-8f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 90-97 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* 98-9f */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* a0-a7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* a8-af */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* b0-b7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* b8-bf */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* c0-c7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* c8-cf */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* d0-d7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* d8-df */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* e0-e7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* e8-ef */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* f0-f7 */
+                -1, -1, -1, -1, -1, -1, -1, -1,                /* f8-ff */
+       };
+       return val[c];
 }
 
 int get_sha1_hex(const char *hex, unsigned char *sha1)
@@ -115,7 +143,7 @@ static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
 
 /*
  * NOTE! This returns a statically allocated buffer, so you have to be
- * careful about using it. Do a "strdup()" if you need to save the
+ * careful about using it. Do a "xstrdup()" if you need to save the
  * filename.
  *
  * Also note that this returns the location for creating.  Reading
@@ -711,17 +739,39 @@ int legacy_loose_object(unsigned char *map)
                return 0;
 }
 
-static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
+unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep)
 {
+       unsigned shift;
        unsigned char c;
-       unsigned int bits;
        unsigned long size;
-       static const char *typename[8] = {
-               NULL,   /* OBJ_EXT */
-               "commit", "tree", "blob", "tag",
-               NULL, NULL, NULL
+       unsigned long used = 0;
+
+       c = buf[used++];
+       *type = (c >> 4) & 7;
+       size = c & 15;
+       shift = 4;
+       while (c & 0x80) {
+               if (len <= used)
+                       return 0;
+               if (sizeof(long) * 8 <= shift)
+                       return 0;
+               c = buf[used++];
+               size += (c & 0x7f) << shift;
+               shift += 7;
+       }
+       *sizep = size;
+       return used;
+}
+
+static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
+{
+       unsigned long size, used;
+       static const char valid_loose_object_type[8] = {
+               0, /* OBJ_EXT */
+               1, 1, 1, 1, /* "commit", "tree", "blob", "tag" */
+               0, /* "delta" and others are invalid in a loose object */
        };
-       const char *type;
+       enum object_type type;
 
        /* Get the data stream */
        memset(stream, 0, sizeof(*stream));
@@ -735,22 +785,11 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
                return inflate(stream, 0);
        }
 
-       c = *map++;
-       mapsize--;
-       type = typename[(c >> 4) & 7];
-       if (!type)
+       used = unpack_object_header_gently(map, mapsize, &type, &size);
+       if (!used || !valid_loose_object_type[type])
                return -1;
-
-       bits = 4;
-       size = c & 0xf;
-       while ((c & 0x80)) {
-               if (bits >= 8*sizeof(long))
-                       return -1;
-               c = *map++;
-               size += (c & 0x7f) << bits;
-               bits += 7;
-               mapsize--;
-       }
+       map += used;
+       mapsize -= used;
 
        /* Set up the stream for the rest.. */
        stream->next_in = map;
@@ -758,7 +797,8 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
        inflateInit(stream);
 
        /* And generate the fake traditional header */
-       stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", type, size);
+       stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
+                                        type_names[type], size);
        return 0;
 }
 
@@ -916,25 +956,18 @@ static int packed_delta_info(unsigned char *base_sha1,
 static unsigned long unpack_object_header(struct packed_git *p, unsigned long offset,
        enum object_type *type, unsigned long *sizep)
 {
-       unsigned shift;
-       unsigned char c;
-       unsigned long size;
+       unsigned long used;
 
-       if (offset >= p->pack_size)
+       if (p->pack_size <= offset)
                die("object offset outside of pack file");
-       c = *((unsigned char *)p->pack_base + offset++);
-       *type = (c >> 4) & 7;
-       size = c & 15;
-       shift = 4;
-       while (c & 0x80) {
-               if (offset >= p->pack_size)
-                       die("object offset outside of pack file");
-               c = *((unsigned char *)p->pack_base + offset++);
-               size += (c & 0x7f) << shift;
-               shift += 7;
-       }
-       *sizep = size;
-       return offset;
+
+       used = unpack_object_header_gently((unsigned char *)p->pack_base +
+                                          offset,
+                                          p->pack_size - offset, type, sizep);
+       if (!used)
+               die("object offset outside of pack file");
+
+       return offset + used;
 }
 
 int check_reuse_pack_delta(struct packed_git *p, unsigned long offset,