fat_init violates host ABI on Win64
Nicolas Hake
nh at nosebud.de
Tue Apr 4 13:28:11 UTC 2017
Dear GMP maintainers,
the Windows x64 ABI requires callers to allocate a 32 byte "parameter
area" before calling into a function, which the callee is allowed to use
as it pleases[1]. fat_init does not do this before calling
__gmpn_cpuvec_init, thus violating the ABI.
This is not usually an issue, since neither gcc nor clang seem to use
the space. MSVC, however, does, which results in rax/rcx/r8/r9
incorrectly being restored to clobbered values, and, in turn, random
crashes as fat_init jumps into the real routines with incorrect arguments.
I'm not sure whether MSVC is a supported compiler (I assume it isn't,
because --enable-fat requires support for variable-length arrays, which
MSVC will not compile in C mode), but it's possible that other compilers
may also use the parameter area as a scratch space, or even that
gcc/clang start using it in future releases.
Attached patch solves this problem by just allocating 32 bytes of stack
space before calling __gmpn_cpuvec_init, and discarding them afterwards.
Thanks,
Nicolas
[1] "Even if the called function has fewer than 4 parameters, these 4
stack locations ... may be used by the called function for other
purposes ..." https://msdn.microsoft.com/en-us/library/ew5tede7.aspx
-------------- next part --------------
--- a/mpn/x86_64/fat/fat_entry.asm
+++ b/mpn/x86_64/fat/fat_entry.asm
@@ -167,7 +167,13 @@
push %r8
push %r9
push %rax
+ifdef(`HOST_DOS64',`dnl
+ subq $32, %rsp
+')
CALL( __gmpn_cpuvec_init)
+ifdef(`HOST_DOS64',`dnl
+ addq $32, %rsp
+')
pop %rax
pop %r9
pop %r8
More information about the gmp-bugs
mailing list