summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-05-04 15:32:52 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-05-04 22:22:48 +0200
commit2b975a449c17268f943403176a7609079b7af084 (patch)
treefee51e2f4b4f424c9a55dc35fb7aad21e3ce6580
parent6f7ee71165b30272a4f18bca361c324c7671680c (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.h3
-rw-r--r--include/meta_reader.h1
-rw-r--r--include/meta_writer.h3
-rw-r--r--lib/comp/lzma.c34
-rw-r--r--lib/comp/zlib.c13
-rw-r--r--lib/sqfs/frag_reader.c7
-rw-r--r--lib/sqfs/meta_reader.c8
-rw-r--r--lib/sqfs/meta_writer.c10
-rw-r--r--lib/sqfs/super.c4
-rw-r--r--mkfs/block.c27
-rw-r--r--mkfs/mksquashfs.h1
-rw-r--r--mkfs/options.c3
-rw-r--r--unpack/extract_file.c13
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;