on master help sign in
Make bounds checking safer

--HG-- extra : convert_revision : bcf03182e3c495f4f358d34edf8e3b5fcaeebcec

commitd84a2ecbaeb3d8272ce54b784830df7813597911 authorBryan O'Sullivan <bos@serpentine.com> dateTue 5 Oct 2010, 06:03 (16 years ago) parent8c34924
2 files changed+31−15
Data/Text.hs+27−12 Data/Text/Array.hs+4−3
Data/Text.hs+27−12
@@ -174,7 +174,7 @@ import Prelude (Char, Bool(..), Functor(..), Int, Maybe(..), String,
174174 Eq(..), Ord(..), Ordering(..), (++),
175175 Read(..), Show(..),
176176 (&&), (||), (+), (-), (.), ($), ($!), (>>), (*),
177− div, error, not, return, otherwise)
177+ div, maxBound, not, return, otherwise)
178178#if defined(HAVE_DEEPSEQ)
179179import Control.DeepSeq (NFData)
180180#endif
@@ -294,8 +294,8 @@ instance NFData Text
294294
295295instance Data Text where
296296 gfoldl f z txt = z pack `f` (unpack txt)
297− toConstr _ = error "Data.Text.Text.toConstr"
298− gunfold _ _ = error "Data.Text.Text.gunfold"
297+ toConstr _ = P.error "Data.Text.Text.toConstr"
298+ gunfold _ _ = P.error "Data.Text.Text.gunfold"
299299#if __GLASGOW_HASKELL__ >= 612
300300 dataTypeOf _ = mkNoRepType "Data.Text.Text"
301301#else
@@ -340,7 +340,11 @@ snoc t c = unstream (S.snoc (stream t) c)
340340-- | /O(n)/ Appends one 'Text' to the other by copying both of them
341341-- into a new 'Text'. Subject to fusion.
342342append :: Text -> Text -> Text
343−append (Text arr1 off1 len1) (Text arr2 off2 len2) = Text (A.run x) 0 len
343+append a@(Text arr1 off1 len1) b@(Text arr2 off2 len2)
344+ | len1 == 0 = b
345+ | len2 == 0 = a
346+ | len > 0 = Text (A.run x) 0 len
347+ | otherwise = overflowError "append"
344348 where
345349 len = len1+len2
346350 x = do
@@ -706,7 +710,7 @@ concat ts = case ts' of
706710 _ -> Text (A.run go) 0 len
707711 where
708712 ts' = L.filter (not . null) ts
709− len = L.sum $ L.map lengthWord16 ts'
713+ len = sumP "concat" $ L.map lengthWord16 ts'
710714 go = do
711715 arr <- A.new len
712716 let step i (Text a o l) =
@@ -804,12 +808,11 @@ mapAccumR f z0 = second reverse . S.mapAccumL f z0 . reverseStream
804808-- @t@ repeated @n@ times.
805809replicate :: Int -> Text -> Text
806810replicate n t@(Text a o l)
807− | n <= 0 || l <= 0 = empty
808− | n == 1 = t
809− | isSingleton t = replicateChar n (unsafeHead t)
810− | len < n = error $ "Data.Text.replicate: invalid length " ++
811− show n -- multiplication overflow
812− | otherwise = Text (A.run x) 0 len
811+ | n <= 0 || l <= 0 = empty
812+ | n == 1 = t
813+ | isSingleton t = replicateChar n (unsafeHead t)
814+ | n <= maxBound `div` l = Text (A.run x) 0 len
815+ | otherwise = overflowError "replicate"
813816 where
814817 len = l * n
815818 x = do
@@ -1440,5 +1443,17 @@ stripSuffix p@(Text _arr _off plen) t@(Text arr off len)
14401443 | p `isSuffixOf` t = Just $! textP arr off (len-plen)
14411444 | otherwise = Nothing
14421445
1446+-- | Add a list of non-negative numbers. Errors out on overflow.
1447+sumP :: String -> [Int] -> Int
1448+sumP fun = go 0
1449+ where go !a (x:xs)
1450+ | ax >= 0 = go ax xs
1451+ | otherwise = overflowError fun
1452+ where ax = a + x
1453+ go a _ = a
1454+
14431455emptyError :: String -> a
1444−emptyError fun = P.error ("Data.Text." ++ fun ++ ": empty input")
1456+emptyError fun = P.error $ "Data.Text." ++ fun ++ ": empty input"
1457+
1458+overflowError :: String -> a
1459+overflowError fun = P.error $ "Data.Text." ++ fun ++ ": size overflow"
Data/Text/Array.hs+4−3
@@ -59,7 +59,7 @@ if (_k_) < 0 || (_k_) >= (_len_) then error ("Data.Text.Array." ++ (_func_) ++ "
5959#if defined(ASSERTS)
6060import Control.Exception (assert)
6161#endif
62−import Data.Bits ((.&.))
62+import Data.Bits ((.&.), xor)
6363import Data.Text.UnsafeShift (shiftL, shiftR)
6464import GHC.Base (ByteArray#, MutableByteArray#, Int(..),
6565 indexWord16Array#, indexWordArray#, newByteArray#,
@@ -103,7 +103,7 @@ instance IArray (MArray s) where
103103-- | Create an uninitialized mutable array.
104104new :: forall s. Int -> ST s (MArray s)
105105new n
106− | len < n = error $ "Data.Text.Array.unsafeNew: invalid length " ++ show n
106+ | n < 0 || n .&. highBit /= 0 = error $ "Data.Text.Array.new: size overflow"
107107 | otherwise = ST $ \s1# ->
108108 case newByteArray# len# s1# of
109109 (# s2#, marr# #) -> (# s2#, MArray marr#
@@ -111,7 +111,8 @@ new n
111111 n
112112#endif
113113 #)
114− where !len@(I# len#) = bytesInArray n
114+ where !(I# len#) = bytesInArray n
115+ highBit = maxBound `xor` (maxBound `shiftR` 1)
115116{-# INLINE new #-}
116117
117118-- | Freeze a mutable array. Do not mutate the 'MArray' afterwards!