]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Stack overflow on 64-bit modulus operations on 32-bit architectures.
authorAlex Zhuravlev <Alex.Zhuravlev@Sun.COM>
Thu, 3 Jun 2010 05:01:14 +0000 (22:01 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 3 Jun 2010 16:06:55 +0000 (09:06 -0700)
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>
module/spl/spl-generic.c

index 29b698889e36be6cf169cf9fc44cf9272e5f38ce..9916051de0fc28c31446d063c5e7a04ee2fa86cc 100644 (file)
@@ -96,7 +96,8 @@ EXPORT_SYMBOL(highbit);
  * Implementation of 64 bit division for 32-bit machines.
  */
 #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 */
        return div64_64(dividend, divisor);
@@ -125,9 +126,10 @@ EXPORT_SYMBOL(__udivdi3);
 /*
  * 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);
 #endif /* BITS_PER_LONG */