Merge branch 'lt/maint-wrap-zlib'

* lt/maint-wrap-zlib:
  Wrap inflate and other zlib routines for better error reporting

Conflicts:
	http-push.c
	http-walker.c
	sha1_file.c
This commit is contained in:
Junio C Hamano 2009-01-21 16:55:17 -08:00
commit 36dd939393
9 changed files with 99 additions and 34 deletions

View File

@ -1258,8 +1258,9 @@ static char *inflate_it(const void *data, unsigned long size,
stream.avail_in = size; stream.avail_in = size;
stream.next_out = out = xmalloc(inflated_size); stream.next_out = out = xmalloc(inflated_size);
stream.avail_out = inflated_size; stream.avail_out = inflated_size;
inflateInit(&stream); git_inflate_init(&stream);
st = inflate(&stream, Z_FINISH); st = git_inflate(&stream, Z_FINISH);
git_inflate_end(&stream);
if ((st != Z_STREAM_END) || stream.total_out != inflated_size) { if ((st != Z_STREAM_END) || stream.total_out != inflated_size) {
free(out); free(out);
return NULL; return NULL;

View File

@ -195,16 +195,16 @@ static int check_pack_inflate(struct packed_git *p,
int st; int st;
memset(&stream, 0, sizeof(stream)); memset(&stream, 0, sizeof(stream));
inflateInit(&stream); git_inflate_init(&stream);
do { do {
in = use_pack(p, w_curs, offset, &stream.avail_in); in = use_pack(p, w_curs, offset, &stream.avail_in);
stream.next_in = in; stream.next_in = in;
stream.next_out = fakebuf; stream.next_out = fakebuf;
stream.avail_out = sizeof(fakebuf); stream.avail_out = sizeof(fakebuf);
st = inflate(&stream, Z_FINISH); st = git_inflate(&stream, Z_FINISH);
offset += stream.next_in - in; offset += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR); } while (st == Z_OK || st == Z_BUF_ERROR);
inflateEnd(&stream); git_inflate_end(&stream);
return (st == Z_STREAM_END && return (st == Z_STREAM_END &&
stream.total_out == expect && stream.total_out == expect &&
stream.total_in == len) ? 0 : -1; stream.total_in == len) ? 0 : -1;

View File

@ -99,10 +99,10 @@ static void *get_data(unsigned long size)
stream.avail_out = size; stream.avail_out = size;
stream.next_in = fill(1); stream.next_in = fill(1);
stream.avail_in = len; stream.avail_in = len;
inflateInit(&stream); git_inflate_init(&stream);
for (;;) { for (;;) {
int ret = inflate(&stream, 0); int ret = git_inflate(&stream, 0);
use(len - stream.avail_in); use(len - stream.avail_in);
if (stream.total_out == size && ret == Z_STREAM_END) if (stream.total_out == size && ret == Z_STREAM_END)
break; break;
@ -118,7 +118,7 @@ static void *get_data(unsigned long size)
stream.next_in = fill(1); stream.next_in = fill(1);
stream.avail_in = len; stream.avail_in = len;
} }
inflateEnd(&stream); git_inflate_end(&stream);
return buf; return buf;
} }

View File

@ -18,6 +18,10 @@
#define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11) #define deflateBound(c,s) ((s) + (((s) + 7) >> 3) + (((s) + 63) >> 6) + 11)
#endif #endif
void git_inflate_init(z_streamp strm);
void git_inflate_end(z_streamp strm);
int git_inflate(z_streamp strm, int flush);
#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT) #if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
#define DTYPE(de) ((de)->d_type) #define DTYPE(de) ((de)->d_type)
#else #else

View File

@ -209,7 +209,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
do { do {
request->stream.next_out = expn; request->stream.next_out = expn;
request->stream.avail_out = sizeof(expn); request->stream.avail_out = sizeof(expn);
request->zret = inflate(&request->stream, Z_SYNC_FLUSH); request->zret = git_inflate(&request->stream, Z_SYNC_FLUSH);
git_SHA1_Update(&request->c, expn, git_SHA1_Update(&request->c, expn,
sizeof(expn) - request->stream.avail_out); sizeof(expn) - request->stream.avail_out);
} while (request->stream.avail_in && request->zret == Z_OK); } while (request->stream.avail_in && request->zret == Z_OK);
@ -269,7 +269,7 @@ static void start_fetch_loose(struct transfer_request *request)
memset(&request->stream, 0, sizeof(request->stream)); memset(&request->stream, 0, sizeof(request->stream));
inflateInit(&request->stream); git_inflate_init(&request->stream);
git_SHA1_Init(&request->c); git_SHA1_Init(&request->c);
@ -310,7 +310,7 @@ static void start_fetch_loose(struct transfer_request *request)
file; also rewind to the beginning of the local file. */ file; also rewind to the beginning of the local file. */
if (prev_read == -1) { if (prev_read == -1) {
memset(&request->stream, 0, sizeof(request->stream)); memset(&request->stream, 0, sizeof(request->stream));
inflateInit(&request->stream); git_inflate_init(&request->stream);
git_SHA1_Init(&request->c); git_SHA1_Init(&request->c);
if (prev_posn>0) { if (prev_posn>0) {
prev_posn = 0; prev_posn = 0;
@ -742,7 +742,7 @@ static void finish_request(struct transfer_request *request)
if (request->http_code == 416) if (request->http_code == 416)
fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n"); fprintf(stderr, "Warning: requested range invalid; we may already have all the data.\n");
inflateEnd(&request->stream); git_inflate_end(&request->stream);
git_SHA1_Final(request->real_sha1, &request->c); git_SHA1_Final(request->real_sha1, &request->c);
if (request->zret != Z_STREAM_END) { if (request->zret != Z_STREAM_END) {
unlink(request->tmpfile); unlink(request->tmpfile);

View File

@ -82,7 +82,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
do { do {
obj_req->stream.next_out = expn; obj_req->stream.next_out = expn;
obj_req->stream.avail_out = sizeof(expn); obj_req->stream.avail_out = sizeof(expn);
obj_req->zret = inflate(&obj_req->stream, Z_SYNC_FLUSH); obj_req->zret = git_inflate(&obj_req->stream, Z_SYNC_FLUSH);
git_SHA1_Update(&obj_req->c, expn, git_SHA1_Update(&obj_req->c, expn,
sizeof(expn) - obj_req->stream.avail_out); sizeof(expn) - obj_req->stream.avail_out);
} while (obj_req->stream.avail_in && obj_req->zret == Z_OK); } while (obj_req->stream.avail_in && obj_req->zret == Z_OK);
@ -142,7 +142,7 @@ static void start_object_request(struct walker *walker,
memset(&obj_req->stream, 0, sizeof(obj_req->stream)); memset(&obj_req->stream, 0, sizeof(obj_req->stream));
inflateInit(&obj_req->stream); git_inflate_init(&obj_req->stream);
git_SHA1_Init(&obj_req->c); git_SHA1_Init(&obj_req->c);
@ -183,7 +183,7 @@ static void start_object_request(struct walker *walker,
file; also rewind to the beginning of the local file. */ file; also rewind to the beginning of the local file. */
if (prev_read == -1) { if (prev_read == -1) {
memset(&obj_req->stream, 0, sizeof(obj_req->stream)); memset(&obj_req->stream, 0, sizeof(obj_req->stream));
inflateInit(&obj_req->stream); git_inflate_init(&obj_req->stream);
git_SHA1_Init(&obj_req->c); git_SHA1_Init(&obj_req->c);
if (prev_posn>0) { if (prev_posn>0) {
prev_posn = 0; prev_posn = 0;
@ -243,7 +243,7 @@ static void finish_object_request(struct object_request *obj_req)
return; return;
} }
inflateEnd(&obj_req->stream); git_inflate_end(&obj_req->stream);
git_SHA1_Final(obj_req->real_sha1, &obj_req->c); git_SHA1_Final(obj_req->real_sha1, &obj_req->c);
if (obj_req->zret != Z_STREAM_END) { if (obj_req->zret != Z_STREAM_END) {
unlink(obj_req->tmpfile); unlink(obj_req->tmpfile);

View File

@ -275,10 +275,10 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size)
stream.avail_out = size; stream.avail_out = size;
stream.next_in = fill(1); stream.next_in = fill(1);
stream.avail_in = input_len; stream.avail_in = input_len;
inflateInit(&stream); git_inflate_init(&stream);
for (;;) { for (;;) {
int ret = inflate(&stream, 0); int ret = git_inflate(&stream, 0);
use(input_len - stream.avail_in); use(input_len - stream.avail_in);
if (stream.total_out == size && ret == Z_STREAM_END) if (stream.total_out == size && ret == Z_STREAM_END)
break; break;
@ -287,7 +287,7 @@ static void *unpack_entry_data(unsigned long offset, unsigned long size)
stream.next_in = fill(1); stream.next_in = fill(1);
stream.avail_in = input_len; stream.avail_in = input_len;
} }
inflateEnd(&stream); git_inflate_end(&stream);
return buf; return buf;
} }
@ -382,9 +382,9 @@ static void *get_data_from_pack(struct object_entry *obj)
stream.avail_out = obj->size; stream.avail_out = obj->size;
stream.next_in = src; stream.next_in = src;
stream.avail_in = len; stream.avail_in = len;
inflateInit(&stream); git_inflate_init(&stream);
while ((st = inflate(&stream, Z_FINISH)) == Z_OK); while ((st = git_inflate(&stream, Z_FINISH)) == Z_OK);
inflateEnd(&stream); git_inflate_end(&stream);
if (st != Z_STREAM_END || stream.total_out != obj->size) if (st != Z_STREAM_END || stream.total_out != obj->size)
die("serious inflate inconsistency"); die("serious inflate inconsistency");
free(src); free(src);

View File

@ -1196,8 +1196,8 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
stream->avail_out = bufsiz; stream->avail_out = bufsiz;
if (legacy_loose_object(map)) { if (legacy_loose_object(map)) {
inflateInit(stream); git_inflate_init(stream);
return inflate(stream, 0); return git_inflate(stream, 0);
} }
@ -1217,7 +1217,7 @@ static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned lon
/* Set up the stream for the rest.. */ /* Set up the stream for the rest.. */
stream->next_in = map; stream->next_in = map;
stream->avail_in = mapsize; stream->avail_in = mapsize;
inflateInit(stream); git_inflate_init(stream);
/* And generate the fake traditional header */ /* And generate the fake traditional header */
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu",
@ -1254,11 +1254,11 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size
stream->next_out = buf + bytes; stream->next_out = buf + bytes;
stream->avail_out = size - bytes; stream->avail_out = size - bytes;
while (status == Z_OK) while (status == Z_OK)
status = inflate(stream, Z_FINISH); status = git_inflate(stream, Z_FINISH);
} }
buf[size] = 0; buf[size] = 0;
if (status == Z_STREAM_END && !stream->avail_in) { if (status == Z_STREAM_END && !stream->avail_in) {
inflateEnd(stream); git_inflate_end(stream);
return buf; return buf;
} }
@ -1348,15 +1348,15 @@ unsigned long get_size_from_delta(struct packed_git *p,
stream.next_out = delta_head; stream.next_out = delta_head;
stream.avail_out = sizeof(delta_head); stream.avail_out = sizeof(delta_head);
inflateInit(&stream); git_inflate_init(&stream);
do { do {
in = use_pack(p, w_curs, curpos, &stream.avail_in); in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in; stream.next_in = in;
st = inflate(&stream, Z_FINISH); st = git_inflate(&stream, Z_FINISH);
curpos += stream.next_in - in; curpos += stream.next_in - in;
} while ((st == Z_OK || st == Z_BUF_ERROR) && } while ((st == Z_OK || st == Z_BUF_ERROR) &&
stream.total_out < sizeof(delta_head)); stream.total_out < sizeof(delta_head));
inflateEnd(&stream); git_inflate_end(&stream);
if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head)) { if ((st != Z_STREAM_END) && stream.total_out != sizeof(delta_head)) {
error("delta data unpack-initial failed"); error("delta data unpack-initial failed");
return 0; return 0;
@ -1585,14 +1585,14 @@ static void *unpack_compressed_entry(struct packed_git *p,
stream.next_out = buffer; stream.next_out = buffer;
stream.avail_out = size; stream.avail_out = size;
inflateInit(&stream); git_inflate_init(&stream);
do { do {
in = use_pack(p, w_curs, curpos, &stream.avail_in); in = use_pack(p, w_curs, curpos, &stream.avail_in);
stream.next_in = in; stream.next_in = in;
st = inflate(&stream, Z_FINISH); st = git_inflate(&stream, Z_FINISH);
curpos += stream.next_in - in; curpos += stream.next_in - in;
} while (st == Z_OK || st == Z_BUF_ERROR); } while (st == Z_OK || st == Z_BUF_ERROR);
inflateEnd(&stream); git_inflate_end(&stream);
if ((st != Z_STREAM_END) || stream.total_out != size) { if ((st != Z_STREAM_END) || stream.total_out != size) {
free(buffer); free(buffer);
return NULL; return NULL;
@ -2020,7 +2020,7 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
status = error("unable to parse %s header", sha1_to_hex(sha1)); status = error("unable to parse %s header", sha1_to_hex(sha1));
else if (sizep) else if (sizep)
*sizep = size; *sizep = size;
inflateEnd(&stream); git_inflate_end(&stream);
munmap(map, mapsize); munmap(map, mapsize);
return status; return status;
} }

View File

@ -196,3 +196,63 @@ int xmkstemp(char *template)
die("Unable to create temporary file: %s", strerror(errno)); die("Unable to create temporary file: %s", strerror(errno));
return fd; return fd;
} }
/*
* zlib wrappers to make sure we don't silently miss errors
* at init time.
*/
void git_inflate_init(z_streamp strm)
{
const char *err;
switch (inflateInit(strm)) {
case Z_OK:
return;
case Z_MEM_ERROR:
err = "out of memory";
break;
case Z_VERSION_ERROR:
err = "wrong version";
break;
default:
err = "error";
}
die("inflateInit: %s (%s)", err, strm->msg ? strm->msg : "no message");
}
void git_inflate_end(z_streamp strm)
{
if (inflateEnd(strm) != Z_OK)
error("inflateEnd: %s", strm->msg ? strm->msg : "failed");
}
int git_inflate(z_streamp strm, int flush)
{
int ret = inflate(strm, flush);
const char *err;
switch (ret) {
/* Out of memory is fatal. */
case Z_MEM_ERROR:
die("inflate: out of memory");
/* Data corruption errors: we may want to recover from them (fsck) */
case Z_NEED_DICT:
err = "needs dictionary"; break;
case Z_DATA_ERROR:
err = "data stream error"; break;
case Z_STREAM_ERROR:
err = "stream consistency error"; break;
default:
err = "unknown error"; break;
/* Z_BUF_ERROR: normal, needs more space in the output buffer */
case Z_BUF_ERROR:
case Z_OK:
case Z_STREAM_END:
return ret;
}
error("inflate: %s (%s)", err, strm->msg ? strm->msg : "no message");
return ret;
}