diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,9 @@
 # Changelog for streamly-bytestring
 
+## 0.2.2 (Jul 2024)
+
+* Fix a bug that uses an unpinned array in the foreign pointer
+
 ## 0.2.1 (Dec 2023)
 
 * Support streamly-core-0.2.0
diff --git a/src/Streamly/External/ByteString.hs b/src/Streamly/External/ByteString.hs
--- a/src/Streamly/External/ByteString.hs
+++ b/src/Streamly/External/ByteString.hs
@@ -42,15 +42,20 @@
 import qualified Streamly.Data.Array as Array
 import qualified Streamly.Internal.Data.Unfold as Unfold (fold, mkUnfoldrM)
 
+#if !(MIN_VERSION_bytestring(0,11,0))
+import GHC.ForeignPtr (plusForeignPtr)
+#endif
+
 #if MIN_VERSION_streamly_core(0,2,0)
 import Streamly.Internal.Data.Array (Array(..))
 import Streamly.Internal.Data.MutByteArray (MutByteArray(..))
-import qualified Streamly.Internal.Data.MutByteArray as MutBA (nil)
+import qualified Streamly.Internal.Data.Array as Array
+import qualified Streamly.Internal.Data.MutByteArray as MutBA
 import qualified Streamly.Internal.Data.Stream as StreamD (Step(Yield))
 #else
 import Streamly.Internal.Data.Array.Type (Array(..))
 import Streamly.Internal.Data.Unboxed (MutableByteArray(..))
-import qualified Streamly.Internal.Data.Unboxed as MutBA (nil)
+import qualified Streamly.Internal.Data.Unboxed as MutBA
 import qualified Streamly.Internal.Data.Stream.StreamD as StreamD (Step(Yield))
 #endif
 
@@ -62,6 +67,42 @@
 #define MUT_BYTE_ARRAY MutableByteArray
 #endif
 
+#if MIN_VERSION_streamly_core(0,2,2)
+#define NIL MutBA.empty
+#else
+#define NIL MutBA.nil
+#endif
+
+#if MIN_VERSION_bytestring(0,11,0)
+#define CONSTRUCTOR(a, b, c) BS a c
+#define WHEN_0_10_12(x)
+#else
+#define CONSTRUCTOR(a, b, c) PS a b c
+#define WHEN_0_10_12(x) x
+#endif
+
+
+{-# INLINE ensurePinned #-}
+ensurePinned :: Array a -> IO (Array a)
+{-# INLINE pinnedCreateOf #-}
+pinnedCreateOf :: MonadIO m => Int -> Fold m Word8 (Array Word8)
+{-# INLINE pinnedCreate #-}
+pinnedCreate :: MonadIO m => Fold m Word8 (Array Word8)
+
+#if MIN_VERSION_streamly_core(0,2,2)
+ensurePinned = Array.pin
+pinnedCreateOf = Array.pinnedCreateOf
+pinnedCreate = Array.pinnedCreate
+#elif MIN_VERSION_streamly_core(0,2,0)
+ensurePinned = Array.pin
+pinnedCreateOf = Array.pinnedWriteN
+pinnedCreate = Array.pinnedWrite
+#else
+ensurePinned = pure
+pinnedCreateOf = Array.writeN
+pinnedCreate = Array.write
+#endif
+
 {-# INLINE mutableByteArrayContents# #-}
 mutableByteArrayContents# :: MutableByteArray# RealWorld -> Addr#
 mutableByteArrayContents# marr# = byteArrayContents# (unsafeCoerce# marr#)
@@ -79,14 +120,16 @@
 -- there is a copy involved.
 {-# INLINE toArray #-}
 toArray :: ByteString -> Array Word8
-toArray (BS (ForeignPtr addr# _) _)
-    | Ptr addr# == nullPtr = Array MutBA.nil 0 0
-toArray (BS (ForeignPtr addr# (PlainPtr marr#)) len) =
+toArray (CONSTRUCTOR((ForeignPtr addr# _), _, _))
+    | Ptr addr# == nullPtr = Array NIL 0 0
+toArray (CONSTRUCTOR((ForeignPtr addr# (PlainPtr marr#)), off0, len)) =
     let off = I# (addr# `minusAddr#` mutableByteArrayContents# marr#)
+                  WHEN_0_10_12(+ off0)
      in Array (MUT_BYTE_ARRAY marr#) off (off + len)
-toArray (BS fptr len) =
+toArray (CONSTRUCTOR(fptr, off, len)) =
     unsafeInlineIO
-        $ withForeignPtr fptr $ Unfold.fold (Array.writeN len) generator
+        $ withForeignPtr (fptr WHEN_0_10_12(`plusForeignPtr` off))
+        $ Unfold.fold (Array.writeN len) generator
 
     where
 
@@ -94,18 +137,24 @@
         Unfold.mkUnfoldrM
             (\ptr -> flip StreamD.Yield (ptr `plusPtr` 1) <$> peek ptr)
 
--- | Convert an array of 'Word8' to a 'ByteString'. This function unwraps the
--- 'Array' and wraps it with 'ByteString' constructors and hence the operation
--- is performed in constant time.
+-- | Convert an array of 'Word8' to a 'ByteString'.
+--
+-- Please ensure that the array is pinned when using this function.
+
+-- If the array is pinned, the operation is performed in constant time. Whereas
+-- for an unpinned array a copy is involved to pin it.
+--
 {-# INLINE fromArray #-}
 fromArray :: Array Word8 -> ByteString
-fromArray (Array {..})
+fromArray arr
     | aLen == 0 = mempty
-    | otherwise = BS (makeForeignPtr arrContents arrStart) aLen
+    | otherwise = unsafeInlineIO $ do
+        Array{..} <- ensurePinned arr
+        pure $ CONSTRUCTOR((makeForeignPtr arrContents arrStart), 0, aLen)
 
     where
 
-    aLen = arrEnd - arrStart
+    aLen = arrEnd arr - arrStart arr
 
 -- | Unfold a strict ByteString to a stream of Word8.
 {-# INLINE reader #-}
@@ -115,12 +164,12 @@
 -- | Fold a stream of Word8 to a strict ByteString of given size in bytes.
 {-# INLINE writeN #-}
 writeN :: MonadIO m => Int -> Fold m Word8 ByteString
-writeN i = fromArray <$> Array.writeN i
+writeN i = fromArray <$> pinnedCreateOf i
 
 -- | Fold a stream of Word8 to a strict ByteString of appropriate size.
 {-# INLINE write #-}
 write :: MonadIO m => Fold m Word8 ByteString
-write = fromArray <$> Array.write
+write = fromArray <$> pinnedCreate
 
 --------------------------------------------------------------------------------
 -- Deprecated
diff --git a/streamly-bytestring.cabal b/streamly-bytestring.cabal
--- a/streamly-bytestring.cabal
+++ b/streamly-bytestring.cabal
@@ -1,6 +1,6 @@
 cabal-version:  1.12
 name:           streamly-bytestring
-version:        0.2.1
+version:        0.2.2
 synopsis:       Library for streamly and bytestring interoperation.
 description:    Please see the README on GitHub at <https://github.com/psibi/streamly-bytestring#readme>
 category:       Streamly, Stream, ByteString
@@ -38,7 +38,8 @@
   ghc-options: -Wall -O2
   build-depends:
       base >=4.7 && <5
-    , bytestring    == 0.11.0.*
+    , bytestring    == 0.10.12.*
+                 || == 0.11.0.*
                  || == 0.11.1.*
                  || == 0.11.2.*
                  -- bytestring-0.11.3.0 causes panics and other issues on
@@ -47,7 +48,7 @@
                  || == 0.11.4.*
                  || == 0.11.5.*
                  || == 0.12.0.*
-    , streamly-core >= 0.1.0 && < 0.2.2
+    , streamly-core >= 0.1.0 && < 0.2.3
   default-language: Haskell2010
 
 test-suite sb-test
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,8 +1,12 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
 
 module Main where
 
+import Control.Monad (when)
+import System.Mem (performMajorGC)
+import Control.Concurrent (threadDelay)
 import Data.ByteString (ByteString)
 import Data.Word (Word8)
 import GHC.IO.Handle (Handle)
@@ -28,6 +32,7 @@
 import qualified Streamly.External.ByteString.Lazy as Lazy
 import qualified Streamly.Data.Stream as S
 import qualified Streamly.Data.Fold as Fold
+import qualified Streamly.Internal.Data.Array as Array
 
 streamToByteString :: Monad m => S.Stream m (Array Word8) -> m ByteString
 streamToByteString stream =
@@ -101,10 +106,28 @@
         S.fromList (Strict.toArray (BS.singleton h) : undefined)
     return $ BSL.head lbs
 
+checkPinnedNature :: IO ()
+checkPinnedNature = do
+    (arr :: Array Word8) <-
+        Array.fromStream (S.fromList (take 1000 (cycle [0..255])))
+    performMajorGC
+    threadDelay 50000
+    threadDelay 50000
+    performMajorGC
+    threadDelay 50000
+    threadDelay 50000
+    (_ :: Array Word8) <-
+        Array.fromStream (S.fromList (take 10000 (cycle [0..255])))
+    let bs = Strict.fromArray arr
+        lst1 = BS.unpack bs
+        lst2 = Array.toList arr
+    when (lst1 /= lst2) $ error "Pinned nature isn't ensured"
+
 main :: IO ()
 main =
     hspec $ do
         describe "Array tests" $ do
+            it "Pinned in nature" $ checkPinnedNature
             it "Strict fromArray" $
                 mapM_
                     (flip withSystemTempFile checkFileContent . show)
