diff --git a/bench/Bench/Product.hs b/bench/Bench/Product.hs
--- a/bench/Bench/Product.hs
+++ b/bench/Bench/Product.hs
@@ -36,14 +36,14 @@
 benchProduct :: Int -> Benchmark
 benchProduct k = bgroup (show (1 `shiftL` k :: Int))
   [ bench "Bit/product"          $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x)    (toF2Poly $ randomVec2 Bit k)
-  -- , bench "Bit/productShort"     $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x)    (toF2Poly $ U.take 32 $ randomVec2 Bit k)
-  -- , bench "Bit/square"           $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x)    (toF2Poly $ randomVec Bit k)
-  -- , bench "Bit.TS/product"       $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k)
-  -- , bench "Bit.TS/productShort"  $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ U.take 32 $ randomVec2 TS.Bit k)
-  -- , bench "Bit.TS/square"        $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec TS.Bit k)
+  , bench "Bit/productShort"     $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x)    (toF2Poly $ U.take 32 $ randomVec2 Bit k)
+  , bench "Bit/square"           $ nf (\x -> (*) (toF2Poly $ randomVec Bit k) x)    (toF2Poly $ randomVec Bit k)
+  , bench "Bit.TS/product"       $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k)
+  , bench "Bit.TS/productShort"  $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ U.take 32 $ randomVec2 TS.Bit k)
+  , bench "Bit.TS/square"        $ nf (\x -> (*) (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec TS.Bit k)
   , bench "Integer/product"      $ nf (\x -> binMul (randomInteger k) x) (randomInteger2 k)
-  -- , bench "Integer/productShort" $ nf (\x -> binMul (randomInteger k) x) ((1 `shiftL` 32 - 1) .&. randomInteger2 k)
-  -- , bench "Integer/square"       $ nf (\x -> binMul (randomInteger k) x) (randomInteger k)
+  , bench "Integer/productShort" $ nf (\x -> binMul (randomInteger k) x) ((1 `shiftL` 32 - 1) .&. randomInteger2 k)
+  , bench "Integer/square"       $ nf (\x -> binMul (randomInteger k) x) (randomInteger k)
   ]
 
 binMul :: Integer -> Integer -> Integer
diff --git a/bench/Bench/Remainder.hs b/bench/Bench/Remainder.hs
--- a/bench/Bench/Remainder.hs
+++ b/bench/Bench/Remainder.hs
@@ -40,7 +40,7 @@
 benchRemainder :: Int -> Benchmark
 benchRemainder k = bgroup (show (1 `shiftL` k :: Int))
   [ bench "Bit/remainder"     $ nf (\x -> rem (toF2Poly $ randomVec Bit k) x) (toF2Poly $ randomVec2 Bit k)
-  -- , bench "Bit.TS/remainder"  $ nf (\x -> rem (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k)
+  , bench "Bit.TS/remainder"  $ nf (\x -> rem (TS.toF2Poly $ randomVec TS.Bit k) x) (TS.toF2Poly $ randomVec2 TS.Bit k)
   , bench "Integer/remainder" $ nf (\x -> binRem (randomInteger k) x) (randomInteger2 k)
   ]
 
diff --git a/bitvec.cabal b/bitvec.cabal
--- a/bitvec.cabal
+++ b/bitvec.cabal
@@ -1,5 +1,5 @@
 name: bitvec
-version: 1.0.1.1
+version: 1.0.1.2
 cabal-version: >=1.10
 build-type: Simple
 license: BSD3
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+# 1.0.1.2
+
+* Fix more bugs in 'F2Poly' multiplication.
+
 # 1.0.1.1
 
 * Fix bugs in 'F2Poly' multiplication.
diff --git a/src/Data/Bit/F2Poly.hs b/src/Data/Bit/F2Poly.hs
--- a/src/Data/Bit/F2Poly.hs
+++ b/src/Data/Bit/F2Poly.hs
@@ -234,13 +234,13 @@
 
 sqrBits :: U.Vector Bit -> U.Vector Bit
 sqrBits xs = runST $ do
-    let lenXs = U.length xs
-    zs <- MU.replicate (lenXs `shiftL` 1) (Bit False)
-    forM_ [0, wordSize .. lenXs - 1] $ \i -> do
-      let (z0, z1) = sparseBits (indexWord xs i)
-      writeWord zs (i `shiftL` 1) z0
-      writeWord zs (i `shiftL` 1 + wordSize) z1
-    U.unsafeFreeze zs
+  let lenXs = U.length xs
+  zs <- MU.replicate (mulWordSize (nWords lenXs `shiftL` 1)) (Bit False)
+  forM_ [0, wordSize .. lenXs - 1] $ \i -> do
+    let (z0, z1) = sparseBits (indexWord xs i)
+    writeWord zs (i `shiftL` 1) z0
+    writeWord zs ((i `shiftL` 1) + wordSize) z1
+  U.unsafeFreeze zs
 
 quotRemBits :: U.Vector Bit -> U.Vector Bit -> (U.Vector Bit, U.Vector Bit)
 quotRemBits xs ys
@@ -303,7 +303,7 @@
   $ dropWhile (\(_, b) -> x >= b)
   $ map (\a -> (a, 1 `shiftL` a))
   $ map (1 `shiftL`)
-  $ [0..]
+  $ [lgWordSize..]
 
 bitsToInteger :: U.Vector Bit -> Integer
 bitsToInteger = U.ifoldl' (\acc i (Bit b) -> if b then acc `setBit` i else acc) 0
diff --git a/src/Data/Bit/Internal.hs b/src/Data/Bit/Internal.hs
--- a/src/Data/Bit/Internal.hs
+++ b/src/Data/Bit/Internal.hs
@@ -139,6 +139,7 @@
 
 -- | read a word at the given bit offset in little-endian order (i.e., the LSB will correspond to the bit at the given address, the 2's bit will correspond to the address + 1, etc.).  If the offset is such that the word extends past the end of the vector, the result is padded with memory garbage.
 indexWord :: U.Vector Bit -> Int -> Word
+indexWord !(BitVec _ 0 _) _ = 0
 indexWord !(BitVec off len' arr) !i' = word
  where
   len    = off + len'
@@ -159,6 +160,7 @@
 
 -- | read a word at the given bit offset in little-endian order (i.e., the LSB will correspond to the bit at the given address, the 2's bit will correspond to the address + 1, etc.).  If the offset is such that the word extends past the end of the vector, the result is padded with memory garbage.
 readWord :: PrimMonad m => U.MVector (PrimState m) Bit -> Int -> m Word
+readWord !(BitMVec _ 0 _) _ = pure 0
 readWord !(BitMVec off len' arr) !i' = do
   let len  = off + len'
       i    = off + i'
@@ -182,6 +184,7 @@
 
 -- | write a word at the given bit offset in little-endian order (i.e., the LSB will correspond to the bit at the given address, the 2's bit will correspond to the address + 1, etc.).  If the offset is such that the word extends past the end of the vector, the word is truncated and as many low-order bits as possible are written.
 writeWord :: PrimMonad m => U.MVector (PrimState m) Bit -> Int -> Word -> m ()
+writeWord !(BitMVec _ 0 _) _ _ = pure ()
 writeWord !(BitMVec off len' arr) !i' !x = do
   let len    = off + len'
       lenMod = modWordSize len
diff --git a/src/Data/Bit/Utils.hs b/src/Data/Bit/Utils.hs
--- a/src/Data/Bit/Utils.hs
+++ b/src/Data/Bit/Utils.hs
@@ -2,7 +2,8 @@
 {-# LANGUAGE CPP                        #-}
 
 module Data.Bit.Utils
-  ( modWordSize
+  ( lgWordSize
+  , modWordSize
   , divWordSize
   , mulWordSize
   , wordSize
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -49,7 +49,9 @@
 f2polyTests = testGroup "F2Poly"
   [ testProperty "Addition"       prop_f2polyAdd
   , testProperty "Multiplication" prop_f2polyMul
+  , testProperty "Square" prop_f2polySqr
   , tenTimesLess $ testProperty "Multiplication long" prop_f2polyMulLong
+  , tenTimesLess $ testProperty "Square long" prop_f2polySqrLong
   , testProperty "Remainder"      prop_f2polyRem
   , tenTimesLess $ lawsToTest $
     showLaws (Proxy :: Proxy F2Poly)
@@ -67,11 +69,19 @@
 prop_f2polyMul :: F2Poly -> F2Poly -> Property
 prop_f2polyMul x y = x * y === fromInteger (toInteger x `binMul` toInteger y)
 
+prop_f2polySqr :: F2Poly -> Property
+prop_f2polySqr x = x * x === fromInteger (toInteger x `binMul` toInteger x)
+
 prop_f2polyMulLong :: U.Vector Word -> U.Vector Word -> Property
 prop_f2polyMulLong xs ys = x * y === fromInteger (toInteger x `binMul` toInteger y)
   where
     x = toF2Poly $ castFromWords xs
     y = toF2Poly $ castFromWords ys
+
+prop_f2polySqrLong :: U.Vector Word -> Property
+prop_f2polySqrLong xs = x * x === fromInteger (toInteger x `binMul` toInteger x)
+  where
+    x = toF2Poly $ castFromWords xs
 
 prop_f2polyRem :: F2Poly -> F2Poly -> Property
 prop_f2polyRem x y = y /= 0 ==> x `rem` y === fromInteger (toInteger x `binRem` toInteger y)
