Merge branch 'jk/check-corrupt-objects-carefully'
authorJunio C Hamano <gitster@pobox.com>
Wed, 3 Apr 2013 16:34:28 +0000 (09:34 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Apr 2013 16:34:29 +0000 (09:34 -0700)
Have the streaming interface and other codepaths more carefully
examine for corrupt objects.

* jk/check-corrupt-objects-carefully:
clone: leave repo in place after checkout errors
clone: run check_everything_connected
clone: die on errors from unpack_trees
add tests for cloning corrupted repositories
streaming_write_entry: propagate streaming errors
add test for streaming corrupt blobs
avoid infinite loop in read_istream_loose
read_istream_filtered: propagate read error from upstream
check_sha1_signature: check return value from read_istream
stream_blob_to_fd: detect errors reading from stream

1  2 
entry.c
sha1_file.c
diff --combined entry.c
index 63c52edf600b5fd966e24cc5758bdab7dbeaf41b,a20bcbc47af6b231fa7d649b02a45da84d6da706..d7c131d45309a496714221616244a70569155913
+++ b/entry.c
@@@ -120,16 -120,18 +120,18 @@@ static int streaming_write_entry(struc
                                 const struct checkout *state, int to_tempfile,
                                 int *fstat_done, struct stat *statbuf)
  {
-       int result = -1;
+       int result = 0;
        int fd;
  
        fd = open_output_fd(path, ce, to_tempfile);
-       if (0 <= fd) {
-               result = stream_blob_to_fd(fd, ce->sha1, filter, 1);
-               *fstat_done = fstat_output(fd, state, statbuf);
-               result = close(fd);
-       }
-       if (result && 0 <= fd)
+       if (fd < 0)
+               return -1;
+       result |= stream_blob_to_fd(fd, ce->sha1, filter, 1);
+       *fstat_done = fstat_output(fd, state, statbuf);
+       result |= close(fd);
+       if (result)
                unlink(path);
        return result;
  }
@@@ -145,7 -147,7 +147,7 @@@ static int write_entry(struct cache_ent
        struct stat st;
  
        if (ce_mode_s_ifmt == S_IFREG) {
 -              struct stream_filter *filter = get_stream_filter(path, ce->sha1);
 +              struct stream_filter *filter = get_stream_filter(ce->name, ce->sha1);
                if (filter &&
                    !streaming_write_entry(ce, path, filter,
                                           state, to_tempfile,
diff --combined sha1_file.c
index 5f573d9b8107720b1a4f5c1da63a2d8e5b4369cf,0b99f336e62256606f3fffc3eaf0ee7727d428c5..0ed23981b363a07c6f4c5b930b1a5991d5c8a622
@@@ -124,13 -124,8 +124,13 @@@ int safe_create_leading_directories(cha
                        }
                }
                else if (mkdir(path, 0777)) {
 -                      *pos = '/';
 -                      return -1;
 +                      if (errno == EEXIST &&
 +                          !stat(path, &st) && S_ISDIR(st.st_mode)) {
 +                              ; /* somebody created it since we checked */
 +                      } else {
 +                              *pos = '/';
 +                              return -1;
 +                      }
                }
                else if (adjust_shared_perm(path)) {
                        *pos = '/';
@@@ -1271,6 -1266,10 +1271,10 @@@ int check_sha1_signature(const unsigne
                char buf[1024 * 16];
                ssize_t readlen = read_istream(st, buf, sizeof(buf));
  
+               if (readlen < 0) {
+                       close_istream(st);
+                       return -1;
+               }
                if (!readlen)
                        break;
                git_SHA1_Update(&c, buf, readlen);