Commit 4d3727e9 authored by Jakob Kummerow's avatar Jakob Kummerow Committed by Commit Bot

[bigint][ubsan] Fix UB in digit_div fallback path

See: https://trac.webkit.org/changeset/232253/webkit

This is a defensive fix insofar as we were not observing any
issues, hence there is no regression test either.

Bug: v8:6791, v8:3770
Change-Id: Icdabe6a26aca9a5913fba278ae1fd0a79857dfd9
Reviewed-on: https://chromium-review.googlesource.com/1077660Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53651}
parent 470dfa9f
......@@ -2395,16 +2395,20 @@ BigInt::digit_t MutableBigInt::digit_div(digit_t high, digit_t low,
static const digit_t kHalfDigitBase = 1ull << kHalfDigitBits;
// Adapted from Warren, Hacker's Delight, p. 152.
int s = base::bits::CountLeadingZeros(divisor);
DCHECK_NE(s, kDigitBits); // {divisor} is not 0.
divisor <<= s;
digit_t vn1 = divisor >> kHalfDigitBits;
digit_t vn0 = divisor & kHalfDigitMask;
// {s} can be 0. "low >> kDigitBits == low" on x86, so we "&" it with
// {s} can be 0. {low >> kDigitBits} would be undefined behavior, so
// we mask the shift amount with {kShiftMask}, and the result with
// {s_zero_mask} which is 0 if s == 0 and all 1-bits otherwise.
STATIC_ASSERT(sizeof(intptr_t) == sizeof(digit_t));
const int kShiftMask = kDigitBits - 1;
digit_t s_zero_mask =
static_cast<digit_t>(static_cast<intptr_t>(-s) >> (kDigitBits - 1));
digit_t un32 = (high << s) | ((low >> (kDigitBits - s)) & s_zero_mask);
digit_t un32 =
(high << s) | ((low >> ((kDigitBits - s) & kShiftMask)) & s_zero_mask);
digit_t un10 = low << s;
digit_t un1 = un10 >> kHalfDigitBits;
digit_t un0 = un10 & kHalfDigitMask;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment