diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,16 @@
 # Revision history for base64
 
+## 0.4.2.4
+
+* Support for GHC 9.2.x
+* Remove dependency on `ghc-byteorder`
+* Bump base lower bound to GHC 8.10.x to make sure endianness is properly support
+  (see: https://gitlab.haskell.org/ghc/ghc/-/issues/20338)
+* Bump upper bound for `deepseq`
+
 ## 0.4.2.3
 
-* Minor release for stackage, limiting memory usage in test suites.
-* Transition to Github Actions CI
+* Tighter length calculations in unpadded base64url [#35](https://github.com/emilypi/base64/pull/35)
 
 ## 0.4.2.2
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Base64
 
-[![Build Status](https://travis-ci.com/emilypi/base64.svg?branch=master)](https://travis-ci.com/emilypi/base64)
+![Build Status](https://github.com/emilypi/base64/workflows/Haskell-CI/badge.svg)
 [![Hackage](https://img.shields.io/hackage/v/base64.svg)](https://hackage.haskell.org/package/base64)
 
 Base64 encoding and decodings.
diff --git a/base64.cabal b/base64.cabal
--- a/base64.cabal
+++ b/base64.cabal
@@ -1,6 +1,6 @@
 cabal-version:   2.0
 name:            base64
-version:         0.4.2.3
+version:         0.4.2.4
 synopsis:        A modern RFC 4648-compliant Base64 library
 description:
   RFC 4648-compliant Base64 with an eye towards performance and modernity (additional support for RFC 7049 standards)
@@ -11,14 +11,14 @@
 license-file:    LICENSE
 author:          Emily Pillmore
 maintainer:      emilypi@cohomolo.gy
-copyright:       (c) 2019-2020 Emily Pillmore
+copyright:       (c) 2019-2022 Emily Pillmore
 category:        Data
 build-type:      Simple
 extra-doc-files:
   CHANGELOG.md
   README.md
 
-tested-with:     GHC ==8.2.2 || ==8.4.4 || ==8.6.5 || ==8.8.4 || ==8.10.3
+tested-with:     GHC ==8.10.7 || ==9.0.2 || ==9.2.2
 
 source-repository head
   type:     git
@@ -51,10 +51,9 @@
     Data.ByteString.Base64.Internal.W64.Loop
 
   build-depends:
-      base           >=4.10     && <5
+      base           >=4.14     && <4.17
     , bytestring     >=0.10     && <0.12
-    , deepseq        >=1.4.3.0  && <1.4.5.0
-    , ghc-byteorder  ^>=4.11.0.0
+    , deepseq        >=1.4.3.0  && <1.5
     , text           ^>=1.2
     , text-short     ^>=0.1
 
@@ -69,7 +68,7 @@
   other-modules:    Internal
   main-is:          Main.hs
   build-depends:
-      base               >=4.10 && <5
+      base               >=4.14 && <4.17
     , base64
     , base64-bytestring
     , bytestring
@@ -89,7 +88,7 @@
   hs-source-dirs:   benchmarks
   main-is:          Base64Bench.hs
   build-depends:
-      base               >=4.10 && <5
+      base               >=4.14 && <4.17
     , base64
     , base64-bytestring
     , bytestring
diff --git a/src/Data/ByteString/Base64.hs b/src/Data/ByteString/Base64.hs
--- a/src/Data/ByteString/Base64.hs
+++ b/src/Data/ByteString/Base64.hs
@@ -85,11 +85,9 @@
     | l == 0 = Right bs
     | r == 1 = Left "Base64-encoded bytestring has invalid size"
     | r /= 0 = Left "Base64-encoded bytestring requires padding"
-    | otherwise = unsafeDupablePerformIO $ decodeBase64_ dlen decodeB64Table bs
+    | otherwise = unsafeDupablePerformIO $ decodeBase64_ decodeB64Table bs
   where
-    !q = l `quot` 4
     !r = l `rem` 4
-    !dlen = q * 3
 {-# inline decodeBase64 #-}
 
 -- | Leniently decode an unpadded Base64-encoded 'ByteString' value. This function
diff --git a/src/Data/ByteString/Base64/Internal/Head.hs b/src/Data/ByteString/Base64/Internal/Head.hs
--- a/src/Data/ByteString/Base64/Internal/Head.hs
+++ b/src/Data/ByteString/Base64/Internal/Head.hs
@@ -88,11 +88,10 @@
 -- padded string.
 --
 decodeBase64_
-    :: Int
-    -> ForeignPtr Word8
+    :: ForeignPtr Word8
     -> ByteString
     -> IO (Either Text ByteString)
-decodeBase64_ !dlen !dtfp (PS !sfp !soff !slen) =
+decodeBase64_ !dtfp (PS !sfp !soff !slen) =
     withForeignPtr dtfp $ \dtable ->
     withForeignPtr sfp $ \sptr -> do
       dfp <- mallocPlainForeignPtrBytes dlen
@@ -101,6 +100,8 @@
         decodeLoop dtable
           (plusPtr sptr soff)
           dptr end dfp
+  where
+    !dlen = (slen `quot` 4) * 3
 {-# inline decodeBase64_ #-}
 
 decodeBase64Lenient_ :: ForeignPtr Word8 -> ByteString -> ByteString
diff --git a/src/Data/ByteString/Base64/Internal/Utils.hs b/src/Data/ByteString/Base64/Internal/Utils.hs
--- a/src/Data/ByteString/Base64/Internal/Utils.hs
+++ b/src/Data/ByteString/Base64/Internal/Utils.hs
@@ -2,7 +2,7 @@
 {-# LANGUAGE MagicHash #-}
 -- |
 -- Module       : Data.ByteString.Base64.Internal
--- Copyright    : (c) 2019-2020 Emily Pillmore
+-- Copyright    : (c) 2019-2022 Emily Pillmore
 -- License      : BSD-style
 --
 -- Maintainer   : Emily Pillmore <emilypi@cohomolo.gy>
@@ -54,7 +54,9 @@
 -- | Read 'Word8' index off alphabet addr
 --
 aix :: Word8 -> Addr# -> Word8
-aix (W8# i) alpha = W8# (indexWord8OffAddr# alpha (word2Int# i))
+aix w8 alpha = W8# (indexWord8OffAddr# alpha i)
+  where
+    !(I# i) = fromIntegral w8
 {-# INLINE aix #-}
 
 -- | Convert 'Word8''s into 'Word32''s
@@ -155,11 +157,11 @@
 peekWord32BE :: Ptr Word32 -> IO Word32
 peekWord32BE p = case targetByteOrder of
   LittleEndian -> byteSwap32 <$> peek p
-  BigEndian    -> peek p
+  BigEndian -> peek p
 {-# inline peekWord32BE #-}
 
 peekWord64BE :: Ptr Word64 -> IO Word64
 peekWord64BE p = case targetByteOrder of
   LittleEndian -> byteSwap64 <$> peek p
-  BigEndian    -> peek p
+  BigEndian -> peek p
 {-# inline peekWord64BE #-}
diff --git a/src/Data/ByteString/Base64/URL.hs b/src/Data/ByteString/Base64/URL.hs
--- a/src/Data/ByteString/Base64/URL.hs
+++ b/src/Data/ByteString/Base64/URL.hs
@@ -94,14 +94,12 @@
 decodeBase64 :: ByteString -> Either Text ByteString
 decodeBase64 bs@(PS _ _ !l)
     | l == 0 = Right bs
-    | r == 0 = unsafeDupablePerformIO $ decodeBase64_ dlen decodeB64UrlTable bs
-    | r == 2 = unsafeDupablePerformIO $ decodeBase64_ dlen decodeB64UrlTable (BS.append bs "==")
-    | r == 3 = validateLastPad bs $ decodeBase64_ dlen decodeB64UrlTable (BS.append bs "=")
+    | r == 0 = unsafeDupablePerformIO $ decodeBase64_ decodeB64UrlTable bs
+    | r == 2 = unsafeDupablePerformIO $ decodeBase64_ decodeB64UrlTable (BS.append bs "==")
+    | r == 3 = validateLastPad bs $ decodeBase64_ decodeB64UrlTable (BS.append bs "=")
     | otherwise = Left "Base64-encoded bytestring has invalid size"
   where
-    !q = l `quot` 4
     !r = l `rem` 4
-    !dlen = q * 3
 {-# INLINE decodeBase64 #-}
 
 -- | Encode a 'ByteString' value as Base64url 'Text' without padding. Note that for Base64url,
@@ -153,14 +151,12 @@
 decodeBase64Unpadded :: ByteString -> Either Text ByteString
 decodeBase64Unpadded bs@(PS _ _ !l)
     | l == 0 = Right bs
-    | r == 0 = validateLastPad bs $ decodeBase64_ dlen decodeB64UrlTable bs
-    | r == 2 = validateLastPad bs $ decodeBase64_ dlen decodeB64UrlTable (BS.append bs "==")
-    | r == 3 = validateLastPad bs $ decodeBase64_ dlen decodeB64UrlTable (BS.append bs "=")
+    | r == 0 = validateLastPad bs $ decodeBase64_ decodeB64UrlTable bs
+    | r == 2 = validateLastPad bs $ decodeBase64_ decodeB64UrlTable (BS.append bs "==")
+    | r == 3 = validateLastPad bs $ decodeBase64_ decodeB64UrlTable (BS.append bs "=")
     | otherwise = Left "Base64-encoded bytestring has invalid size"
   where
-    !q = l `quot` 4
     !r = l `rem` 4
-    !dlen = q * 3
 {-# INLINE decodeBase64Unpadded #-}
 
 -- | Decode a padded Base64url-encoded 'ByteString' value. Input strings are
@@ -185,11 +181,9 @@
     | l == 0 = Right bs
     | r == 1 = Left "Base64-encoded bytestring has invalid size"
     | r /= 0 = Left "Base64-encoded bytestring requires padding"
-    | otherwise = unsafeDupablePerformIO $ decodeBase64_ dlen decodeB64UrlTable bs
+    | otherwise = unsafeDupablePerformIO $ decodeBase64_ decodeB64UrlTable bs
   where
-    !q = l `quot` 4
     !r = l `rem` 4
-    !dlen = q * 3
 {-# INLINE decodeBase64Padded #-}
 
 -- | Leniently decode an unpadded Base64url-encoded 'ByteString'. This function
