@@ -18,7 +18,6 @@ import Control.Applicative
18import Data.Bits
18import Data.Bits
19import Data.Word
19import Data.Word
20import Foreign.Storable
20import Foreign.Storable
22import Data.Traversable (traverse)
21import Data.Traversable (traverse)
23import Data.Foldable (traverse_)
22import Data.Foldable (traverse_)
@@ -262,8 +261,8 @@ prop_fail lbs errMsg0 = forAll (choose (0, 8 * L.length lbs)) $ \len ->
262 expectedBytesConsumed
261 expectedBytesConsumed
263 | bits == 0 = bytes
262 | bits == 0 = bytes
264 | otherwise = bytes + 1
263 | otherwise = bytes + 1
265− p = do getByteString (fromIntegral bytes)
264+ p = do _ <- getByteString (fromIntegral bytes)
266− getBits (fromIntegral bits) :: BitGet Word8
265+ _ <- getBits (fromIntegral bits) :: BitGet Word8
267 fail errMsg0
266 fail errMsg0
268 r = runGetIncremental (runBitGet p) `pushChunks` lbs
267 r = runGetIncremental (runBitGet p) `pushChunks` lbs
269 in case r of
268 in case r of
@@ -395,11 +394,6 @@ instance (Arbitrary (W a), Arbitrary (W b), Arbitrary (W c)) => Arbitrary (W (a,
395 arbitrary = ((W .) .) . (,,) <$> arbitraryW <*> arbitraryW <*> arbitraryW
394 arbitrary = ((W .) .) . (,,) <$> arbitraryW <*> arbitraryW <*> arbitraryW
396 shrink (W (a,b,c)) = ((W .) .) . (,,) <$> shrinkW a <*> shrinkW b <*> shrinkW c
395 shrink (W (a,b,c)) = ((W .) .) . (,,) <$> shrinkW a <*> shrinkW b <*> shrinkW c
398−integralRandomR :: (Integral a, RandomGen g) => (a,a) -> g -> (a,g)
399−integralRandomR (a,b) g = case randomR (fromIntegral a :: Integer,
400− fromIntegral b :: Integer) g of
401− (x,g) -> (fromIntegral x, g)
403data Primitive
397data Primitive
404 = Bool Bool
398 = Bool Bool
405 | W8 Int Word8
399 | W8 Int Word8
@@ -408,6 +402,7 @@ data Primitive
408 | W64 Int Word64
402 | W64 Int Word64
409 | BS Int B.ByteString
403 | BS Int B.ByteString
410 | LBS Int L.ByteString
404 | LBS Int L.ByteString
411 | IsEmpty
406 | IsEmpty
412 deriving (Eq, Show)
407 deriving (Eq, Show)
@@ -426,6 +421,7 @@ instance Arbitrary Primitive where
426 , gen W16
421 , gen W16
427 , gen W32
422 , gen W32
428 , gen W64
423 , gen W64
424+ , Skip <$> choose (0, 3000)
429 , do n <- choose (0,10)
425 , do n <- choose (0,10)
430 cs <- vector n
426 cs <- vector n
431 return (BS n (B.pack cs))
427 return (BS n (B.pack cs))
@@ -442,6 +438,7 @@ instance Arbitrary Primitive where
442 W16 _ x -> snk W16 x
438 W16 _ x -> snk W16 x
443 W32 _ x -> snk W32 x
439 W32 _ x -> snk W32 x
444 W64 _ x -> snk W64 x
440 W64 _ x -> snk W64 x
441+ Skip x -> Skip <$> shrink x
445 BS _ bs -> let ws = B.unpack bs in map (\ws' -> BS (length ws') (B.pack ws')) (shrink ws)
442 BS _ bs -> let ws = B.unpack bs in map (\ws' -> BS (length ws') (B.pack ws')) (shrink ws)
446 LBS _ lbs -> let ws = L.unpack lbs in map (\ws' -> LBS (length ws') (L.pack ws')) (shrink ws)
443 LBS _ lbs -> let ws = L.unpack lbs in map (\ws' -> LBS (length ws') (L.pack ws')) (shrink ws)
447 IsEmpty -> []
444 IsEmpty -> []
@@ -478,6 +475,7 @@ putPrimitive p =
478 W16 n x -> putWord16 n x
475 W16 n x -> putWord16 n x
479 W32 n x -> putWord32 n x
476 W32 n x -> putWord32 n x
480 W64 n x -> putWord64 n x
477 W64 n x -> putWord64 n x
478+ Skip n -> skipBits n
481 BS _ bs -> putByteString bs
479 BS _ bs -> putByteString bs
482 LBS _ lbs -> mapM_ putByteString (L.toChunks lbs)
480 LBS _ lbs -> mapM_ putByteString (L.toChunks lbs)
483 IsEmpty -> return ()
481 IsEmpty -> return ()
@@ -490,10 +488,22 @@ getPrimitive p =
490 W16 n _ -> W16 n <$> getWord16 n
488 W16 n _ -> W16 n <$> getWord16 n
491 W32 n _ -> W32 n <$> getWord32 n
489 W32 n _ -> W32 n <$> getWord32 n
492 W64 n _ -> W64 n <$> getWord64 n
490 W64 n _ -> W64 n <$> getWord64 n
491+ Skip n -> skipBits n >> return (Skip n)
493 BS n _ -> BS n <$> getByteString n
492 BS n _ -> BS n <$> getByteString n
494 LBS n _ -> LBS n <$> getLazyByteString n
493 LBS n _ -> LBS n <$> getLazyByteString n
495 IsEmpty -> isEmpty >> return IsEmpty
494 IsEmpty -> isEmpty >> return IsEmpty
496+getPrimitiveSize :: Primitive -> Int
497+getPrimitiveSize p = case p of
498verifyProgram :: Int -> Program -> BitGet Bool
508verifyProgram :: Int -> Program -> BitGet Bool
499verifyProgram totalLength ps0 = go 0 ps0
509verifyProgram totalLength ps0 = go 0 ps0
@@ -501,13 +511,6 @@ verifyProgram totalLength ps0 = go 0 ps0
501 go _ [] = return True
511 go _ [] = return True
502 go pos (p:ps) =
512 go pos (p:ps) =
503 case p of
513 case p of
504− Bool x -> check x getBool >> go (pos+1) ps
505− W8 n x -> check x (getWord8 n) >> go (pos+n) ps
506− W16 n x -> check x (getWord16 n) >> go (pos+n) ps
507− W32 n x -> check x (getWord32 n) >> go (pos+n) ps
508− W64 n x -> check x (getWord64 n) >> go (pos+n) ps
509− BS n x -> check x (getByteString n) >> go (pos+(8*n)) ps
510− LBS n x -> check x (getLazyByteString n) >> go (pos+(8*n)) ps
511 IsEmpty -> do
514 IsEmpty -> do
512 let expected = pos == totalLength
515 let expected = pos == totalLength
513 actual <- isEmpty
516 actual <- isEmpty
@@ -515,6 +518,7 @@ verifyProgram totalLength ps0 = go 0 ps0
515 then go pos ps
518 then go pos ps
516 else error $ "isEmpty returned wrong value, expected "
519 else error $ "isEmpty returned wrong value, expected "
517 ++ show expected ++ " but got " ++ show actual
520 ++ show expected ++ " but got " ++ show actual
521+ _ -> check p (getPrimitive p) >> go (pos + getPrimitiveSize p) ps
518 check x g = do
522 check x g = do
520 if x == y
524 if x == y