summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2016-12-15 17:47:08 -0500
committerBen Gamari <ben@smart-cactus.org>2016-12-15 18:49:38 -0500
commitcd4b202f24da928adf66c05443b457002ab6a3e1 (patch)
tree4cf4eaeec9aa9bac18cfa87037257745eee7cfbf
parent81c49562570a403e8470f73f4decd3e0cb891983 (diff)
downloadhaskell-cd4b202f24da928adf66c05443b457002ab6a3e1.tar.gz
array: Check for integer overflow during allocation
This fixes #229, where creating a new array can cause array to allocate a smaller array than it thinks it allocates due to integer overflow, resulting in memory unsafety. This breaks the rts/overflow1 test, which relied on this unchecked overflow. I fix it by reimplementing the test in terms of newByteArray# directly. Updates the array submodule.
m---------libraries/array0
-rw-r--r--testsuite/tests/rts/overflow1.hs20
2 files changed, 15 insertions, 5 deletions
diff --git a/libraries/array b/libraries/array
-Subproject bab2c234f176fe3e95443cbe4387833da22f7e5
+Subproject b8a8d09ddc20a9c9d99bd03b136718b543edb87
diff --git a/testsuite/tests/rts/overflow1.hs b/testsuite/tests/rts/overflow1.hs
index 63ed5a4e02..74a396bc53 100644
--- a/testsuite/tests/rts/overflow1.hs
+++ b/testsuite/tests/rts/overflow1.hs
@@ -1,11 +1,21 @@
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE UnboxedTuples #-}
+
module Main where
-import Data.Array.IO
-import Data.Word
+import GHC.Exts
+import GHC.Base
-- Try to overflow BLOCK_ROUND_UP in the computation of req_blocks in allocate()
--- Here we invoke allocate() via newByteArray# and the array package.
+-- Here we invoke allocate() via newByteArray#.
-- Request a number of bytes close to HS_WORD_MAX,
-- subtracting a few words for overhead in newByteArray#.
--- Allocate Word32s (rather than Word8s) to get around bounds-checking in array.
-main = newArray (0,maxBound `div` 4 - 10) 0 :: IO (IOUArray Word Word32)
+main :: IO ()
+main =
+ IO $ \s1# ->
+ case newByteArray# (maxInt# -# 10#) s1# of
+ (# s2#, _ #) -> (# s2#, () #)
+ where
+ maxInt# :: Int#
+ !(I# maxInt#) = maxBound