Skip to content

Commit 947aa93

Browse files
committed
Fixed some overflows and arithmetic errors in fusion.
- Size addition and subtraction now checks for overflows and underflows - drop on Bundles was simply subtracting size; implemented a subtraction that clamps to 0 for it.
1 parent 0d83927 commit 947aa93

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

Data/Vector/Fusion/Bundle/Monadic.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,8 @@ take n Bundle{sElems = s, sSize = sz} = fromStream (S.take n s) (smaller (Exact
266266
-- | All but the first @n@ elements
267267
drop :: Monad m => Int -> Bundle m v a -> Bundle m v a
268268
{-# INLINE_FUSED drop #-}
269-
drop n Bundle{sElems = s, sSize = sz} = fromStream (S.drop n s) (sz - Exact n)
269+
drop n Bundle{sElems = s, sSize = sz} =
270+
fromStream (S.drop n s) (clampedSubtract sz (Exact n))
270271

271272
-- Mapping
272273
-- -------

Data/Vector/Fusion/Bundle/Size.hs

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
--
1212

1313
module Data.Vector.Fusion.Bundle.Size (
14-
Size(..), smaller, larger, toMax, upperBound, lowerBound
14+
Size(..), clampedSubtract, smaller, larger, toMax, upperBound, lowerBound
1515
) where
1616

1717
import Data.Vector.Fusion.Util ( delay_inline )
@@ -23,19 +23,19 @@ data Size = Exact Int -- ^ Exact size
2323
deriving( Eq, Show )
2424

2525
instance Num Size where
26-
Exact m + Exact n = Exact (m+n)
27-
Exact m + Max n = Max (m+n)
26+
Exact m + Exact n = checkedAdd Exact m n
27+
Exact m + Max n = checkedAdd Max m n
2828

29-
Max m + Exact n = Max (m+n)
30-
Max m + Max n = Max (m+n)
29+
Max m + Exact n = checkedAdd Max m n
30+
Max m + Max n = checkedAdd Max m n
3131

3232
_ + _ = Unknown
3333

3434

35-
Exact m - Exact n = Exact (m-n)
35+
Exact m - Exact n = checkedSubtract Exact m n
3636
Exact m - Max _ = Max m
3737

38-
Max m - Exact n = Max (m-n)
38+
Max m - Exact n = checkedSubtract Max m n
3939
Max m - Max _ = Max m
4040
Max m - Unknown = Max m
4141

@@ -48,6 +48,34 @@ instance Num Size where
4848
abs = error "vector: internal error abs for Bundle.size isn't defined"
4949
signum = error "vector: internal error signum for Bundle.size isn't defined"
5050

51+
{-# INLINE checkedAdd #-}
52+
checkedAdd :: (Int -> Size) -> Int -> Int -> Size
53+
checkedAdd con m n
54+
| r <= m =
55+
error $ "Data.Vector.Fusion.Bundle.Size.checkedAdd: overflow: " ++ show r
56+
| otherwise = con r
57+
where
58+
r = m + n
59+
60+
{-# INLINE checkedSubtract #-}
61+
checkedSubtract :: (Int -> Size) -> Int -> Int -> Size
62+
checkedSubtract con m n
63+
| r < 0 =
64+
error $ "Data.Vector.Fusion.Bundle.Size.checkedSubtract: underflow: " ++ show r
65+
| otherwise = con r
66+
where
67+
r = m - n
68+
69+
-- | Subtract two sizes with clamping to 0, for drop-like things
70+
{-# INLINE clampedSubtract #-}
71+
clampedSubtract :: Size -> Size -> Size
72+
clampedSubtract (Exact m) (Exact n) = Exact (max 0 (m - n))
73+
clampedSubtract (Max m) (Exact n)
74+
| m <= n = Exact 0
75+
| otherwise = Max (m - n)
76+
clampedSubtract (Exact m) (Max _) = Max m
77+
clampedSubtract (Max m) (Max _) = Max m
78+
clampedSubtract _ _ = Unknown
5179

5280
-- | Minimum of two size hints
5381
smaller :: Size -> Size -> Size

0 commit comments

Comments
 (0)