summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorFlorian La Roche <florian.laroche@googlemail.com>2019-01-19 16:14:50 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2019-01-20 19:20:18 +0100
commitfbfaf851902cd9293f392f3a1735e0543016d530 (patch)
tree3af0a2fd574c28337083e5db0971fc4f1defe492 /lib
parentx86: uaccess: Inhibit speculation past access_ok() in user_access_begin() (diff)
downloadlinux-fbfaf851902cd9293f392f3a1735e0543016d530.tar.xz
linux-fbfaf851902cd9293f392f3a1735e0543016d530.zip
fix int_sqrt64() for very large numbers
If an input number x for int_sqrt64() has the highest bit set, then fls64(x) is 64. (1UL << 64) is an overflow and breaks the algorithm. Subtracting 1 is a better guess for the initial value of m anyway and that's what also done in int_sqrt() implicitly [*]. [*] Note how int_sqrt() uses __fls() with two underscores, which already returns the proper raw bit number. In contrast, int_sqrt64() used fls64(), and that returns bit numbers illogically starting at 1, because of error handling for the "no bits set" case. Will points out that he bug probably is due to a copy-and-paste error from the regular int_sqrt() case. Signed-off-by: Florian La Roche <Florian.LaRoche@googlemail.com> Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/int_sqrt.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c
index 14436f4ca6bd..30e0f9770f88 100644
--- a/lib/int_sqrt.c
+++ b/lib/int_sqrt.c
@@ -52,7 +52,7 @@ u32 int_sqrt64(u64 x)
if (x <= ULONG_MAX)
return int_sqrt((unsigned long) x);
- m = 1ULL << (fls64(x) & ~1ULL);
+ m = 1ULL << ((fls64(x) - 1) & ~1ULL);
while (m != 0) {
b = y + m;
y >>= 1;