Skip to content

Commit bb86258

Browse files
committed
Correct decoding of uncompressed frames
1 parent 055ac78 commit bb86258

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

src/Lz4/Frame.hs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,11 @@ import Lz4.Internal (requiredBufferSize,c_hs_compress_HC,c_hs_decompress_safe)
2121

2222
import Control.Monad (when)
2323
import Control.Monad.ST (runST)
24-
import Control.Monad.ST.Run (runByteArrayST)
2524
import Data.Bits ((.&.))
2625
import Data.Bytes.Types (Bytes (Bytes))
2726
import Data.Int (Int32)
2827
import Data.Primitive (ByteArray (..), MutableByteArray (..))
2928
import Data.Word (Word8, Word32)
30-
import GHC.Exts (ByteArray#,MutableByteArray#)
3129
import GHC.IO (unsafeIOToST)
3230

3331
import qualified Data.Primitive as PM
@@ -45,7 +43,7 @@ decompressU ::
4543
Int -- ^ The exact size of the decompressed bytes
4644
-> Bytes -- ^ Compressed bytes
4745
-> Maybe ByteArray
48-
decompressU !decompressedSize bytes@(Bytes arr@(ByteArray arr# ) off len) = do
46+
decompressU !decompressedSize (Bytes arr@(ByteArray arr# ) off len) = do
4947
when (len < 11) Nothing
5048
when (indexWord8 arr off /= 0x04) Nothing
5149
when (indexWord8 arr (off + 1) /= 0x22) Nothing
@@ -88,7 +86,8 @@ decompressU !decompressedSize bytes@(Bytes arr@(ByteArray arr# ) off len) = do
8886
-- suite, and I cannot find examples of this feature used in the wild.
8987
-- If anyone knows of an example, open a PR.
9088
when (decompressedSize /= compressedSizeI) Nothing
91-
Just $! Bytes.toByteArray bytes
89+
when (decompressedSize + 15 /= len) Nothing
90+
Just $! Bytes.toByteArrayClone (Bytes arr (off + 11) decompressedSize)
9291

9392
{- | Use HC compression to produce a frame with a single block.
9493
All optional fields (checksums, content sizes, and dictionary IDs)

test/Main.hs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Data.Primitive (ByteArray,sizeofByteArray)
66
import Data.Word (Word8)
77
import Lz4.Block (compress, compressHighly, decompress)
88
import Test.Tasty (TestTree, defaultMain, testGroup)
9-
import Test.Tasty.HUnit (testCase)
9+
import Test.Tasty.HUnit (testCase,(@=?))
1010
import Test.Tasty.QuickCheck (Gen, choose, forAll, testProperty, vectorOf, (===))
1111

1212
import qualified Data.Bytes as Bytes
@@ -39,6 +39,9 @@ tests = testGroup "lz4"
3939
, testCase "example-a" $ case Frame.decompressU 20 (Bytes.fromByteArray exampleA) of
4040
Nothing -> fail "decompression failed"
4141
Just _ -> pure ()
42+
, testCase "example-b" $ case Frame.decompressU 10 (Bytes.fromByteArray exampleB) of
43+
Nothing -> fail "decompression failed"
44+
Just x -> x @=? Exts.fromList [0xbb :: Word8, 0x01, 0xbb, 0x01, 0xbb, 0x01, 0xbb, 0x01, 0xbb, 0x01 ]
4245
]
4346
]
4447

@@ -62,3 +65,17 @@ exampleA = Exts.fromList
6265
, 0x47, 0x15, 0x08, 0x01, 0x0a, 0x04 , 0x00, 0x50, 0x0a, 0x15, 0x08, 0x01, 0x0a
6366
, 0x00, 0x00, 0x00, 0x00
6467
]
68+
69+
-- Example that tests a frame that does not use compression
70+
exampleB :: ByteArray
71+
exampleB = Exts.fromList
72+
[ 0x04, 0x22, 0x4d, (0x18 :: Word8)
73+
, 0x60, 0x40, 0x82
74+
, 0x0a, 0x00, 0x00, 0x80 -- little-endian encoding of 10 but with the high bit set to disable compression
75+
, 0xbb, 0x01
76+
, 0xbb, 0x01
77+
, 0xbb, 0x01
78+
, 0xbb, 0x01
79+
, 0xbb, 0x01
80+
, 0x00, 0x00, 0x00, 0x00
81+
]

0 commit comments

Comments
 (0)