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-hsmake Main-C-
./Main-hsprintsTrue -
./Main-Cprints0
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