Incorrect handling of Bool return value in FFI
Summary
When declaring a foreign C function with return type Bool
or IO Bool
, the output might be improperly read as True
instead of False
. The problem is fixed when using CBool
from Foreign.C.Types
, so please excuse me if I've just misunderstood what the FFI does in this case :-)
I've attached a set of files that reproduce a problem I encountered with a small Makefile
, here is the C and Haskell code reproduced for better understanding:
int64_t foo(void)
{
return -1LL;
}
bool test(void)
{
return foo() > 0LL;
}
int main(void)
{
printf("%d\n", test());
}
module Main(main) where
foreign import ccall "test"
test :: IO Bool
main :: IO ()
main =
print =<< test
The expected result to the call to test
is false
and it is indeed what is reported by the C main. However, on my machine (Linux Fedora, x86_64) the Haskell main prints True
. After some investigation with gdb
, I suspect this is due to the content of the %rax
register being 0xff...ff00
after the call to test
(i.e. the result is only stored on the last byte), which could be misinterpreted as True
on the Haskell side?
Steps to reproduce
make Main-hs
make Main-C
-
./Main-hs
printsTrue
-
./Main-C
prints0
Expected behavior
./Main-hs
prints False
Environment
- GHC version used: tested on 8.10.7 and 9.2.5
Optional:
- Operating System: Fedora 37
- System Architecture: x86_64
- GCC: 12.2.1, using
-O3