From 0e5b6af9b0843e8b0021b9c83fb33d7950fe2ac6 Mon Sep 17 00:00:00 2001 From: Kalle Olavi Niemitalo Date: Sat, 24 Feb 2007 22:51:12 +0200 Subject: [PATCH] Various comments and tweaks in bzip2 decoding. Do not assume that memset(ptr, 0, size) clears pointers to NULL. The length of decoded data can be read in two ways; assert they match. --- src/encoding/bzip2.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/encoding/bzip2.c b/src/encoding/bzip2.c index e3ddfe76d..9df4c658c 100644 --- a/src/encoding/bzip2.c +++ b/src/encoding/bzip2.c @@ -20,29 +20,52 @@ #include "encoding/encoding.h" #include "util/memory.h" +/* How many bytes of compressed data to read before decompressing. + * This is currently defined as BZ_MAX_UNUSED to make the behaviour + * similar to BZ2_bzRead; but other values would work too. */ #define ELINKS_BZ_BUFFER_LENGTH BZ_MAX_UNUSED struct bz2_enc_data { bz_stream fbz_stream; + + /* The file descriptor from which we read. */ int fdread; - int last_read; /* If err after last bzDecompress was BZ_STREAM_END.. */ - unsigned char buf[ELINKS_BZ_BUFFER_LENGTH]; /* must be the last */ + + /* Initially 0; set to 1 when BZ2_bzDecompress indicates + * BZ_STREAM_END, which means it has found the bzip2-specific + * end-of-stream marker and all data has been decompressed. + * Then we neither read from the file nor call BZ2_bzDecompress + * any more. */ + int last_read; + + /* A buffer for data that has been read from the file but not + * yet decompressed. fbz_stream.next_in and fbz_stream.avail_in + * refer to this buffer. */ + unsigned char buf[ELINKS_BZ_BUFFER_LENGTH]; }; static int bzip2_open(struct stream_encoded *stream, int fd) { + /* A zero-initialized bz_stream. The compiler ensures that all + * pointer members in it are null. (Can't do this with memset + * because C99 does not require all-bits-zero to be a null + * pointer.) */ + static const bz_stream null_bz_stream = {0}; + struct bz2_enc_data *data = mem_alloc(sizeof(*data)); int err; - stream->data = 0; + stream->data = NULL; if (!data) { return -1; } - memset(data, 0, sizeof(struct bz2_enc_data) - ELINKS_BZ_BUFFER_LENGTH); - data->last_read = 0; + /* Initialize all members of *data, except data->buf[], which + * will be initialized on demand by bzip2_read. */ + copy_struct(&data->fbz_stream, &null_bz_stream); data->fdread = fd; + data->last_read = 0; err = BZ2_bzDecompressInit(&data->fbz_stream, 0, 0); if (err != BZ_OK) { @@ -97,7 +120,8 @@ bzip2_read(struct stream_encoded *stream, unsigned char *buf, int len) return -1; } } while (data->fbz_stream.avail_out > 0); - + + assert(len - data->fbz_stream.avail_out == data->fbz_stream.next_out - (char *) buf); return len - data->fbz_stream.avail_out; }