Commit 7ad27481 authored by Rémy Oudompheng's avatar Rémy Oudompheng Committed by Robert Griesemer

math/big: fix out-of-bounds panic in divRecursive

The bounds in the last carry branch were wrong as there
is no reason for len(u) >= n+n/2 to always hold true.

We also adjust test to avoid using a remainder of 1
(in which case, the last step of the algorithm computes
(qhatv+1) - qhatv which rarely produces a carry).

Change-Id: I69fbab9c5e19d0db1c087fbfcd5b89352c2d26fb
Reviewed-on: https://go-review.googlesource.com/c/go/+/206839
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRobert Griesemer <gri@golang.org>
parent e762378c
...@@ -941,7 +941,7 @@ func (z nat) divRecursiveStep(u, v nat, depth int, tmp *nat, temps []*nat) { ...@@ -941,7 +941,7 @@ func (z nat) divRecursiveStep(u, v nat, depth int, tmp *nat, temps []*nat) {
} }
c := subVV(u[0:len(qhatv)], u[0:len(qhatv)], qhatv) c := subVV(u[0:len(qhatv)], u[0:len(qhatv)], qhatv)
if c > 0 { if c > 0 {
c = subVW(u[len(qhatv):B+n], u[len(qhatv):B+n], c) c = subVW(u[len(qhatv):], u[len(qhatv):], c)
} }
if c > 0 { if c > 0 {
panic("impossible") panic("impossible")
......
...@@ -765,16 +765,23 @@ func TestNatDiv(t *testing.T) { ...@@ -765,16 +765,23 @@ func TestNatDiv(t *testing.T) {
if len(b) == 1 && b[0] == 1 { if len(b) == 1 && b[0] == 1 {
b[0] = 2 b[0] = 2
} }
// choose a remainder c < b
c := rndNat1(len(b))
if len(c) == len(b) && c[len(c)-1] >= b[len(b)-1] {
c[len(c)-1] = 0
c = c.norm()
}
// compute x = a*b+c
x := nat(nil).mul(a, b) x := nat(nil).mul(a, b)
addVW(x, x, 1) x = x.add(x, c)
var q, r nat var q, r nat
q, r = q.div(r, x, b) q, r = q.div(r, x, b)
if q.cmp(a) != 0 { if q.cmp(a) != 0 {
t.Fatalf("wrong quotient: got %s; want %s for %s/%s", q.utoa(10), a.utoa(10), x.utoa(10), b.utoa(10)) t.Fatalf("wrong quotient: got %s; want %s for %s/%s", q.utoa(10), a.utoa(10), x.utoa(10), b.utoa(10))
} }
if len(r) != 1 || r[0] != 1 { if r.cmp(c) != 0 {
t.Fatalf("wrong remainder: got %s; want 1 for %s/%s", r.utoa(10), x.utoa(10), b.utoa(10)) t.Fatalf("wrong remainder: got %s; want %s for %s/%s", r.utoa(10), c.utoa(10), x.utoa(10), b.utoa(10))
} }
} }
} }
......
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