]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
[linux] Fix decompression memory allocation 726/head
authorNick Terrell <terrelln@fb.com>
Mon, 19 Jun 2017 19:24:14 +0000 (12:24 -0700)
committerNick Terrell <terrelln@fb.com>
Mon, 19 Jun 2017 19:32:04 +0000 (12:32 -0700)
contrib/linux-kernel/lib/zstd/decompress.c
contrib/linux-kernel/test/UserlandTest.cpp
contrib/linux-kernel/zstd.diff

index def10ea4de7c0c6af9db1e962d74b096b5927439..ec673d7e6b564f63983b2d36b4293b1f509ec8f4 100644 (file)
@@ -2212,6 +2212,20 @@ ZSTD_DStream *ZSTD_initDStream(size_t maxWindowSize, void *workspace, size_t wor
        zds->ddict = zds->ddictLocal;
        zds->legacyVersion = 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;
 }
 
@@ -2333,25 +2347,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB
                        if (zds->fParams.windowSize > zds->maxWindowSize)
                                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 neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
-                               zds->blockSize = blockSize;
+                               size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
+                               size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
                                if (zds->inBuffSize < blockSize) {
-                                       ZSTD_free(zds->inBuff, zds->customMem);
-                                       zds->inBuffSize = blockSize;
-                                       zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
-                                       if (zds->inBuff == NULL)
-                                               return ERROR(memory_allocation);
+                                       return ERROR(GENERIC);
                                }
                                if (zds->outBuffSize < neededOutSize) {
-                                       ZSTD_free(zds->outBuff, zds->customMem);
-                                       zds->outBuffSize = neededOutSize;
-                                       zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
-                                       if (zds->outBuff == NULL)
-                                               return ERROR(memory_allocation);
+                                       return ERROR(GENERIC);
                                }
+                               zds->blockSize = blockSize;
                        }
                        zds->stage = zdss_read;
                }
index 73b30be4c362549044b1d51d43edd9460bb470be..03058382fbf404ff93e2022b41ddeb146502b664 100644 (file)
@@ -280,9 +280,9 @@ TEST(Block, ContentSize) {
 
 TEST(Block, CCtxLevelIncrease) {
   std::string c;
-  auto cctx = createCCtx(6);
+  auto cctx = createCCtx(22);
   auto dctx = createDCtx();
-  for (int level = 1; level <= 6; ++level) {
+  for (int level = 1; level <= 22; ++level) {
     auto compressed = compress(*cctx, kData, level);
     auto const decompressed = decompress(*dctx, compressed, kData.size());
     EXPECT_EQ(kData, decompressed);
@@ -478,6 +478,17 @@ TEST(Stream, Flush) {
   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)                                                    \
   do {                                                                         \
     extern void *__##symbol;                                                   \
index 285961ab2655f70d5ab7282cc4b9f2b7f5c0607e..1fa64ff868c8d7a0e636d1e98e064687671eb8b5 100644 (file)
@@ -5068,10 +5068,10 @@ index 0000000..42236a3
 +MODULE_DESCRIPTION("Zstd Compressor");
 diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c
 new file mode 100644
-index 0000000..def10ea
+index 0000000..ec673d7
 --- /dev/null
 +++ b/lib/zstd/decompress.c
-@@ -0,0 +1,2508 @@
+@@ -0,0 +1,2514 @@
 +/**
 + * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
 + * All rights reserved.
@@ -7286,6 +7286,20 @@ index 0000000..def10ea
 +      zds->ddict = zds->ddictLocal;
 +      zds->legacyVersion = 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;
 +}
 +
@@ -7407,25 +7421,17 @@ index 0000000..def10ea
 +                      if (zds->fParams.windowSize > zds->maxWindowSize)
 +                              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 neededOutSize = zds->fParams.windowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
-+                              zds->blockSize = blockSize;
++                              size_t const blockSize = MIN(zds->maxWindowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
++                              size_t const neededOutSize = zds->maxWindowSize + blockSize + WILDCOPY_OVERLENGTH * 2;
 +                              if (zds->inBuffSize < blockSize) {
-+                                      ZSTD_free(zds->inBuff, zds->customMem);
-+                                      zds->inBuffSize = blockSize;
-+                                      zds->inBuff = (char *)ZSTD_malloc(blockSize, zds->customMem);
-+                                      if (zds->inBuff == NULL)
-+                                              return ERROR(memory_allocation);
++                                      return ERROR(GENERIC);
 +                              }
 +                              if (zds->outBuffSize < neededOutSize) {
-+                                      ZSTD_free(zds->outBuff, zds->customMem);
-+                                      zds->outBuffSize = neededOutSize;
-+                                      zds->outBuff = (char *)ZSTD_malloc(neededOutSize, zds->customMem);
-+                                      if (zds->outBuff == NULL)
-+                                              return ERROR(memory_allocation);
++                                      return ERROR(GENERIC);
 +                              }
++                              zds->blockSize = blockSize;
 +                      }
 +                      zds->stage = zdss_read;
 +              }