aboutsummaryrefslogtreecommitdiff
path: root/sha1_file.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2007-03-10 23:10:26 -0800
committerJunio C Hamano <junkio@cox.net>2007-03-10 23:10:26 -0800
commit8509fed75d576023f5f2db8542fad102fcc62d4d (patch)
tree3e8e0bf37acd8b5b7b3347391f7ebebcaca4d55a /sha1_file.c
parentce4474b65d9293c889282325dc697f0ddee669e6 (diff)
parente2b4f63512357d83f1f11bafadb22063e5d56621 (diff)
downloadgit-8509fed75d576023f5f2db8542fad102fcc62d4d.tar.gz
git-8509fed75d576023f5f2db8542fad102fcc62d4d.tar.xz
Merge branch 'jc/fsck'
* jc/fsck: fsck: exit with non-zero status upon errors unpack_sha1_file(): detect corrupt loose object files. fsck: fix broken loose object check.
Diffstat (limited to 'sha1_file.c')
-rw-r--r--sha1_file.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/sha1_file.c b/sha1_file.c
index 219a10f40..7faa8bcd5 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -967,11 +967,12 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
return 0;
}
-static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
+static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size, const unsigned char *sha1)
{
int bytes = strlen(buffer) + 1;
unsigned char *buf = xmalloc(1+size);
unsigned long n;
+ int status = Z_OK;
n = stream->total_out - bytes;
if (n > size)
@@ -981,12 +982,22 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size
if (bytes < size) {
stream->next_out = buf + bytes;
stream->avail_out = size - bytes;
- while (inflate(stream, Z_FINISH) == Z_OK)
- /* nothing */;
+ while (status == Z_OK)
+ status = inflate(stream, Z_FINISH);
}
buf[size] = 0;
- inflateEnd(stream);
- return buf;
+ if ((status == Z_OK || status == Z_STREAM_END) && !stream->avail_in) {
+ inflateEnd(stream);
+ return buf;
+ }
+
+ if (status < 0)
+ error("corrupt loose object '%s'", sha1_to_hex(sha1));
+ else if (stream->avail_in)
+ error("garbage at end of loose object '%s'",
+ sha1_to_hex(sha1));
+ free(buf);
+ return NULL;
}
/*
@@ -1040,7 +1051,7 @@ static int parse_sha1_header(const char *hdr, unsigned long *sizep)
return *hdr ? -1 : type_from_string(type);
}
-void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size)
+static void *unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type, unsigned long *size, const unsigned char *sha1)
{
int ret;
z_stream stream;
@@ -1050,7 +1061,7 @@ void * unpack_sha1_file(void *map, unsigned long mapsize, enum object_type *type
if (ret < Z_OK || (*type = parse_sha1_header(hdr, size)) < 0)
return NULL;
- return unpack_sha1_rest(&stream, hdr, *size);
+ return unpack_sha1_rest(&stream, hdr, *size, sha1);
}
static off_t get_delta_base(struct packed_git *p,
@@ -1571,7 +1582,7 @@ void *read_sha1_file(const unsigned char *sha1, enum object_type *type,
return buf;
map = map_sha1_file(sha1, &mapsize);
if (map) {
- buf = unpack_sha1_file(map, mapsize, type, size);
+ buf = unpack_sha1_file(map, mapsize, type, size, sha1);
munmap(map, mapsize);
return buf;
}