Stack overflow on 64-bit modulus operations on 32-bit architectures.

Running 'zpool create' on a 32-bit machine with an SPL compiled with
gcc 4.4.4 led to a stack overlow.  This turned out to be due to some
sort of 'optimization' by gcc:

uint64_t __umoddi3(uint64_t dividend, uint64_t divisor)
{
   return dividend - divisor * (dividend / divisor);
}

This code was supposed to be using __udivdi3 to implement /, but gcc
instead implemented it via __umoddi3 itself.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
Alex Zhuravlev 2010-06-02 22:01:14 -07:00 committed by Brian Behlendorf
parent 8a1c9a02fb
commit 1b4ad25e2f

View File

@ -96,7 +96,8 @@ EXPORT_SYMBOL(highbit);
* Implementation of 64 bit division for 32-bit machines. * Implementation of 64 bit division for 32-bit machines.
*/ */
#if BITS_PER_LONG == 32 #if BITS_PER_LONG == 32
uint64_t __udivdi3(uint64_t dividend, uint64_t divisor) uint64_t
__udivdi3(uint64_t dividend, uint64_t divisor)
{ {
#if defined(HAVE_DIV64_64) /* 2.6.22 - 2.6.25 API */ #if defined(HAVE_DIV64_64) /* 2.6.22 - 2.6.25 API */
return div64_64(dividend, divisor); return div64_64(dividend, divisor);
@ -125,9 +126,10 @@ EXPORT_SYMBOL(__udivdi3);
/* /*
* Implementation of 64 bit modulo for 32-bit machines. * Implementation of 64 bit modulo for 32-bit machines.
*/ */
uint64_t __umoddi3(uint64_t dividend, uint64_t divisor) uint64_t
__umoddi3(uint64_t dividend, uint64_t divisor)
{ {
return dividend - divisor * (dividend / divisor); return (dividend - (divisor * __udivdi3(dividend, divisor)));
} }
EXPORT_SYMBOL(__umoddi3); EXPORT_SYMBOL(__umoddi3);
#endif /* BITS_PER_LONG */ #endif /* BITS_PER_LONG */