diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,14 @@
 See also http://pvp.haskell.org/faq
 
+# 1.2.1.0
+
+* Bugfix for GHC 9.0.1 memory corruption bug ([#46](https://github.com/haskell/base64-bytestring/pull/46))
+  * Thanks to [Fraser Tweedale](https://github.com/frasertweedale) and [Andrew Lelechenko](https://github.com/bodigrim) for logging and helping with this fix.
+
 # 1.2.0.1
 
 * Package update: support for `bytestring >=0.11`
- 
+
 # 1.2.0.0
 
 * Security fix: reject non-canonical base64 encoded values - ([#38](https://github.com/haskell/base64-bytestring/pull/38)) fixing issue [#24](https://github.com/haskell/base64-bytestring/issues/24).
diff --git a/Data/ByteString/Base64/Internal.hs b/Data/ByteString/Base64/Internal.hs
--- a/Data/ByteString/Base64/Internal.hs
+++ b/Data/ByteString/Base64/Internal.hs
@@ -49,13 +49,13 @@
 -- | Encode a string into base64 form.  The result will always be a multiple
 -- of 4 bytes in length.
 encodeWith :: Padding -> EncodeTable -> ByteString -> ByteString
-encodeWith !padding !(ET alfaFP encodeTable) !bs = withBS bs go
+encodeWith !padding (ET alfaFP encodeTable) !bs = withBS bs go
   where
     go !sptr !slen
       | slen > maxBound `div` 4 =
         error "Data.ByteString.Base64.encode: input too long"
       | otherwise = do
-        let dlen = ((slen + 2) `div` 3) * 4
+        let dlen = (slen + 2) `div` 3 * 4
         dfp <- mallocByteString dlen
         withForeignPtr alfaFP $ \aptr ->
           withForeignPtr encodeTable $ \ep -> do
@@ -68,7 +68,7 @@
                   i <- peek8_32 sp
                   j <- peek8_32 (sp `plusPtr` 1)
                   k <- peek8_32 (sp `plusPtr` 2)
-                  let w = (i `shiftL` 16) .|. (j `shiftL` 8) .|. k
+                  let w = i `shiftL` 16 .|. j `shiftL` 8 .|. k
                       enc = peekElemOff ep . fromIntegral
                   poke dp =<< enc (w `shiftR` 12)
                   poke (dp `plusPtr` 2) =<< enc (w .&. 0xfff)
@@ -107,7 +107,7 @@
                         else finish (n + 2)
 
 
-            withForeignPtr dfp $! \dptr -> fill (castPtr dptr) sptr 0
+            withForeignPtr dfp (\dptr -> fill (castPtr dptr) sptr 0)
 
 data EncodeTable = ET !(ForeignPtr Word8) !(ForeignPtr Word16)
 
@@ -155,18 +155,16 @@
       | r == 3 -> validateLastPad bs noPad $ withBS (B.append bs (B.replicate 1 0x3d)) go
       | otherwise -> Left "Base64-encoded bytestring has invalid size"
   where
-    (!q, !r) = (B.length bs) `divMod` 4
+    !r = B.length bs `rem` 4
 
     noPad = "Base64-encoded bytestring required to be unpadded"
     invalidPad = "Base64-encoded bytestring has invalid padding"
 
-    !dlen = q * 3
-
     go !sptr !slen = do
-      dfp <- mallocByteString dlen
-      withForeignPtr decodeFP $! \ !decptr ->
-        withForeignPtr dfp $! \dptr ->
-          decodeLoop decptr sptr dptr (sptr `plusPtr` slen) dfp
+      dfp <- mallocByteString (slen `quot` 4 * 3)
+      withForeignPtr decodeFP (\ !decptr ->
+        withForeignPtr dfp (\dptr ->
+          decodeLoop decptr sptr dptr (sptr `plusPtr` slen) dfp))
 
 decodeLoop
     :: Ptr Word8
@@ -229,9 +227,9 @@
      | c == 0xff = err (plusPtr src 2)
      | d == 0xff = err (plusPtr src 3)
      | otherwise = do
-       let !w = ((shiftL a 18)
-             .|. (shiftL b 12)
-             .|. (shiftL c 6)
+       let !w = (shiftL a 18
+             .|. shiftL b 12
+             .|. shiftL c 6
              .|. d) :: Word32
 
        poke8 dst (fromIntegral (shiftR w 16))
@@ -252,9 +250,9 @@
       | c == 0xff = err (plusPtr src 2)
       | d == 0xff = err (plusPtr src 3)
       | otherwise = do
-        let !w = ((shiftL a 18)
-              .|. (shiftL b 12)
-              .|. (shiftL c 6)
+        let !w = (shiftL a 18
+              .|. shiftL b 12
+              .|. shiftL c 6
               .|. d) :: Word32
 
         poke8 dst (fromIntegral (shiftR w 16))
@@ -308,7 +306,7 @@
                              | otherwise = {-# SCC "decodeLenient/look" #-} do
                           ix <- fromIntegral `fmap` peek8 p
                           v <- peek8 (decptr `plusPtr` ix)
-                          if v == x || (v == done && skipPad)
+                          if v == x || v == done && skipPad
                             then go' (p `plusPtr` 1)
                             else f (p `plusPtr` 1) (fromIntegral v)
                 in look True sp $ \ !aNext !aValue ->
@@ -318,8 +316,8 @@
                      else
                         look False bNext $ \ !cNext !cValue ->
                         look False cNext $ \ !dNext !dValue -> do
-                          let w = (aValue `shiftL` 18) .|. (bValue `shiftL` 12) .|.
-                                  (cValue `shiftL` 6) .|. dValue
+                          let w = aValue `shiftL` 18 .|. bValue `shiftL` 12 .|.
+                                  cValue `shiftL` 6 .|. dValue
                           poke8 dp $ fromIntegral (w `shiftR` 16)
                           if cValue == done
                             then finish (n + 1)
@@ -332,7 +330,7 @@
                                   fill (dp `plusPtr` 3) dNext (n+3)
           withForeignPtr dfp $ \dptr -> fill dptr sptr 0
       where
-        !dlen = ((slen + 3) `div` 4) * 3
+        !dlen = (slen + 3) `div` 4 * 3
 
 x :: Integral a => a
 x = 255
@@ -405,7 +403,7 @@
 -- it's coherent. If pos & mask == 0, we're good. If not, we should fail.
 --
 sanityCheckPos :: Word32 -> Word8 -> Bool
-sanityCheckPos pos mask = ((fromIntegral pos) .&. mask) == 0
+sanityCheckPos pos mask = fromIntegral pos .&. mask == 0
 {-# INLINE sanityCheckPos #-}
 
 -- | Mask 2 bits
diff --git a/base64-bytestring.cabal b/base64-bytestring.cabal
--- a/base64-bytestring.cabal
+++ b/base64-bytestring.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.12
 name:               base64-bytestring
-version:            1.2.0.1
+version:            1.2.1.0
 synopsis:           Fast base64 encoding and decoding for ByteStrings
 description:
   This package provides support for encoding and decoding binary data according to @base64@ (see also <https://tools.ietf.org/html/rfc4648 RFC 4648>) for strict and lazy ByteStrings
@@ -31,9 +31,8 @@
    || ==8.2.2
    || ==8.4.4
    || ==8.6.5
-   || ==8.8.3
-   || ==8.10.1
-   || ==8.10.2
+   || ==8.8.4
+   || ==8.10.5
 
 extra-source-files:
   README.md
