@@ -20,6 +20,11 @@ module Streamly.Internal.Data.Serialize
2020
2121#include "assert.hs"
2222
23+#ifdef DEBUG
24+import Control.Exception (assert)
25+import Streamly.Internal.Data.Unbox (Unbox(..), sizeOfMutableByteArray)
26+#endif
27+
2328import Control.Monad (void)
2429import Data.List (foldl')
2530import Data.Proxy (Proxy (..))
@@ -105,20 +110,41 @@ class Serialize a where
105110-- Instances
106111--------------------------------------------------------------------------------
107112
113+{-# INLINE checkBounds #-}
114+checkBounds :: String -> Int -> MutableByteArray -> IO ()
115+checkBounds _label _off _arr = do
116+#ifdef DEBUG
117+ sz <- sizeOfMutableByteArray _arr
118+ if (_off > sz)
119+ then error
120+ $ _label
121+ ++ ": accessing array at offset = "
122+ ++ show (_off - 1)
123+ ++ " max valid offset = " ++ show (sz - 1)
124+ else return ()
125+#else
126+ return ()
127+#endif
128+
108129#define DERIVE_SERIALIZE_FROM_UNBOX(_type) \
109130instance Serialize _type where \
110131; {-# INLINE size #-} \
111132; size = Size (\acc _ -> acc + Unbox.sizeOf (Proxy :: Proxy _type)) \
112133; {-# INLINE deserialize #-} \
113134; deserialize off arr = \
114− Unbox.peekByteIndex off arr >>= \
115− \val -> let sz = Unbox.sizeOf (Proxy :: Proxy _type) \
116− in pure (off + sz, val) \
135+ let next = off + Unbox.sizeOf (Proxy :: Proxy _type) \
136+ in do { \
137+ checkBounds "deserialize" next arr; \
138+ Unbox.peekByteIndex off arr >>= \val -> pure (next, val); \
139+ } \
117140; {-# INLINE serialize #-} \
118141; serialize off arr val = \
119− Unbox.pokeByteIndex off arr val \
120− >> let sz = Unbox.sizeOf (Proxy :: Proxy _type) \
121− in pure (off + sz)
142+ let next = off + Unbox.sizeOf (Proxy :: Proxy _type) \
143+ in do { \
144+ checkBounds "serialize" next arr; \
145+ Unbox.pokeByteIndex off arr val; \
146+ pure next \
147+ }
122148
123149DERIVE_SERIALIZE_FROM_UNBOX(Bool)
124150DERIVE_SERIALIZE_FROM_UNBOX(Char)