"static_wrapper" imports in the FFI

Iavor Diatchki iavor.diatchki at gmail.com
Mon Mar 15 12:48:02 EDT 2010


Hello,
I have implemented a small extension to the FFI which allows for
"static_wrapper" imports.  These are a variation on "wrapper" imports
that do not use run-time code generation.  This is important in
security sensitive contexts because it avoids executable data.  While
"static_wrapper" imports are less general then "wrapper" imports, they
can be used to install Haskell handlers in many C libraries where
callbacks have an extra "user-data" parameter (e.g., GTK signal
handlers).

I have a darcs patch implementing the feature but I could not send it
to the list because for some reason the patch is 150K long (!!!  my
changes are only ~50 lines) and the list has a 40K limit.  What is the
correct way to submit the patch, should I just commit it to the GHC
tree?


Here is an example, illustrating how "static_wrapper" imports work:

foreign import ccall "static_wrapper"
 runHandler :: Int -> IO Bool

This declaration will generate a C function that can call Haskell
functions of the specified type.  More concretely, the generated
function has the following signature:

HsBool runHandler(HsInt argument, HsStablePointer haskell_function);

(i.e., given an integer and a pointer to a haskell closure of the
correct type, we return a boolean computed by executing the closure).
A common use case would be to install "runHandler" as the call-back in
the C library, and pass the Haskell closure as the user-specified
argument.

By default, the closure argument is the last argument in the C
function but, if necessary, this can be changed by using a type
variable to indicate the position of the closure argument.  For
example, another way to write the previous example is:

foreign import ccall "static_wrapper"
 runHandler :: Int -> closure -> IO Bool

If in some C library the user-specified data is the second argument,
then this is how we'd write the declaration:

foreign import ccall "static_wrapper"
 runAnotherHandler :: Char -> closure -> Int -> IO Bool


In addition to generating the C function, a "static_wrapper"
declaration also imports the C function's address into Haskell, as if
the programmer had written an import like this:

-- First example
foreign import ccall "&runHandler"
 runHandler :: FunPtr (Int -> StablePtr (Int -> IO Bool) -> IO Bool)

-- Second example
foreign import ccall "&runAnotherHandler"
 runAnotherHandler :: FunPtr (Int -> StablePtr (Int -> Char -> IO
Bool) -> Char -> IO Bool)

This address can be passed to the C library when installing the handler.

I hope that you find this features useful!  As usual, comments and
feedback are most welcome.
-Iavor


More information about the Glasgow-haskell-users mailing list