diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2017-07-25  Facundo Domínguez <facundo.dominguez@tweag.io> 0.5.2
+
+* prependLength checks for overflow (5608f0f)
+* Drop inlinePerformIO for unsafeDupablePerformIO (18bf80c)
+* Have travis build n-t even with no tests (7ffe43e)
+
 2017-02-23  Facundo Domínguez <facundo.dominguez@tweag.io> 0.5.1
 
 * Add {encode|decode}{Word|Enum|Num}{32|16}.
diff --git a/network-transport.cabal b/network-transport.cabal
--- a/network-transport.cabal
+++ b/network-transport.cabal
@@ -1,5 +1,5 @@
 Name:          network-transport
-Version:       0.5.1
+Version:       0.5.2
 Cabal-Version: >=1.6
 Build-Type:    Simple
 License:       BSD3
diff --git a/src/Network/Transport/Internal.hs b/src/Network/Transport/Internal.hs
--- a/src/Network/Transport/Internal.hs
+++ b/src/Network/Transport/Internal.hs
@@ -30,11 +30,11 @@
 import Foreign.Storable (pokeByteOff, peekByteOff)
 import Foreign.ForeignPtr (withForeignPtr)
 import Data.ByteString (ByteString)
+import Data.List (foldl')
 import qualified Data.ByteString as BS (length)
 import qualified Data.ByteString.Internal as BSI
   ( unsafeCreate
   , toForeignPtr
-  , inlinePerformIO
   )
 import Data.Word (Word32, Word16)
 import Control.Applicative ((<$>))
@@ -53,6 +53,7 @@
 import Control.Concurrent (ThreadId, forkIO)
 import Control.Concurrent.MVar (MVar, newEmptyMVar, takeMVar, putMVar)
 import GHC.IO (unsafeUnmask)
+import System.IO.Unsafe (unsafeDupablePerformIO)
 import System.Timeout (timeout)
 --import Control.Concurrent (myThreadId)
 
@@ -83,7 +84,7 @@
 decodeWord32 :: ByteString -> Word32
 decodeWord32 bs
   | BS.length bs /= 4 = throw $ userError "decodeWord32: not 4 bytes"
-  | otherwise         = BSI.inlinePerformIO $ do
+  | otherwise         = unsafeDupablePerformIO $ do
       let (fp, offset, _) = BSI.toForeignPtr bs
       withForeignPtr fp $ \p -> ntohl <$> peekByteOff p offset
 
@@ -98,7 +99,7 @@
 decodeWord16 :: ByteString -> Word16
 decodeWord16 bs
   | BS.length bs /= 2 = throw $ userError "decodeWord16: not 2 bytes"
-  | otherwise         = BSI.inlinePerformIO $ do
+  | otherwise         = unsafeDupablePerformIO $ do
       let (fp, offset, _) = BSI.toForeignPtr bs
       withForeignPtr fp $ \p -> ntohs <$> peekByteOff p offset
 
@@ -123,8 +124,25 @@
 decodeNum16 = fromIntegral . decodeWord16
 
 -- | Prepend a list of bytestrings with their total length
+--   Will be an exception in case of overflow: the sum of the lengths of
+--   the ByteStrings overflows Int, or that sum overflows Word32.
 prependLength :: [ByteString] -> [ByteString]
-prependLength bss = encodeWord32 (fromIntegral . sum . map BS.length $ bss) : bss
+prependLength bss = case word32Length of
+    Nothing -> overflow
+    Just w32 -> encodeWord32 w32 : bss
+  where
+    intLength :: Int
+    intLength = foldl' safeAdd 0 . map BS.length $ bss
+    word32Length :: Maybe Word32
+    word32Length = tryToEnum intLength
+    -- Non-negative integer addition with overflow check.
+    safeAdd :: Int -> Int -> Int
+    safeAdd i j
+      | r >= 0    = r
+      | otherwise = overflow
+      where
+      r = i + j
+    overflow = throw $ userError "prependLength: input is too long (overflow)"
 
 -- | Translate exceptions that arise in IO computations
 mapIOException :: Exception e => (IOException -> e) -> IO a -> IO a
