diff --git a/Data/Attoparsec/ByteString/Char8.hs b/Data/Attoparsec/ByteString/Char8.hs
--- a/Data/Attoparsec/ByteString/Char8.hs
+++ b/Data/Attoparsec/ByteString/Char8.hs
@@ -128,10 +128,10 @@
     ) where
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative (pure, (*>), (<*))
+import Control.Applicative (pure, (*>), (<*), (<$>))
 import Data.Word (Word)
 #endif
-import Control.Applicative ((<$>), (<|>))
+import Control.Applicative ((<|>))
 import Control.Monad (void, when)
 import Data.Attoparsec.ByteString.FastSet (charClass, memberChar)
 import Data.Attoparsec.ByteString.Internal (Parser)
diff --git a/Data/Attoparsec/ByteString/Internal.hs b/Data/Attoparsec/ByteString/Internal.hs
--- a/Data/Attoparsec/ByteString/Internal.hs
+++ b/Data/Attoparsec/ByteString/Internal.hs
@@ -1,4 +1,5 @@
-{-# LANGUAGE BangPatterns, GADTs, OverloadedStrings, RankNTypes, RecordWildCards #-}
+{-# LANGUAGE BangPatterns, CPP, GADTs, OverloadedStrings, RankNTypes,
+    RecordWildCards #-}
 -- |
 -- Module      :  Data.Attoparsec.ByteString.Internal
 -- Copyright   :  Bryan O'Sullivan 2007-2015
@@ -65,7 +66,10 @@
     , atEnd
     ) where
 
-import Control.Applicative ((<|>), (<$>))
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+#endif
+import Control.Applicative ((<|>))
 import Control.Monad (when)
 import Data.Attoparsec.ByteString.Buffer (Buffer, buffer)
 import Data.Attoparsec.ByteString.FastSet (charClass, memberWord8)
@@ -186,11 +190,12 @@
   let n = B.length s
       s = f s0
   in if lengthAtLeast pos n t
-     then if s == substring pos (Pos n) t
-          then succ t (pos + Pos n) more s
-          else lose t pos more [] "string"
+     then let t' = substring pos (Pos n) t
+          in if s == f t'
+             then succ t (pos + Pos n) more t'
+             else lose t pos more [] "string"
      else let t' = Buf.unsafeDrop (fromPos pos) t
-          in if t' `B.isPrefixOf` s
+          in if f t' `B.isPrefixOf` s
              then suspended s (B.drop (B.length t') s) t pos more lose succ
              else lose t pos more [] "string"
 {-# INLINE string_ #-}
@@ -208,7 +213,9 @@
               n  = B.length s'
           in if n >= m
              then if B.unsafeTake m s' == s
-                  then succ' t' (pos' + Pos (B.length s0)) more' s0
+                  then let o = Pos (B.length s0)
+                       in succ' t' (pos' + o) more'
+                          (substring pos' o t')
                   else lose' t' pos' more' [] "string"
              else if s' == B.unsafeTake n s
                   then stringSuspended f s0 (B.unsafeDrop n s)
diff --git a/Data/Attoparsec/Combinator.hs b/Data/Attoparsec/Combinator.hs
--- a/Data/Attoparsec/Combinator.hs
+++ b/Data/Attoparsec/Combinator.hs
@@ -40,11 +40,10 @@
     ) where
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative (Applicative(..))
+import Control.Applicative (Applicative(..), (<$>))
 import Data.Monoid (Monoid(mappend))
 #endif
-import Control.Applicative (Alternative(..), empty, liftA2, many, (<|>), 
-                            (<$>))
+import Control.Applicative (Alternative(..), empty, liftA2, many, (<|>))
 import Control.Monad (MonadPlus(..))
 import Data.Attoparsec.Internal.Types (Parser(..), IResult(..))
 import Data.Attoparsec.Internal (endOfInput, atEnd, satisfyElem)
diff --git a/Data/Attoparsec/Internal.hs b/Data/Attoparsec/Internal.hs
--- a/Data/Attoparsec/Internal.hs
+++ b/Data/Attoparsec/Internal.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
+{-# LANGUAGE BangPatterns, CPP, ScopedTypeVariables #-}
 -- |
 -- Module      :  Data.Attoparsec.Internal
 -- Copyright   :  Bryan O'Sullivan 2007-2015
@@ -22,7 +22,9 @@
     , satisfyElem
     ) where
 
+#if !MIN_VERSION_base(4,8,0)
 import Control.Applicative ((<$>))
+#endif
 import Data.Attoparsec.Internal.Types
 import Data.ByteString (ByteString)
 import Data.Text (Text)
diff --git a/Data/Attoparsec/Internal/Types.hs b/Data/Attoparsec/Internal/Types.hs
--- a/Data/Attoparsec/Internal/Types.hs
+++ b/Data/Attoparsec/Internal/Types.hs
@@ -26,10 +26,10 @@
     ) where
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative (Applicative(..))
+import Control.Applicative (Applicative(..), (<$>))
 import Data.Monoid (Monoid(..))
 #endif
-import Control.Applicative (Alternative(..), (<$>))
+import Control.Applicative (Alternative(..))
 import Control.DeepSeq (NFData(rnf))
 import Control.Monad (MonadPlus(..))
 import Data.Word (Word8)
diff --git a/Data/Attoparsec/Text.hs b/Data/Attoparsec/Text.hs
--- a/Data/Attoparsec/Text.hs
+++ b/Data/Attoparsec/Text.hs
@@ -126,10 +126,10 @@
     ) where
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative (pure, (*>), (<*))
+import Control.Applicative (pure, (*>), (<*), (<$>))
 import Data.Word (Word)
 #endif
-import Control.Applicative ((<$>), (<|>))
+import Control.Applicative ((<|>))
 import Data.Attoparsec.Combinator
 import Data.Attoparsec.Number (Number(..))
 import Data.Scientific (Scientific)
diff --git a/Data/Attoparsec/Text/Internal.hs b/Data/Attoparsec/Text/Internal.hs
--- a/Data/Attoparsec/Text/Internal.hs
+++ b/Data/Attoparsec/Text/Internal.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE BangPatterns, FlexibleInstances, GADTs, OverloadedStrings,
+{-# LANGUAGE BangPatterns, CPP, FlexibleInstances, GADTs, OverloadedStrings,
     Rank2Types, RecordWildCards, TypeFamilies, TypeSynonymInstances #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 -- |
@@ -65,7 +65,10 @@
     , atEnd
     ) where
 
-import Control.Applicative ((<|>), (<$>))
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
+#endif
+import Control.Applicative ((<|>))
 import Control.Monad (when)
 import Data.Attoparsec.Combinator ((<?>))
 import Data.Attoparsec.Internal
diff --git a/attoparsec.cabal b/attoparsec.cabal
--- a/attoparsec.cabal
+++ b/attoparsec.cabal
@@ -1,5 +1,5 @@
 name:            attoparsec
-version:         0.12.1.5
+version:         0.12.1.6
 license:         BSD3
 license-file:    LICENSE
 category:        Text, Parsing
diff --git a/benchmarks/Aeson.hs b/benchmarks/Aeson.hs
--- a/benchmarks/Aeson.hs
+++ b/benchmarks/Aeson.hs
@@ -10,8 +10,13 @@
 import Data.ByteString.Builder
   (Builder, byteString, toLazyByteString, charUtf8, word8)
 
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((*>), (<$>), (<*), pure)
+import Data.Monoid (mappend, mempty)
+#endif
+
 import Common (pathTo)
-import Control.Applicative ((*>), (<$>), (<*), liftA2, pure)
+import Control.Applicative (liftA2)
 import Control.DeepSeq (NFData(..))
 import Control.Monad (forM)
 import Data.Attoparsec.ByteString.Char8 (Parser, char, endOfInput, scientific,
@@ -20,7 +25,6 @@
 import Data.ByteString (ByteString)
 import Data.Char (chr)
 import Data.List (sort)
-import Data.Monoid (mappend, mempty)
 import Data.Scientific (Scientific)
 import Data.Text (Text)
 import Data.Text.Encoding (decodeUtf8')
diff --git a/benchmarks/Links.hs b/benchmarks/Links.hs
--- a/benchmarks/Links.hs
+++ b/benchmarks/Links.hs
@@ -5,8 +5,8 @@
 import Control.Applicative
 import Control.DeepSeq (NFData(..))
 import Criterion.Main (Benchmark, bench, nf)
-import Data.Attoparsec as A
-import Data.Attoparsec.Char8 as A8
+import Data.Attoparsec.ByteString as A
+import Data.Attoparsec.ByteString.Char8 as A8
 import Data.ByteString.Char8 as B8
 
 data Link = Link {
diff --git a/benchmarks/Numbers.hs b/benchmarks/Numbers.hs
--- a/benchmarks/Numbers.hs
+++ b/benchmarks/Numbers.hs
@@ -1,4 +1,5 @@
 {-# LANGUAGE BangPatterns #-}
+{-# OPTIONS_GHC -fno-warn-deprecations #-}
 
 module Numbers (numbers) where
 
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+0.12.1.6
+
+* Fixed a case folding bug in the ByteString version of stringCI.
+
 0.12.1.5
 
 * Fixed an indexing bug in the new Text implementation of string,
diff --git a/tests/QC/Buffer.hs b/tests/QC/Buffer.hs
--- a/tests/QC/Buffer.hs
+++ b/tests/QC/Buffer.hs
@@ -3,8 +3,8 @@
 
 module QC.Buffer (tests) where
 
-import Control.Applicative ((<$>))
 #if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<$>))
 import Data.Monoid (Monoid(mconcat))
 #endif
 import QC.Common ()
diff --git a/tests/QC/ByteString.hs b/tests/QC/ByteString.hs
--- a/tests/QC/ByteString.hs
+++ b/tests/QC/ByteString.hs
@@ -2,14 +2,13 @@
 module QC.ByteString (tests) where
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative ((<*>))
+import Control.Applicative ((<*>), (<$>))
 #endif
-import Control.Applicative ((<$>))
-import Data.Char (chr, ord)
+import Data.Char (chr, ord, toUpper)
 import Data.Int (Int64)
 import Data.Word (Word8)
 import Prelude hiding (take, takeWhile)
-import QC.Common (liftOp, parseBS, toStrictBS)
+import QC.Common (ASCII(..), liftOp, parseBS, toStrictBS)
 import Test.Framework (Test)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
 import Test.QuickCheck
@@ -18,6 +17,7 @@
 import qualified Data.Attoparsec.ByteString.FastSet as S
 import qualified Data.Attoparsec.ByteString.Lazy as PL
 import qualified Data.ByteString as B
+import qualified Data.ByteString.Char8 as B8
 import qualified Data.ByteString.Lazy as L
 import qualified Data.ByteString.Lazy.Char8 as L8
 
@@ -66,6 +66,18 @@
 string s t = parseBS (P.string s') (s `L.append` t) === Just s'
   where s' = toStrictBS s
 
+stringCI :: ASCII L.ByteString -> ASCII L.ByteString -> Property
+stringCI (ASCII s) (ASCII t) =
+    parseBS (P8.stringCI up) (s `L.append` t) === Just s'
+  where s' = toStrictBS s
+        up = B8.map toUpper s'
+
+strings :: L.ByteString -> L.ByteString -> L.ByteString -> Property
+strings s t u =
+    parseBS (P.string (toStrictBS s) >> P.string t') (L.concat [s,t,u])
+    === Just t'
+  where t' = toStrictBS t
+
 skipWhile :: Word8 -> L.ByteString -> Property
 skipWhile w s =
     let t = L.dropWhile (<=w) s
@@ -157,6 +169,8 @@
     , testProperty "skip" skip
     , testProperty "skipWhile" skipWhile
     , testProperty "string" string
+    , testProperty "stringCI" stringCI
+    , testProperty "strings" strings
     , testProperty "take" take
     , testProperty "takeByteString" takeByteString
     , testProperty "takeCount" takeCount
diff --git a/tests/QC/Combinator.hs b/tests/QC/Combinator.hs
--- a/tests/QC/Combinator.hs
+++ b/tests/QC/Combinator.hs
@@ -1,8 +1,10 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE CPP, OverloadedStrings #-}
 
 module QC.Combinator where
 
-import Control.Applicative
+#if !MIN_VERSION_base(4,8,0)
+import Control.Applicative ((<*>), (<$>), (<*), (*>))
+#endif
 import Data.Maybe (fromJust, isJust)
 import Data.Word (Word8)
 import QC.Common (Repack, parseBS, repackBS, toLazyBS)
diff --git a/tests/QC/Common.hs b/tests/QC/Common.hs
--- a/tests/QC/Common.hs
+++ b/tests/QC/Common.hs
@@ -1,8 +1,9 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, FlexibleInstances #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module QC.Common
     (
-      parseBS
+      ASCII(..)
+    , parseBS
     , parseT
     , toLazyBS
     , toStrictBS
@@ -15,9 +16,8 @@
     ) where
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative ((<*>))
+import Control.Applicative ((<*>), (<$>))
 #endif
-import Control.Applicative ((<$>))
 import Data.Char (isAlpha)
 import Test.QuickCheck
 import Test.QuickCheck.Unicode (shrinkChar, string)
@@ -28,6 +28,16 @@
 import qualified Data.Attoparsec.ByteString.Lazy as BL
 import qualified Data.Attoparsec.Text.Lazy as TL
 
+#if !MIN_VERSION_base(4,4,0)
+-- This should really be a dependency on the random package :-(
+instance Random Word8 where
+  randomR = integralRandomR
+  random = randomR (minBound,maxBound)
+
+instance Arbitrary Word8 where
+    arbitrary = choose (minBound, maxBound)
+#endif
+
 parseBS :: BL.Parser r -> BL.ByteString -> Maybe r
 parseBS p = BL.maybeResult . BL.parse p
 
@@ -42,9 +52,22 @@
 
 instance Arbitrary B.ByteString where
     arbitrary = B.pack <$> arbitrary
+    shrink = map B.pack . shrink . B.unpack
 
 instance Arbitrary BL.ByteString where
     arbitrary = repackBS <$> arbitrary <*> arbitrary
+    shrink = map BL.pack . shrink . BL.unpack
+
+newtype ASCII a = ASCII { fromASCII :: a }
+                  deriving (Eq, Ord, Show)
+
+instance Arbitrary (ASCII B.ByteString) where
+    arbitrary = (ASCII . B.pack) <$> listOf (choose (0,127))
+    shrink = map (ASCII . B.pack) . shrink . B.unpack . fromASCII
+
+instance Arbitrary (ASCII BL.ByteString) where
+    arbitrary = ASCII <$> (repackBS <$> arbitrary <*> (fromASCII <$> arbitrary))
+    shrink = map (ASCII . BL.pack) . shrink . BL.unpack . fromASCII
 
 type Repack = NonEmptyList (Positive (Small Int))
 
diff --git a/tests/QC/Text.hs b/tests/QC/Text.hs
--- a/tests/QC/Text.hs
+++ b/tests/QC/Text.hs
@@ -3,9 +3,8 @@
 module QC.Text (tests) where
 
 #if !MIN_VERSION_base(4,8,0)
-import Control.Applicative ((<*>))
+import Control.Applicative ((<*>), (<$>))
 #endif
-import Control.Applicative ((<$>))
 import Data.Int (Int64)
 import Prelude hiding (take, takeWhile)
 import QC.Common (liftOp, parseT)
@@ -63,6 +62,12 @@
 string s t = parseT (P.string s') (s `L.append` t) === Just s'
   where s' = toStrict s
 
+strings :: L.Text -> L.Text -> L.Text -> Property
+strings s t u =
+    parseT (P.string (toStrict s) >> P.string t') (L.concat [s,t,u])
+    === Just t'
+  where t' = toStrict t
+
 stringCI :: T.Text -> Property
 stringCI s = P.parseOnly (P.stringCI fs) s === Right s
   where fs = T.toCaseFold s
@@ -171,6 +176,7 @@
     , testProperty "skip" skip
     , testProperty "skipWhile" skipWhile
     , testProperty "string" string
+    , testProperty "strings" strings
     , testProperty "stringCI" stringCI
     , testProperty "take" take
     , testProperty "takeText" takeText
