c2hs fails to produce the correct alignment
- Dominant language
- Haskell
- Stars
- 211
- Forks
- 52
- PR merge metrics
- No merged PRs in 30d
Description
I am producing bindings for `libsodium`, and especially the [following struct](https://github.com/jedisct1/libsodium/blob/07c2f6c053dd2aed1716444d667dcc781f14739c/src/libsodium/include/sodium/crypto_generichash_blake2b.h#L25):
```c
#ifndef CRYPTO_ALIGN
# if defined(__INTEL_COMPILER) || defined(_MSC_VER)
# define CRYPTO_ALIGN(x) __declspec(align(x))
# else
# define CRYPTO_ALIGN(x) __attribute__ ((aligned(x)))
# endif
#endif
typedef struct CRYPTO_ALIGN(64) crypto_generichash_blake2b_state {
unsigned char opaque[384];
} crypto_generichash_blake2b_state;
```
Here is my Types.chs file:
Types.chs
```
module Cryptography.LibSodium.Hash.Types
( Blake2bState(..)
) where
import Data.Array.Storable (StorableArray, withStorableArray)
import Data.Array.MArray (newListArray)
import Foreign (Storable(..))
import Foreign.Ptr (Ptr, castPtr, plusPtr)
import Data.Word (Word8)
import Foreign.C.Types (CSize, CUChar (..))
import Data.Foldable (traverse_)
import Cryptography.LibSodium.Orphans ()
#include "sodium.h"
-- | Wrapper holding the state for the Blake2b hashing algorithm.
--
-- C counterpart:
--
-- > typedef struct CRYPTO_ALIGN(64) crypto_generichash_blake2b_state {
-- > unsigned char opaque[384];
-- > } crypto_generichash_blake2b_state;
--
-- @since 0.0.1.0
newtype Blake2bState = Blake2bState { getBlake2bState :: StorableArray CSize CUChar}
-- @since 0.0.1.0
instance Storable Blake2bState where
sizeOf _ = {#sizeof crypto_generichash_blake2b_state #}
alignment _ = {#alignof crypto_generichash_blake2b_state #}
peek :: Ptr Blake2bState -> IO Blake2bState
peek p = Blake2bState <$> ({#get crypto_generichash_blake2b_state.opaque #} p)
-- Previous implementation, kept for comparison
-- peek ptr = do
-- let bytePtr :: Ptr Word8 = castPtr ptr
-- xs <- traverse (\i -> peek (plusPtr bytePtr i)) [0..383]
-- Blake2bState <$> newListArray (0, 383) xs
poke :: Ptr Blake2bState -> Blake2bState -> IO ()
poke ptr (Blake2bState arr) = withStorableArray arr (go bytePtr)
where
bytePtr :: Ptr CUChar
bytePtr = castPtr ptr
go :: Ptr CUChar -> Ptr CUChar -> IO ()
go outPtr arrPtr = traverse_
(\i -> peek @CUChar (plusPtr arrPtr i) >>= poke (plusPtr outPtr i)) [0..383]
{#pointer *crypto_generichash_blake2b_state as Blake2bStatePtr -> Blake2bState#}
```
And here is the generated Haskell code
Types.hs
```haskell
-- GENERATED by C->Haskell Compiler, version 0.28.8 Switcheroo, 25 November 2017 (Haskell)
-- Edit the ORIGNAL .chs file instead!
{-# LINE 1 "src/Cryptography/LibSodium/Hash/Types.chs" #-}
module Cryptography.LibSodium.Hash.Types
( Blake2bState(..)
) where
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Ptr as C2HSImp
import Data.Array.Storable (StorableArray, withStorableArray)
import Data.Array.MArray (newListArray)
import Foreign (Storable(..))
import Foreign.Ptr (Ptr, castPtr, plusPtr)
import Data.Word (Word8)
import Foreign.C.Types (CSize, CUChar (..))
import Data.Foldable (traverse_)
import Cryptography.LibSodium.Orphans ()
-- | Wrapper holding the state for the Blake2b hashing algorithm.
--
-- C counterpart:
--
-- > typedef struct CRYPTO_ALIGN(64) crypto_generichash_blake2b_state {
-- > unsigned char opaque[384];
-- > } crypto_generichash_blake2b_state;
--
-- @since 0.0.1.0
newtype Blake2bState = Blake2bState { getBlake2bState :: StorableArray CSize CUChar}
-- @since 0.0.1.0
instance Storable Blake2bState where
sizeOf _ = 384
{-# LINE 29 "src/Cryptography/LibSodium/Hash/Types.chs" #-}
alignment _ = 1
{-# LINE 31 "src/Cryptography/LibSodium/Hash/Types.chs" #-}
peek :: Ptr Blake2bState -> IO Blake2bState
peek p = Blake2bState <$> ((\ptr -> do {return $ ptr `C2HSImp.plusPtr` 0 :: IO (C2HSImp.Ptr C2HSImp.CUChar)}) p)
-- Previous implementation, kept for comparison
-- peek ptr = do
-- let bytePtr :: Ptr Word8 = castPtr ptr
-- xs <- traverse (\i -> peek (plusPtr bytePtr i)) [0..383]
-- Blake2bState <$> newListArray (0, 383) xs
poke :: Ptr Blake2bState -> Blake2bState -> IO ()
poke ptr (Blake2bState arr) = withStorableArray arr (go bytePtr)
where
bytePtr :: Ptr CUChar
bytePtr = castPtr ptr
go :: Ptr CUChar -> Ptr CUChar -> IO ()
go outPtr arrPtr = traverse_
(\i -> peek @CUChar (plusPtr arrPtr i) >>= poke (plusPtr outPtr i)) [0..383]
type Blake2bStatePtr = C2HSImp.Ptr (Blake2bState)
{-# LINE 50 "src/Cryptography/LibSodium/Hash/Types.chs" #-}
```
As you can see, the alignment in the `Storable` instance is `1` instead of `64`. Could this be caused by the use of a macro or is this a red herring?
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.