Skip to content

Commit 7841b58

Browse files
authored
Merge pull request #551 from IntersectMBO/jdral/issue-549
Fix out-of-bounds array access in `hFlipBit`.
2 parents 5ea9cdb + 02e7aa7 commit 7841b58

File tree

2 files changed

+15
-4
lines changed

2 files changed

+15
-4
lines changed

test/Test/FS.hs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,19 @@ createFile hfs p = withFile hfs p (WriteMode MustBeNew) $ \_ -> pure ()
124124
data WithBitOffset a = WithBitOffset Int a
125125
deriving stock Show
126126

127+
bitLength :: BS.ByteString -> Int
128+
bitLength bs = BS.length bs * 8
129+
127130
instance Arbitrary (WithBitOffset ByteString) where
128131
arbitrary = do
129132
bs <- arbitrary `suchThat` (\bs -> BS.length bs > 0)
130-
bitOffset <- chooseInt (0, BS.length bs - 1)
133+
bitOffset <- chooseInt (0, bitLength bs - 1)
131134
pure $ WithBitOffset bitOffset bs
132135
shrink (WithBitOffset bitOffset bs) =
133136
[ WithBitOffset bitOffset' bs'
134137
| bs' <- shrink bs
135138
, BS.length bs' > 0
136-
, let bitOffset' = max 0 $ min (BS.length bs' - 1) bitOffset
139+
, let bitOffset' = max 0 $ min (bitLength bs' - 1) bitOffset
137140
] ++ [
138141
WithBitOffset bitOffset' bs
139142
| bitOffset' <- max 0 <$> shrink bitOffset

test/Test/Util/FS.hs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,23 +360,31 @@ hFlipBit ::
360360
-> Int -- ^ Bit offset
361361
-> m ()
362362
hFlipBit hfs h bitOffset = do
363+
-- Check that the bit offset is within the file
364+
fileSize <- hGetSize hfs h
365+
let fileSizeBits = 8 * fileSize
366+
assert (bitOffset >= 0) $ pure ()
367+
assert (bitOffset < fromIntegral fileSizeBits) $ pure ()
363368
-- Create an empty buffer initialised to all 0 bits. The buffer must have at
364369
-- least the size of a machine word.
365370
let n = sizeOf (0 :: Word)
366371
buf <- newPinnedByteArray n
367-
setByteArray buf 0 n (0 :: Word)
372+
setByteArray buf 0 1 (0 :: Word)
368373
-- Read the bit at the given offset
369374
let (byteOffset, i) = bitOffset `quotRem` 8
370375
bufOff = BufferOffset 0
371376
count = 1
372377
off = AbsOffset (fromIntegral byteOffset)
378+
-- Check that the byte offset is within the file
379+
assert (byteOffset >= 0) $ pure ()
380+
assert (byteOffset < fromIntegral fileSize) $ pure ()
381+
assert (i >= 0 && i < 8) $ pure ()
373382
void $ hGetBufExactlyAt hfs h buf bufOff count off
374383
-- Flip the bit in memory, and then write it back
375384
let bvec = BitMVec 0 8 buf
376385
flipBit bvec i
377386
void $ hPutBufExactlyAt hfs h buf bufOff count off
378387

379-
380388
{-------------------------------------------------------------------------------
381389
Errors
382390
-------------------------------------------------------------------------------}

0 commit comments

Comments
 (0)