Fix buffer sizing for LZ4.
Fix exit condition checks in LZ4 decompression wrapper.
This commit is contained in:
parent
f9215b53fb
commit
2cbcb0c9e4
3 changed files with 50 additions and 10 deletions
|
@ -32,6 +32,8 @@
|
||||||
#include <lz4hc.h>
|
#include <lz4hc.h>
|
||||||
#include <allocator.h>
|
#include <allocator.h>
|
||||||
|
|
||||||
|
#define LZ4_MAX_CHUNK 2147450621L
|
||||||
|
|
||||||
struct lz4_params {
|
struct lz4_params {
|
||||||
int level;
|
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
|
int
|
||||||
lz4_init(void **data, int *level, ssize_t chunksize)
|
lz4_init(void **data, int *level, ssize_t chunksize)
|
||||||
{
|
{
|
||||||
struct lz4_params *lzdat;
|
struct lz4_params *lzdat;
|
||||||
int lev;
|
int lev;
|
||||||
|
|
||||||
if (chunksize > INT_MAX) {
|
if (chunksize > LZ4_MAX_CHUNK) {
|
||||||
fprintf(stderr, "Chunk size too big for LZ4.\n");
|
fprintf(stderr, "Max allowed chunk size for LZ4 is: %d \n",
|
||||||
|
LZ4_MAX_CHUNK);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
lzdat = slab_alloc(NULL, sizeof (struct lz4_params));
|
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) {
|
if (lzdat->level == 1) {
|
||||||
rv = LZ4_compress(src, dst, _srclen);
|
rv = LZ4_compress(src, dst, _srclen);
|
||||||
|
|
||||||
} else if (lzdat->level == 2) {
|
} else if (lzdat->level == 2) {
|
||||||
rv = LZ4_compress(src, dst, _srclen);
|
rv = LZ4_compress(src, dst, _srclen);
|
||||||
if (rv == 0) {
|
if (rv == 0 || rv > *dstlen) {
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
dst2 = slab_alloc(NULL, rv + sizeof (int));
|
dst2 = slab_alloc(NULL, rv + sizeof (int) + LZ4_compressBound(rv));
|
||||||
*((int *)dst2) = htonl(rv);
|
*((int *)dst2) = htonl(rv);
|
||||||
rv = LZ4_compressHC(dst, dst2 + sizeof (int), rv);
|
rv = LZ4_compressHC(dst, dst2 + sizeof (int), rv);
|
||||||
if (rv != 0) {
|
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) {
|
if (lzdat->level == 1 || lzdat->level == 3) {
|
||||||
rv = LZ4_uncompress(src, dst, _dstlen);
|
rv = LZ4_uncompress(src, dst, _dstlen);
|
||||||
|
if (rv != srclen) {
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (lzdat->level == 2) {
|
} else if (lzdat->level == 2) {
|
||||||
int sz1;
|
int sz1;
|
||||||
|
|
||||||
sz1 = ntohl(*((int *)src));
|
sz1 = ntohl(*((int *)src));
|
||||||
rv = LZ4_uncompress(src + sizeof (int), dst, sz1);
|
rv = LZ4_uncompress(src + sizeof (int), dst, sz1);
|
||||||
if (rv != sz1) {
|
if (rv != srclen - sizeof (int)) {
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
memcpy(src, dst, sz1);
|
memcpy(src, dst, sz1);
|
||||||
rv = LZ4_uncompress(src, dst, _dstlen);
|
rv = LZ4_uncompress(src, dst, _dstlen);
|
||||||
}
|
if (rv != sz1) {
|
||||||
if (rv != srclen) {
|
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
28
main.c
28
main.c
|
@ -398,8 +398,20 @@ start_decompress(const char *filename, const char *to_filename)
|
||||||
goto uncomp_done;
|
goto uncomp_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
compressed_chunksize = chunksize + (chunksize >> 6) + sizeof (uint64_t)
|
compressed_chunksize = chunksize + sizeof (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) {
|
if (flags & FLAG_DEDUP) {
|
||||||
enable_rabin_scan = 1;
|
enable_rabin_scan = 1;
|
||||||
|
@ -804,6 +816,18 @@ start_compress(const char *filename, uint64_t chunksize, int level)
|
||||||
compressed_chunksize = chunksize + sizeof (chunksize) +
|
compressed_chunksize = chunksize + sizeof (chunksize) +
|
||||||
sizeof (uint64_t) + sizeof (chunksize) + zlib_buf_extra(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;
|
flags = 0;
|
||||||
if (enable_rabin_scan) {
|
if (enable_rabin_scan) {
|
||||||
flags |= FLAG_DEDUP;
|
flags |= FLAG_DEDUP;
|
||||||
|
|
|
@ -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,
|
extern uint64_t lzma_crc64_8bchk(const uint8_t *buf, size_t size,
|
||||||
uint64_t crc, uint64_t *cnt);
|
uint64_t crc, uint64_t *cnt);
|
||||||
extern uint32_t zlib_buf_extra(ssize_t buflen);
|
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,
|
extern int zlib_compress(void *src, size_t srclen, void *dst,
|
||||||
size_t *destlen, int level, uchar_t chdr, void *data);
|
size_t *destlen, int level, uchar_t chdr, void *data);
|
||||||
|
|
Loading…
Reference in a new issue