diff --git a/Text/ProtocolBuffers/Get.hs b/Text/ProtocolBuffers/Get.hs
--- a/Text/ProtocolBuffers/Get.hs
+++ b/Text/ProtocolBuffers/Get.hs
@@ -57,7 +57,8 @@
     ,getWord16le,getWord32le,getWord64le
     ,getWordhost,getWord16host,getWord32host,getWord64host
     --
-    ,scan,decode7,decode7size,decode7unrolled
+    -- ,scan
+    ,decode7,decode7size,decode7unrolled
     ) where
 
 -- The Get monad is an instance of binary-strict's BinaryParser:
@@ -76,7 +77,7 @@
 import Data.Bits(Bits((.|.),(.&.)),shiftL)
 import qualified Data.ByteString as S(concat,length,null,splitAt,findIndex)
 import qualified Data.ByteString.Internal as S(ByteString(..),toForeignPtr,inlinePerformIO)
-import qualified Data.ByteString.Unsafe as S(unsafeIndex,unsafeTake,unsafeDrop)
+import qualified Data.ByteString.Unsafe as S(unsafeIndex,unsafeDrop {-,unsafeTake-})
 import qualified Data.ByteString.Lazy as L(take,drop,length,span,toChunks,fromChunks,null,findIndex)
 import qualified Data.ByteString.Lazy.Internal as L(ByteString(..),chunk)
 import qualified Data.Foldable as F(foldr,foldr1)    -- used with Seq
@@ -99,12 +100,13 @@
               | Partial (Maybe L.ByteString -> Result a)
 
 -- Internal state type, not exposed to the user.
+-- top is mempty implies current is also mempty
 data S = S { top :: {-# UNPACK #-} !S.ByteString
            , current :: !L.ByteString
            , consumed :: {-# UNPACK #-} !Int64
            } deriving Show
 
-
+{-
 data T s = T {-# UNPACK #-} !Int s
 
 -- | A stateful scanner.  The predicate consumes and transforms a
@@ -128,6 +130,7 @@
   go acc s1 = do
     let scanner (S.PS fp off len) =
           withForeignPtr fp $ \ptr0 -> do
+           if ptr0 == nullPtr || len < 1 then error "Get.scan: ByteString invariant failed" else do
             let start = ptr0 `plusPtr` off
                 end   = start `plusPtr` len
                 inner ptr !s
@@ -160,7 +163,7 @@
         putFull (S t bs n')
         return ((h:acc),s')
 
-
+-}
 data T3 s = T3 !Int !s !Int
 
 --data TU s = TU'OK !s !Int | TU'DO (Get s)
@@ -175,90 +178,94 @@
 decode7unrolled :: forall s. (Num s,Integral s, Bits s) => Get s
 {-# NOINLINE decode7unrolled #-}
 decode7unrolled = Get $ \ sc sIn@(S ss@(S.PS fp off len) bs n) pc ->
-  let (TU'OK x i) = 
-        unsafePerformIO $ withForeignPtr fp $ \ptr0 -> do
-            let ok :: s -> Int -> IO (TU s)
-                ok x0 i0 = return (TU'OK x0 i0)
-                more,err :: IO (TU s)
-                more = return (TU'OK 0 0)  -- decode7
-                err = return (TU'OK 0 (-1))  -- throwError
-                {-# INLINE ok #-}
-                {-# INLINE more #-}
-                {-# INLINE err #-}
+  if ss == mempty
+    then unGet decode7 sc sIn pc
+    else
+      let (TU'OK x i) = 
+            unsafePerformIO $ withForeignPtr fp $ \ptr0 -> do
+                if ptr0 == nullPtr || len < 1 then error "Get.decode7unrolled: ByteString invariant failed" else do
+                let ok :: s -> Int -> IO (TU s)
+                    ok x0 i0 = return (TU'OK x0 i0)
+                    more,err :: IO (TU s)
+                    more = return (TU'OK 0 0)  -- decode7
+                    err = return (TU'OK 0 (-1))  -- throwError
+                    {-# INLINE ok #-}
+                    {-# INLINE more #-}
+                    {-# INLINE err #-}
 
-            -- Next line is segfault fix for null bytestrings from Nathan Howell <nhowell@alphaheavy.com>
-            if ptr0 == nullPtr then more else do
+--                -- Next line is segfault fix for null bytestrings from Nathan Howell <nhowell@alphaheavy.com>
+--                if ptr0 == nullPtr then more else do
 
-            let start = ptr0 `plusPtr` off :: Ptr Word8
-            b'1 <- peek start
-            if b'1 < 128 then ok (fromIntegral b'1) 1 else do
-            let !val'1 = fromIntegral (b'1 .&. 0x7F)
-                !end = start `plusPtr` len
-                !ptr2 = start `plusPtr` 1 :: Ptr Word8
-            if ptr2 >= end then more else do
+                let start = ptr0 `plusPtr` off :: Ptr Word8
+                b'1 <- peek start
+                if b'1 < 128 then ok (fromIntegral b'1) 1 else do
+                let !val'1 = fromIntegral (b'1 .&. 0x7F)
+                    !end = start `plusPtr` len
+                    !ptr2 = start `plusPtr` 1 :: Ptr Word8
+                if ptr2 >= end then more else do
 
-            b'2 <- peek ptr2
-            if b'2 < 128 then ok (val'1 .|. (fromIntegral b'2 `shiftL` 7)) 2 else do
-            let !val'2 = (val'1 .|. (fromIntegral (b'2 .&. 0x7F) `shiftL` 7))
-                !ptr3 = ptr2 `plusPtr` 1
-            if ptr3 >= end then more else do
+                b'2 <- peek ptr2
+                if b'2 < 128 then ok (val'1 .|. (fromIntegral b'2 `shiftL` 7)) 2 else do
+                let !val'2 = (val'1 .|. (fromIntegral (b'2 .&. 0x7F) `shiftL` 7))
+                    !ptr3 = ptr2 `plusPtr` 1
+                if ptr3 >= end then more else do
 
-            b'3 <- peek ptr3
-            if b'3 < 128 then ok (val'2 .|. (fromIntegral b'3 `shiftL` 14)) 3 else do
-            let !val'3 = (val'2 .|. (fromIntegral (b'3 .&. 0x7F) `shiftL` 14))
-                !ptr4 = ptr3 `plusPtr` 1
-            if ptr4 >= end then more else do
+                b'3 <- peek ptr3
+                if b'3 < 128 then ok (val'2 .|. (fromIntegral b'3 `shiftL` 14)) 3 else do
+                let !val'3 = (val'2 .|. (fromIntegral (b'3 .&. 0x7F) `shiftL` 14))
+                    !ptr4 = ptr3 `plusPtr` 1
+                if ptr4 >= end then more else do
 
-            b'4 <- peek ptr4
-            if b'4 < 128 then ok (val'3 .|. (fromIntegral b'4 `shiftL` 21)) 4 else do
-            let !val'4 = (val'3 .|. (fromIntegral (b'4 .&. 0x7F) `shiftL` 21))
-                !ptr5 = ptr4 `plusPtr` 1
-            if ptr5 >= end then more else do
+                b'4 <- peek ptr4
+                if b'4 < 128 then ok (val'3 .|. (fromIntegral b'4 `shiftL` 21)) 4 else do
+                let !val'4 = (val'3 .|. (fromIntegral (b'4 .&. 0x7F) `shiftL` 21))
+                    !ptr5 = ptr4 `plusPtr` 1
+                if ptr5 >= end then more else do
 
-            b'5 <- peek ptr5
-            if b'5 < 128 then ok (val'4 .|. (fromIntegral b'5 `shiftL` 28)) 5 else do
-            let !val'5 = (val'4 .|. (fromIntegral (b'5 .&. 0x7F) `shiftL` 28))
-                !ptr6 = ptr5 `plusPtr` 1
-            if ptr6 >= end then more else do
-               
-            b'6 <- peek ptr6
-            if b'6 < 128 then ok (val'5 .|. (fromIntegral b'6 `shiftL` 35)) 6 else do
-            let !val'6 = (val'5 .|. (fromIntegral (b'6 .&. 0x7F) `shiftL` 35))
-                !ptr7 = ptr6 `plusPtr` 1
-            if ptr7 >= end then more else do
-               
-            b'7 <- peek ptr7
-            if b'7 < 128 then ok (val'6 .|. (fromIntegral b'7 `shiftL` 42)) 7 else do
-            let !val'7 = (val'6 .|. (fromIntegral (b'7 .&. 0x7F) `shiftL` 42))
-                !ptr8 = ptr7 `plusPtr` 1
-            if ptr8 >= end then more else do
-               
-            b'8 <- peek ptr8
-            if b'8 < 128 then ok (val'7 .|. (fromIntegral b'8 `shiftL` 49)) 8 else do
-            let !val'8 = (val'7 .|. (fromIntegral (b'8 .&. 0x7F) `shiftL` 49))
-                !ptr9 = ptr8 `plusPtr` 1
-            if ptr9 >= end then more else do
-               
-            b'9 <- peek ptr9
-            if b'9 < 128 then ok (val'8 .|. (fromIntegral b'9 `shiftL` 56)) 9 else do
-            let !val'9 = (val'8 .|. (fromIntegral (b'9 .&. 0x7F) `shiftL` 56))
-                !ptrA = ptr9 `plusPtr` 1
-            if ptrA >= end then more else do
+                b'5 <- peek ptr5
+                if b'5 < 128 then ok (val'4 .|. (fromIntegral b'5 `shiftL` 28)) 5 else do
+                let !val'5 = (val'4 .|. (fromIntegral (b'5 .&. 0x7F) `shiftL` 28))
+                    !ptr6 = ptr5 `plusPtr` 1
+                if ptr6 >= end then more else do
+                   
+                b'6 <- peek ptr6
+                if b'6 < 128 then ok (val'5 .|. (fromIntegral b'6 `shiftL` 35)) 6 else do
+                let !val'6 = (val'5 .|. (fromIntegral (b'6 .&. 0x7F) `shiftL` 35))
+                    !ptr7 = ptr6 `plusPtr` 1
+                if ptr7 >= end then more else do
+                   
+                b'7 <- peek ptr7
+                if b'7 < 128 then ok (val'6 .|. (fromIntegral b'7 `shiftL` 42)) 7 else do
+                let !val'7 = (val'6 .|. (fromIntegral (b'7 .&. 0x7F) `shiftL` 42))
+                    !ptr8 = ptr7 `plusPtr` 1
+                if ptr8 >= end then more else do
+                   
+                b'8 <- peek ptr8
+                if b'8 < 128 then ok (val'7 .|. (fromIntegral b'8 `shiftL` 49)) 8 else do
+                let !val'8 = (val'7 .|. (fromIntegral (b'8 .&. 0x7F) `shiftL` 49))
+                    !ptr9 = ptr8 `plusPtr` 1
+                if ptr9 >= end then more else do
+                   
+                b'9 <- peek ptr9
+                if b'9 < 128 then ok (val'8 .|. (fromIntegral b'9 `shiftL` 56)) 9 else do
+                let !val'9 = (val'8 .|. (fromIntegral (b'9 .&. 0x7F) `shiftL` 56))
+                    !ptrA = ptr9 `plusPtr` 1
+                if ptrA >= end then more else do
 
-            b'A <- peek ptrA
-            if b'A < 128 then ok (val'9 .|. (fromIntegral b'A `shiftL` 63)) 10 else do
-            err
+                b'A <- peek ptrA
+                if b'A < 128 then ok (val'9 .|. (fromIntegral b'A `shiftL` 63)) 10 else do
+                err
 
-  in if i > 0
-       then let ss' = (S.unsafeDrop i ss)
-                n' = n+fromIntegral i
-            in case S.null ss' of
-                 False -> sc x (S ss' bs n') pc
-                 True -> case bs of
-                           L.Empty -> sc x (S mempty mempty n') pc
-                           L.Chunk ss'2 bs'2 -> sc x (S ss'2 bs'2 n') pc
-        else if i==0 then unGet decode7 sc sIn pc
-               else unGet (throwError $ "Text.ProtocolBuffers.Get.decode7unrolled: more than 10 bytes needed at bytes read of "++show n) sc sIn pc
+      in if i > 0
+           then let ss' = (S.unsafeDrop i ss)
+                    n' = n+fromIntegral i
+                in case S.null ss' of
+                     False -> sc x (S ss' bs n') pc
+                     True -> case bs of
+                               L.Empty -> sc x (S mempty mempty n') pc
+                               L.Chunk ss'2 bs'2 -> sc x (S ss'2 bs'2 n') pc
+           else if i==0 then unGet decode7 sc sIn pc
+                       else unGet (throwError $ "Text.ProtocolBuffers.Get.decode7unrolled: more than 10 bytes needed at bytes read of "++show n) sc sIn pc
 
 {- used up till bench-024
 decode7unrolled = Get $ \ sc sIn@(S ss@(S.PS fp off len) bs n) pc ->
@@ -350,6 +357,7 @@
   go !s1 !shift1 = do
     let scanner (S.PS fp off len) =
           withForeignPtr fp $ \ptr0 -> do
+           if ptr0 == nullPtr || len < 1 then error "Get.decode7: ByteString invariant failed" else do
             let start = ptr0 `plusPtr` off
                 end   = start `plusPtr` len
                 inner :: (Ptr Word8) -> s -> Int -> IO (T3 s)
@@ -364,24 +372,31 @@
                   | otherwise = return $ T3 (ptr `minusPtr` start) s shift
             inner start s1 shift1
     (S ss bs n) <- getFull
-    let (T3 i sOut shiftOut) = unsafePerformIO $ scanner ss
-        t = S.unsafeDrop i ss
-        n' = n + fromIntegral i
-    if 0 <= shiftOut
+    if ss == mempty
       then do
-        case bs of
-          L.Empty -> do
-            putFull (S mempty mempty n')
-            continue <- suspend
-            if continue
-              then go sOut shiftOut
-              else return sOut
-          L.Chunk ss' bs' -> do
-            putFull (S ss' bs' n')
-            go sOut shiftOut
+        continue <- suspend
+        if continue
+          then go 0 0
+          else fail "Get.decode7: Zero length input"
       else do
-        putFull (S t bs n')
-        return sOut
+        let (T3 i sOut shiftOut) = unsafePerformIO $ scanner ss
+            t = S.unsafeDrop i ss
+            n' = n + fromIntegral i
+        if 0 <= shiftOut
+          then do
+            case bs of
+              L.Empty -> do
+                putFull (S mempty mempty n')
+                continue <- suspend
+                if continue
+                  then go sOut shiftOut
+                  else return sOut
+              L.Chunk ss' bs' -> do
+                putFull (S ss' bs' n')
+                go sOut shiftOut
+          else do
+            putFull (S t bs n')
+            return sOut
 
 data T2 = T2 !Int64 !Bool
 
@@ -391,6 +406,7 @@
   go !len1 = do
     let scanner (S.PS fp off len) =
           withForeignPtr fp $ \ptr0 -> do
+           if ptr0 == nullPtr || len < 1 then error "Get.decode7size: ByteString invariant failed" else do
             let start = ptr0 `plusPtr` off
                 end   = start `plusPtr` len
                 inner :: (Ptr Word8) -> IO T2
@@ -403,25 +419,32 @@
                   | otherwise = return $ T2 (fromIntegral (ptr `minusPtr` start)) False
             inner start
     (S ss bs n) <- getFull
-    let (T2 i ok) = unsafePerformIO $ scanner ss
-        t = S.unsafeDrop (fromIntegral i) ss
-        n' = n + i
-        len2 = len1 + i
-    if ok
+    if ss == mempty
       then do
-        putFull (S t bs n')
-        return len2
+        continue <- suspend
+        if continue
+          then go 0
+          else fail "Get.decode7size: zero length input"
       else do
-        case bs of
-          L.Empty -> do
-            putFull (S mempty mempty n')
-            continue <- suspend
-            if continue
-              then go len2
-              else return len2
-          L.Chunk ss' bs' -> do
-            putFull (S ss' bs' n')
-            go len2
+        let (T2 i ok) = unsafePerformIO $ scanner ss
+            t = S.unsafeDrop (fromIntegral i) ss
+            n' = n + i
+            len2 = len1 + i
+        if ok
+          then do
+            putFull (S t bs n')
+            return len2
+          else do
+            case bs of
+              L.Empty -> do
+                putFull (S mempty mempty n')
+                continue <- suspend
+                if continue
+                  then go len2
+                  else return len2
+              L.Chunk ss' bs' -> do
+                putFull (S ss' bs' n')
+                go len2
 
 -- Private Internal error handling stack type
 -- This must NOT be exposed by this module
@@ -605,11 +628,14 @@
 ensureBytes :: Int64 -> Get ()
 ensureBytes n = do
   (S ss bs _read) <- getFull
-  if n < fromIntegral (S.length ss)
-    then return ()
-    else do if n == L.length (L.take n (L.chunk ss bs))
-              then return ()
-              else suspendMsg "ensureBytes failed" >> ensureBytes n
+  if ss == mempty
+    then suspendMsg "ensureBytes failed" >> ensureBytes n
+    else do
+      if n < fromIntegral (S.length ss)
+        then return ()
+        else do if n == L.length (L.take n (L.chunk ss bs))
+                  then return ()
+                  else suspendMsg "ensureBytes failed" >> ensureBytes n
 {-# INLINE ensureBytes #-}
 
 -- | Pull @n@ bytes from the unput, as a lazy ByteString.  This will
@@ -618,13 +644,16 @@
 getLazyByteString n | n<=0 = return mempty
                     | otherwise = do
   (S ss bs offset) <- getFull
-  case splitAtOrDie n (L.chunk ss bs) of
-    Just (consume,rest) ->do
-       case rest of
-         L.Empty -> putFull (S mempty mempty (offset + n))
-         L.Chunk ss' bs' -> putFull (S ss' bs' (offset + n))
-       return $! consume
-    Nothing -> suspendMsg ("getLazyByteString failed with "++show (n,(S.length ss,L.length bs,offset)))  >> getLazyByteString n
+  if ss == mempty
+    then suspendMsg ("getLazyByteString failed with "++show (n,(S.length ss,L.length bs,offset)))  >> getLazyByteString n
+    else do
+      case splitAtOrDie n (L.chunk ss bs) of
+        Just (consume,rest) ->do
+           case rest of
+             L.Empty -> putFull (S mempty mempty (offset + n))
+             L.Chunk ss' bs' -> putFull (S ss' bs' (offset + n))
+           return $! consume
+        Nothing -> suspendMsg ("getLazyByteString failed with "++show (n,(S.length ss,L.length bs,offset)))  >> getLazyByteString n
 {-# INLINE getLazyByteString #-} -- important
 
 -- | 'suspend' is supposed to allow the execution of the monad to be
@@ -719,7 +748,8 @@
        | otherwise = do
   ensureBytes m
   (S ss bs n) <- getFull
-  case L.drop m (L.chunk ss bs) of
+  -- Could ignore impossible ss == mempty case due to (ensureBytes m) and (0 < m)
+  case L.drop m (if ss == mempty then bs else L.chunk ss bs) of
     L.Empty -> putFull (S mempty mempty (n+m))
     L.Chunk ss' bs' -> putFull (S ss' bs' (n+m))
 
@@ -769,6 +799,7 @@
   {-# INLINE loop #-}
   loop = do
     (S ss bs _n) <- getFull
+    -- mempty is okay, will lead to Nothing below
     let mi = S.findIndex (128>) ss
     case mi of
       Just i -> return (succ $ fromIntegral i)
@@ -779,12 +810,12 @@
           Nothing -> do
             continue <- suspend
             if continue then loop
-              else throwError "highBitRun has failed"
+              else fail "highBitRun has failed"
 
 -- | get the longest prefix of the input where all the bytes satisfy the predicate.
 spanOf :: (Word8 -> Bool) ->  Get (L.ByteString)
 spanOf f = do let loop = do (S ss bs n) <- getFull
-                            let (pre,post) = L.span f (L.chunk ss bs)
+                            let (pre,post) = L.span f (if ss==mempty then bs else L.chunk ss bs)
                             case post of
                               L.Empty -> putFull (S mempty mempty (n + L.length pre))
                               L.Chunk ss' bs' -> putFull (S ss' bs' (n + L.length pre))
@@ -805,7 +836,7 @@
 getByteString nIn | nIn <= 0 = return mempty
                   | otherwise = do
   (S ss bs n) <- getFull
-  if nIn < S.length ss
+  if nIn < S.length ss -- Leave at least one character of 'ss' in 'post'
     then do let (pre,post) = S.splitAt nIn ss
             putFull (S post bs (n+fromIntegral nIn))
             return $! pre
@@ -956,8 +987,8 @@
 splitAtOrDie i ps | i <= 0 = Just (L.Empty, ps)
 splitAtOrDie _i L.Empty = Nothing
 splitAtOrDie i (L.Chunk x xs) | i < len = let (pre,post) = S.splitAt (fromIntegral i) x
-                                          in Just (L.Chunk pre L.Empty
-                                                  ,L.Chunk post xs)
+                                          in Just (if pre == mempty then L.Empty else L.Chunk pre L.Empty
+                                                  ,if post == mempty then xs else L.Chunk post xs)
                               | otherwise = case splitAtOrDie (i-len) xs of
                                               Nothing -> Nothing
                                               Just (y1,y2) -> Just (L.Chunk x y1,y2)
@@ -971,6 +1002,7 @@
 -- underlying lazy byteString. So many indirections from the raw parser
 -- state that my head hurts...
 
+-- Assume n>0
 getPtr :: (Storable a) => Int -> Get a
 getPtr n = do
     (fp,o,_) <- fmap S.toForeignPtr (getByteString n)
@@ -978,6 +1010,7 @@
 {-# INLINE getPtr #-}
 
 -- I pushed the sizeOf into here (uses ScopedTypeVariables)
+-- Assume sizeOf (undefined :: a)) > 0
 getStorable :: forall a. (Storable a) => Get a
 getStorable = do
     (fp,o,_) <- fmap S.toForeignPtr (getByteString (sizeOf (undefined :: a)))
diff --git a/protocol-buffers.cabal b/protocol-buffers.cabal
--- a/protocol-buffers.cabal
+++ b/protocol-buffers.cabal
@@ -1,5 +1,5 @@
 name:           protocol-buffers
-version:        2.0.7
+version:        2.0.8
 cabal-version:  >= 1.6
 build-type:     Simple
 license:        BSD3
