[linux] Fix decompression memory allocation

This commit is contained in:
Nick Terrell 2017-06-19 12:24:14 -07:00
parent 9cbb152582
commit 9ad11bea4e
3 changed files with 55 additions and 32 deletions

View File

@ -2212,6 +2212,20 @@ ZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace, size_t wor
zds->ddict = zds->ddictLocal; zds->ddict = zds->ddictLocal;
zds->legacyVersion = 0; zds->legacyVersion = 0;
zds->hostageByte = 0; zds->hostageByte = 0;
{
size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
zds->inBuffSize = blockSize;
zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
zds->outBuffSize = neededOutSize;
if (zds->inBuff == NULL || zds->outBuff == NULL) {
ZSTD_freeDStream(zds);
return NULL;
}
}
return zds; return zds;
} }
@ -2333,25 +2347,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB
if (zds->fParams.windowSize > zds->maxWindowSize) if (zds->fParams.windowSize > zds->maxWindowSize)
return ERROR(frameParameter_windowTooLarge); return ERROR(frameParameter_windowTooLarge);
/* Adapt buffer sizes to frame header instructions */ /* Buffers are preallocated, but double check */
{ {
size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2; size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
zds->blockSize = blockSize;
if (zds->inBuffSize < blockSize) { if (zds->inBuffSize < blockSize) {
ZSTD_free(zds->inBuff, zds->customMem); return ERROR(GENERIC);
zds->inBuffSize = blockSize;
zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
if (zds->inBuff == NULL)
return ERROR(memory_allocation);
} }
if (zds->outBuffSize < neededOutSize) { if (zds->outBuffSize < neededOutSize) {
ZSTD_free(zds->outBuff, zds->customMem); return ERROR(GENERIC);
zds->outBuffSize = neededOutSize;
zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
if (zds->outBuff == NULL)
return ERROR(memory_allocation);
} }
zds->blockSize = blockSize;
} }
zds->stage = zdss_read; zds->stage = zdss_read;
} }

View File

@ -280,9 +280,9 @@ TEST(Block, ContentSize) {
TEST(Block, CCtxLevelIncrease) { TEST(Block, CCtxLevelIncrease) {
std::string c; std::string c;
auto cctx = createCCtx(6); auto cctx = createCCtx(22);
auto dctx = createDCtx(); auto dctx = createDCtx();
for (int level = 1; level <= 6; ++level) { for (int level = 1; level <= 22; ++level) {
auto compressed = compress(*cctx, kData, level); auto compressed = compress(*cctx, kData, level);
auto const decompressed = decompress(*dctx, compressed, kData.size()); auto const decompressed = decompress(*dctx, compressed, kData.size());
EXPECT_EQ(kData, decompressed); EXPECT_EQ(kData, decompressed);
@ -478,6 +478,17 @@ TEST(Stream, Flush) {
EXPECT_EQ(kData, decompressed); EXPECT_EQ(kData, decompressed);
} }
TEST(Stream, DStreamLevelIncrease) {
auto zds = createDStream();
for (int level = 1; level <= 22; ++level) {
auto zcs = createCStream(level);
auto compressed = compress(*zcs, kData);
ZSTD_resetDStream(zds.get());
auto const decompressed = decompress(*zds, compressed, kData.size());
EXPECT_EQ(kData, decompressed);
}
}
#define TEST_SYMBOL(symbol) \ #define TEST_SYMBOL(symbol) \
do { \ do { \
extern void *__##symbol; \ extern void *__##symbol; \

View File

@ -5068,10 +5068,10 @@ index 0000000..42236a3
+MODULE_DESCRIPTION("Zstd Compressor"); +MODULE_DESCRIPTION("Zstd Compressor");
diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c
new file mode 100644 new file mode 100644
index 0000000..def10ea index 0000000..ec673d7
--- /dev/null --- /dev/null
+++ b/lib/zstd/decompress.c +++ b/lib/zstd/decompress.c
@@ -0,0 +1,2508 @@ @@ -0,0 +1,2514 @@
+/** +/**
+ * Copyright (c) 2016-present, Yann Collet, Facebook, Inc. + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
+ * All rights reserved. + * All rights reserved.
@ -7286,6 +7286,20 @@ index 0000000..def10ea
+ zds->ddict = zds->ddictLocal; + zds->ddict = zds->ddictLocal;
+ zds->legacyVersion = 0; + zds->legacyVersion = 0;
+ zds->hostageByte = 0; + zds->hostageByte = 0;
+
+ {
+ size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+ size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+
+ zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
+ zds->inBuffSize = blockSize;
+ zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
+ zds->outBuffSize = neededOutSize;
+ if (zds->inBuff == NULL || zds->outBuff == NULL) {
+ ZSTD_freeDStream(zds);
+ return NULL;
+ }
+ }
+ return zds; + return zds;
+} +}
+ +
@ -7407,25 +7421,17 @@ index 0000000..def10ea
+ if (zds->fParams.windowSize > zds->maxWindowSize) + if (zds->fParams.windowSize > zds->maxWindowSize)
+ return ERROR(frameParameter_windowTooLarge); + return ERROR(frameParameter_windowTooLarge);
+ +
+ /* Adapt buffer sizes to frame header instructions */ + /* Buffers are preallocated, but double check */
+ { + {
+ size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX); + size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+ size_t const neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2; + size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
+ zds->blockSize = blockSize;
+ if (zds->inBuffSize < blockSize) { + if (zds->inBuffSize < blockSize) {
+ ZSTD_free(zds->inBuff, zds->customMem); + return ERROR(GENERIC);
+ zds->inBuffSize = blockSize;
+ zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
+ if (zds->inBuff == NULL)
+ return ERROR(memory_allocation);
+ } + }
+ if (zds->outBuffSize < neededOutSize) { + if (zds->outBuffSize < neededOutSize) {
+ ZSTD_free(zds->outBuff, zds->customMem); + return ERROR(GENERIC);
+ zds->outBuffSize = neededOutSize;
+ zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
+ if (zds->outBuff == NULL)
+ return ERROR(memory_allocation);
+ } + }
+ zds->blockSize = blockSize;
+ } + }
+ zds->stage = zdss_read; + zds->stage = zdss_read;
+ } + }