Fix buffer sizing for LZ4.

Fix exit condition checks in LZ4 decompression wrapper.
This commit is contained in:
Moinak Ghosh 2012-08-04 17:55:20 +05:30
parent f9215b53fb
commit 2cbcb0c9e4
3 changed files with 50 additions and 10 deletions

View file

@ -32,6 +32,8 @@
#include <lz4hc.h>
#include <allocator.h>
#define LZ4_MAX_CHUNK 2147450621L
struct lz4_params {
int level;
};
@ -41,14 +43,23 @@ lz4_stats(int show)
{
}
int
lz4_buf_extra(ssize_t buflen)
{
if (buflen > LZ4_MAX_CHUNK)
buflen = LZ4_MAX_CHUNK;
return (LZ4_compressBound(buflen) - buflen + sizeof(int));
}
int
lz4_init(void **data, int *level, ssize_t chunksize)
{
struct lz4_params *lzdat;
int lev;
if (chunksize > INT_MAX) {
fprintf(stderr, "Chunk size too big for LZ4.\n");
if (chunksize > LZ4_MAX_CHUNK) {
fprintf(stderr, "Max allowed chunk size for LZ4 is: %d \n",
LZ4_MAX_CHUNK);
return (1);
}
lzdat = slab_alloc(NULL, sizeof (struct lz4_params));
@ -85,12 +96,13 @@ lz4_compress(void *src, size_t srclen, void *dst, size_t *dstlen,
if (lzdat->level == 1) {
rv = LZ4_compress(src, dst, _srclen);
} else if (lzdat->level == 2) {
rv = LZ4_compress(src, dst, _srclen);
if (rv == 0) {
if (rv == 0 || rv > *dstlen) {
return (-1);
}
dst2 = slab_alloc(NULL, rv + sizeof (int));
dst2 = slab_alloc(NULL, rv + sizeof (int) + LZ4_compressBound(rv));
*((int *)dst2) = htonl(rv);
rv = LZ4_compressHC(dst, dst2 + sizeof (int), rv);
if (rv != 0) {
@ -120,20 +132,23 @@ lz4_decompress(void *src, size_t srclen, void *dst, size_t *dstlen,
if (lzdat->level == 1 || lzdat->level == 3) {
rv = LZ4_uncompress(src, dst, _dstlen);
if (rv != srclen) {
return (-1);
}
} else if (lzdat->level == 2) {
int sz1;
sz1 = ntohl(*((int *)src));
rv = LZ4_uncompress(src + sizeof (int), dst, sz1);
if (rv != sz1) {
if (rv != srclen - sizeof (int)) {
return (-1);
}
memcpy(src, dst, sz1);
rv = LZ4_uncompress(src, dst, _dstlen);
}
if (rv != srclen) {
return (-1);
if (rv != sz1) {
return (-1);
}
}
return (0);
}

28
main.c
View file

@ -398,8 +398,20 @@ start_decompress(const char *filename, const char *to_filename)
goto uncomp_done;
}
compressed_chunksize = chunksize + (chunksize >> 6) + sizeof (uint64_t)
+ sizeof (chunksize);
compressed_chunksize = chunksize + sizeof (chunksize) +
sizeof (uint64_t) + sizeof (chunksize) + zlib_buf_extra(chunksize);
/*
* Adjust for LZ4 overflow size if LZ4 was selected.
* TODO: A more generic way to handle this for various algos. I'm too
* lazy to do this at present.
*/
if (strncmp(algo, "lz4", 3) == 0) {
if (chunksize + lz4_buf_extra(chunksize) > compressed_chunksize) {
compressed_chunksize += (chunksize + lz4_buf_extra(chunksize) -
compressed_chunksize);
}
}
if (flags & FLAG_DEDUP) {
enable_rabin_scan = 1;
@ -804,6 +816,18 @@ start_compress(const char *filename, uint64_t chunksize, int level)
compressed_chunksize = chunksize + sizeof (chunksize) +
sizeof (uint64_t) + sizeof (chunksize) + zlib_buf_extra(chunksize);
/*
* Adjust for LZ4 overflow size if LZ4 was selected.
* TODO: A more generic way to handle this for various algos. I'm too
* lazy to do this at present.
*/
if (strncmp(algo, "lz4", 3) == 0) {
if (chunksize + lz4_buf_extra(chunksize) > compressed_chunksize) {
compressed_chunksize += (chunksize + lz4_buf_extra(chunksize) -
compressed_chunksize);
}
}
flags = 0;
if (enable_rabin_scan) {
flags |= FLAG_DEDUP;

View file

@ -56,6 +56,7 @@ extern uint64_t lzma_crc64(const uint8_t *buf, size_t size, uint64_t crc);
extern uint64_t lzma_crc64_8bchk(const uint8_t *buf, size_t size,
uint64_t crc, uint64_t *cnt);
extern uint32_t zlib_buf_extra(ssize_t buflen);
extern int lz4_buf_extra(ssize_t buflen);
extern int zlib_compress(void *src, size_t srclen, void *dst,
size_t *destlen, int level, uchar_t chdr, void *data);