[GHC] #16294: Code generation corrupts writes to Addr#
GHC
ghc-devs at haskell.org
Wed Feb 6 14:15:57 UTC 2019
#16294: Code generation corrupts writes to Addr#
-------------------------------------+-------------------------------------
Reporter: andrewthad | Owner: (none)
Type: bug | Status: new
Priority: highest | Milestone:
Component: Compiler | Version: 8.6.3
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
This issue affects at least GHC 8.4.4 and GHC 8.6.3. Here is a somewhat
minimal example:
{{{#!hs
{-# language BangPatterns #-}
{-# language MagicHash #-}
{-# language UnboxedTuples #-}
{-# options_ghc -Wall -Werror -O2 #-}
import Data.Primitive
import Data.Void
import Data.Word
import Data.Monoid
import GHC.IO (IO(..))
import Foreign.Storable
import Numeric (showHex)
import qualified GHC.Exts as E
import qualified Data.Primitive as PM
main :: IO ()
main = do
arr <- compute 0xABCD 0x79
putStrLn (showString "raw packet: " . appEndo (foldMap (Endo . showHex)
(E.toList arr)) $ "")
compute :: Word16 -> Word8 -> IO ByteArray
compute totlen prot = do
buf <- PM.newPinnedByteArray 28
PM.setByteArray buf 0 28 (0 :: Word8)
let !(Addr addr) = PM.mutableByteArrayContents buf
!ptr = E.Ptr addr :: E.Ptr Void
pokeByteOff ptr 0 (0x45 :: Word8)
pokeByteOff ptr 1 (0 :: Word8)
pokeByteOff ptr 2 (totlen :: Word16)
pokeByteOff ptr 4 (0 :: Word16)
pokeByteOff ptr 6 (0 :: Word16)
pokeByteOff ptr 8 (0x40 :: Word8)
pokeByteOff ptr 9 (prot :: Word8)
touchMutableByteArray buf
PM.unsafeFreezeByteArray buf
touchMutableByteArray :: MutableByteArray E.RealWorld -> IO ()
touchMutableByteArray (MutableByteArray x) = touchMutableByteArray# x
touchMutableByteArray# :: E.MutableByteArray# E.RealWorld -> IO ()
touchMutableByteArray# x = IO $ \s -> case E.touch# x s of s' -> (# s', ()
#)
}}}
For those curious about the particular interleaving of 8-bit and 16-bit
writes, this was adapted from code that fills out an `iphdr` for use with
raw sockets. The output will be dependent on your platform's endianness.
On my little-endian architecture, I get:
{{{
raw packet: 450cdab00004079000000000000000000
}}}
As we expect, the `abcd` from the source gets flipped to `cdab` because of
the little endian architecture this ran on. However, it starts in an
unusual place. It's not even byte-aligned. Something, possible a cmm
optimization or a codegen optimization, makes the `writeWord16OffAddr#`
end up straddling three bytes.
Someone will probably want to write a more minimal example that eliminates
the use of the `primitive` library.
Sorry to be the bearer of bad news :(
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/16294>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list