diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-05-04 15:32:52 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-05-04 22:22:48 +0200 | 
| commit | 2b975a449c17268f943403176a7609079b7af084 (patch) | |
| tree | fee51e2f4b4f424c9a55dc35fb7aad21e3ce6580 | |
| parent | 6f7ee71165b30272a4f18bca361c324c7671680c (diff) | |
Remove compressor internal buffers
Pass in an external destination buffer + size and allow for propper
bounds checking (especially when unpacking).
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
| -rw-r--r-- | include/compress.h | 3 | ||||
| -rw-r--r-- | include/meta_reader.h | 1 | ||||
| -rw-r--r-- | include/meta_writer.h | 3 | ||||
| -rw-r--r-- | lib/comp/lzma.c | 34 | ||||
| -rw-r--r-- | lib/comp/zlib.c | 13 | ||||
| -rw-r--r-- | lib/sqfs/frag_reader.c | 7 | ||||
| -rw-r--r-- | lib/sqfs/meta_reader.c | 8 | ||||
| -rw-r--r-- | lib/sqfs/meta_writer.c | 10 | ||||
| -rw-r--r-- | lib/sqfs/super.c | 4 | ||||
| -rw-r--r-- | mkfs/block.c | 27 | ||||
| -rw-r--r-- | mkfs/mksquashfs.h | 1 | ||||
| -rw-r--r-- | mkfs/options.c | 3 | ||||
| -rw-r--r-- | unpack/extract_file.c | 13 | 
13 files changed, 77 insertions, 50 deletions
diff --git a/include/compress.h b/include/compress.h index d527307..ad193e8 100644 --- a/include/compress.h +++ b/include/compress.h @@ -12,7 +12,8 @@  typedef struct compressor_t compressor_t;  struct compressor_t { -	ssize_t (*do_block)(compressor_t *cmp, uint8_t *block, size_t outsize); +	ssize_t (*do_block)(compressor_t *cmp, const uint8_t *in, size_t size, +			    uint8_t *out, size_t outsize);  	void (*destroy)(compressor_t *stream);  }; diff --git a/include/meta_reader.h b/include/meta_reader.h index 1fb527a..3085383 100644 --- a/include/meta_reader.h +++ b/include/meta_reader.h @@ -12,6 +12,7 @@ typedef struct {  	int fd;  	compressor_t *cmp;  	uint8_t data[SQFS_META_BLOCK_SIZE]; +	uint8_t scratch[SQFS_META_BLOCK_SIZE];  } meta_reader_t;  meta_reader_t *meta_reader_create(int fd, compressor_t *cmp); diff --git a/include/meta_writer.h b/include/meta_writer.h index 03f9a2e..7f1be9a 100644 --- a/include/meta_writer.h +++ b/include/meta_writer.h @@ -6,11 +6,12 @@  #include "squashfs.h"  typedef struct { -	uint8_t data[SQFS_META_BLOCK_SIZE + 2];  	size_t offset;  	size_t block_offset;  	int outfd;  	compressor_t *cmp; +	uint8_t data[SQFS_META_BLOCK_SIZE + 2]; +	uint8_t scratch[SQFS_META_BLOCK_SIZE + 2];  } meta_writer_t;  meta_writer_t *meta_writer_create(int fd, compressor_t *cmp); diff --git a/lib/comp/lzma.c b/lib/comp/lzma.c index fd2a6c7..3169c33 100644 --- a/lib/comp/lzma.c +++ b/lib/comp/lzma.c @@ -9,12 +9,11 @@  typedef struct {  	compressor_t base; -  	size_t block_size; -	uint8_t buffer[];  } lzma_compressor_t; -static ssize_t lzma_comp_block(compressor_t *base, uint8_t *block, size_t size) +static ssize_t lzma_comp_block(compressor_t *base, const uint8_t *in, +			       size_t size, uint8_t *out, size_t outsize)  {  	lzma_compressor_t *lzma = (lzma_compressor_t *)base;  	lzma_filter filters[5]; @@ -36,16 +35,10 @@ static ssize_t lzma_comp_block(compressor_t *base, uint8_t *block, size_t size)  	filters[1].options = NULL;  	ret = lzma_stream_buffer_encode(filters, LZMA_CHECK_CRC32, NULL, -					block, size, lzma->buffer, -					&written, lzma->block_size); - -	if (ret == LZMA_OK) { -		if (written >= size) -			return 0; +					in, size, out, &written, outsize); -		memcpy(block, lzma->buffer, size); -		return written; -	} +	if (ret == LZMA_OK) +		return (written >= size) ? 0 : written;  	if (ret != LZMA_BUF_ERROR) {  		fputs("lzma block compress failed\n", stderr); @@ -55,24 +48,21 @@ static ssize_t lzma_comp_block(compressor_t *base, uint8_t *block, size_t size)  	return 0;  } -static ssize_t lzma_uncomp_block(compressor_t *base, uint8_t *block, -				 size_t size) +static ssize_t lzma_uncomp_block(compressor_t *base, const uint8_t *in, +				 size_t size, uint8_t *out, size_t outsize)  { -	lzma_compressor_t *lzma = (lzma_compressor_t *)base;  	uint64_t memlimit = 32 * 1024 * 1024;  	size_t dest_pos = 0;  	size_t src_pos = 0;  	lzma_ret ret; +	(void)base;  	ret = lzma_stream_buffer_decode(&memlimit, 0, NULL, -					block, &src_pos, size, -					lzma->buffer, &dest_pos, -					lzma->block_size); +					in, &src_pos, size, +					out, &dest_pos, outsize); -	if (ret == LZMA_OK && size == src_pos) { -		memcpy(block, lzma->buffer, dest_pos); +	if (ret == LZMA_OK && size == src_pos)  		return (ssize_t)dest_pos; -	}  	fputs("lzma block extract failed\n", stderr);  	return -1; @@ -85,7 +75,7 @@ static void lzma_destroy(compressor_t *base)  compressor_t *create_lzma_compressor(bool compress, size_t block_size)  { -	lzma_compressor_t *lzma = calloc(1, sizeof(*lzma) + block_size); +	lzma_compressor_t *lzma = calloc(1, sizeof(*lzma));  	compressor_t *base = (compressor_t *)lzma;  	if (lzma == NULL) { diff --git a/lib/comp/zlib.c b/lib/comp/zlib.c index d3bfe70..f151132 100644 --- a/lib/comp/zlib.c +++ b/lib/comp/zlib.c @@ -14,7 +14,6 @@ typedef struct {  	bool compress;  	size_t block_size; -	uint8_t buffer[];  } zlib_compressor_t;  static void zlib_destroy(compressor_t *base) @@ -30,7 +29,8 @@ static void zlib_destroy(compressor_t *base)  	free(zlib);  } -static ssize_t zlib_do_block(compressor_t *base, uint8_t *block, size_t size) +static ssize_t zlib_do_block(compressor_t *base, const uint8_t *in, +			     size_t size, uint8_t *out, size_t outsize)  {  	zlib_compressor_t *zlib = (zlib_compressor_t *)base;  	size_t written; @@ -47,10 +47,10 @@ static ssize_t zlib_do_block(compressor_t *base, uint8_t *block, size_t size)  		return -1;  	} -	zlib->strm.next_in = (void *)block; +	zlib->strm.next_in = (void *)in;  	zlib->strm.avail_in = size; -	zlib->strm.next_out = zlib->buffer; -	zlib->strm.avail_out = zlib->block_size; +	zlib->strm.next_out = out; +	zlib->strm.avail_out = outsize;  	if (zlib->compress) {  		ret = deflate(&zlib->strm, Z_FINISH); @@ -64,7 +64,6 @@ static ssize_t zlib_do_block(compressor_t *base, uint8_t *block, size_t size)  		if (zlib->compress && written >= size)  			return 0; -		memcpy(block, zlib->buffer, written);  		return (ssize_t)written;  	} @@ -78,7 +77,7 @@ static ssize_t zlib_do_block(compressor_t *base, uint8_t *block, size_t size)  compressor_t *create_zlib_compressor(bool compress, size_t block_size)  { -	zlib_compressor_t *zlib = calloc(1, sizeof(*zlib) + block_size); +	zlib_compressor_t *zlib = calloc(1, sizeof(*zlib));  	compressor_t *base = (compressor_t *)zlib;  	int ret; diff --git a/lib/sqfs/frag_reader.c b/lib/sqfs/frag_reader.c index 1906376..74fd292 100644 --- a/lib/sqfs/frag_reader.c +++ b/lib/sqfs/frag_reader.c @@ -42,12 +42,15 @@ static int precache_block(frag_reader_t *f, size_t i)  	}  	if (compressed) { -		ret = f->cmp->do_block(f->cmp, f->buffer, size); +		ret = f->cmp->do_block(f->cmp, f->buffer, size, +				       f->buffer + f->block_size, f->block_size);  		if (ret <= 0) {  			fputs("extracting fragment failed\n", stderr);  			return -1;  		} + +		memmove(f->buffer, f->buffer + f->block_size, ret);  	}  	f->current_index = i; @@ -73,7 +76,7 @@ frag_reader_t *frag_reader_create(sqfs_super_t *super, int fd,  		++blockcount;  	/* pre allocate all the stuff */ -	f = calloc(1, sizeof(*f) + super->block_size); +	f = calloc(1, sizeof(*f) + super->block_size * 2);  	if (f == NULL)  		goto fail_rd; diff --git a/lib/sqfs/meta_reader.c b/lib/sqfs/meta_reader.c index 8cd7c8f..1a70238 100644 --- a/lib/sqfs/meta_reader.c +++ b/lib/sqfs/meta_reader.c @@ -79,12 +79,18 @@ int meta_reader_seek(meta_reader_t *m, uint64_t block_start, size_t offset)  		goto fail_trunc;  	if (compressed) { -		ret = m->cmp->do_block(m->cmp, m->data, size); +		ret = m->cmp->do_block(m->cmp, m->data, size, +				       m->scratch, sizeof(m->scratch));  		if (ret <= 0) {  			fputs("error uncompressing meta data block\n", stderr);  			return -1;  		} + +		memcpy(m->data, m->scratch, ret); + +		if ((size_t)ret < sizeof(m->data)) +			memset(m->data + ret, 0, sizeof(m->data) - ret);  	}  	return 0; diff --git a/lib/sqfs/meta_writer.c b/lib/sqfs/meta_writer.c index 95092d5..77ceeb9 100644 --- a/lib/sqfs/meta_writer.c +++ b/lib/sqfs/meta_writer.c @@ -30,23 +30,27 @@ void meta_writer_destroy(meta_writer_t *m)  int meta_writer_flush(meta_writer_t *m)  {  	ssize_t ret, count; +	void *ptr;  	if (m->offset == 0)  		return 0; -	ret = m->cmp->do_block(m->cmp, m->data + 2, m->offset); +	ret = m->cmp->do_block(m->cmp, m->data + 2, m->offset, +			       m->scratch + 2, sizeof(m->scratch) - 2);  	if (ret < 0)  		return -1;  	if (ret > 0) { -		((uint16_t *)m->data)[0] = htole16(ret); +		((uint16_t *)m->scratch)[0] = htole16(ret);  		count = ret + 2; +		ptr = m->scratch;  	} else {  		((uint16_t *)m->data)[0] = htole16(m->offset | 0x8000);  		count = m->offset + 2; +		ptr = m->data;  	} -	ret = write_retry(m->outfd, m->data, count); +	ret = write_retry(m->outfd, ptr, count);  	if (ret < 0) {  		perror("writing meta data"); diff --git a/lib/sqfs/super.c b/lib/sqfs/super.c index b402496..d3b79c6 100644 --- a/lib/sqfs/super.c +++ b/lib/sqfs/super.c @@ -17,8 +17,8 @@ int sqfs_super_init(sqfs_super_t *super, size_t block_size, uint32_t mtime,  		return -1;  	} -	if (block_size < 8192 || block_size >= (1 << 24)) { -		fputs("Block size must be between 8k and 1M\n", stderr); +	if (block_size < 4096 || block_size >= (1 << 24)) { +		fputs("Block size must be between 4k and 1M\n", stderr);  		return -1;  	} diff --git a/mkfs/block.c b/mkfs/block.c index d68c0c7..3472346 100644 --- a/mkfs/block.c +++ b/mkfs/block.c @@ -6,22 +6,26 @@ static int write_block(file_info_t *fi, sqfs_info_t *info)  {  	size_t idx, bs;  	ssize_t ret; +	void *ptr;  	idx = info->file_block_count++;  	bs = info->super.block_size; -	ret = info->cmp->do_block(info->cmp, info->block, bs); +	ret = info->cmp->do_block(info->cmp, info->block, bs, +				  info->scratch, bs);  	if (ret < 0)  		return -1;  	if (ret > 0) { +		ptr = info->scratch;  		bs = ret;  		fi->blocksizes[idx] = bs;  	} else { +		ptr = info->block;  		fi->blocksizes[idx] = bs | (1 << 24);  	} -	ret = write_retry(info->outfd, info->block, bs); +	ret = write_retry(info->outfd, ptr, bs);  	if (ret < 0) {  		perror("writing to output file");  		return -1; @@ -41,8 +45,8 @@ static int flush_fragments(sqfs_info_t *info)  	size_t newsz, size;  	file_info_t *fi;  	uint64_t offset; +	void *new, *ptr;  	ssize_t ret; -	void *new;  	if (info->num_fragments == info->max_fragments) {  		newsz = info->max_fragments ? info->max_fragments * 2 : 16; @@ -64,7 +68,8 @@ static int flush_fragments(sqfs_info_t *info)  	for (fi = info->frag_list; fi != NULL; fi = fi->frag_next)  		fi->fragment = info->num_fragments; -	ret = info->cmp->do_block(info->cmp, info->fragment, size); +	ret = info->cmp->do_block(info->cmp, info->fragment, size, +				  info->scratch, info->super.block_size);  	if (ret < 0)  		return -1; @@ -72,16 +77,18 @@ static int flush_fragments(sqfs_info_t *info)  	info->fragments[info->num_fragments].pad0 = 0;  	if (ret > 0) { +		ptr = info->scratch;  		size = ret;  		info->fragments[info->num_fragments].size = htole32(size);  	} else { +		ptr = info->fragment;  		info->fragments[info->num_fragments].size =  			htole32(size | (1 << 24));  	}  	info->num_fragments += 1; -	ret = write_retry(info->outfd, info->fragment, size); +	ret = write_retry(info->outfd, ptr, size);  	if (ret < 0) {  		perror("writing to output file");  		return -1; @@ -203,12 +210,22 @@ int write_data_to_image(sqfs_info_t *info)  		return -1;  	} +	info->scratch = malloc(info->super.block_size); +	if (info->scratch == NULL) { +		perror("allocating scratch buffer"); +		free(info->block); +		free(info->fragment); +		return -1; +	} +  	ret = find_and_process_files(info, info->fs.root);  	free(info->block);  	free(info->fragment); +	free(info->scratch);  	info->block = NULL;  	info->fragment = NULL; +	info->scratch = NULL;  	return ret;  } diff --git a/mkfs/mksquashfs.h b/mkfs/mksquashfs.h index f4ab53a..106822c 100644 --- a/mkfs/mksquashfs.h +++ b/mkfs/mksquashfs.h @@ -36,6 +36,7 @@ typedef struct {  	fstree_t fs;  	void *block;  	void *fragment; +	void *scratch;  	sqfs_fragment_t *fragments;  	size_t num_fragments; diff --git a/mkfs/options.c b/mkfs/options.c index a1077b4..f1fe192 100644 --- a/mkfs/options.c +++ b/mkfs/options.c @@ -248,8 +248,7 @@ void process_command_line(options_t *opt, int argc, char **argv)  			break;  		case 'b':  			opt->blksz = read_number("Block size", optarg, -						 SQFS_META_BLOCK_SIZE, -						 0xFFFFFFFF); +						 4096, (1 << 20) - 1);  			break;  		case 'B':  			opt->devblksz = read_number("Device block size", optarg, diff --git a/unpack/extract_file.c b/unpack/extract_file.c index c18ace8..368f6d7 100644 --- a/unpack/extract_file.c +++ b/unpack/extract_file.c @@ -4,18 +4,19 @@  int extract_file(file_info_t *fi, compressor_t *cmp, size_t block_size,  		 frag_reader_t *frag, int sqfsfd, int outfd)  { +	void *buffer, *scratch, *ptr;  	size_t i, count, fragsz;  	bool compressed; -	void *buffer;  	uint32_t bs;  	ssize_t ret; -	buffer = malloc(block_size); +	buffer = malloc(block_size * 2);  	if (buffer == NULL) {  		perror("allocating scratch buffer");  		return -1;  	} +	scratch = (char *)buffer + block_size;  	count = fi->size / block_size;  	if (count > 0) { @@ -39,14 +40,18 @@ int extract_file(file_info_t *fi, compressor_t *cmp, size_t block_size,  				goto fail_trunc;  			if (compressed) { -				ret = cmp->do_block(cmp, buffer, bs); +				ret = cmp->do_block(cmp, buffer, bs, +						    scratch, block_size);  				if (ret <= 0)  					goto fail;  				bs = ret; +				ptr = scratch; +			} else { +				ptr = buffer;  			} -			ret = write_retry(outfd, buffer, bs); +			ret = write_retry(outfd, ptr, bs);  			if (ret < 0)  				goto fail_wr;  | 
