Skip to content

Commit 2d1829b

Browse files
committed
cmd/compile: don't panic in complex division
Updates #20227 Change-Id: Idadc3137490181a5d380367660cee21e8313cf3b Reviewed-on: https://go-review.googlesource.com/42650 Run-TryBot: Alberto Donizetti <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent c7cae34 commit 2d1829b

File tree

3 files changed

+34
-4
lines changed

3 files changed

+34
-4
lines changed

src/cmd/compile/internal/gc/const.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,15 +1037,13 @@ func evconst(n *Node) {
10371037
cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
10381038

10391039
case ODIV_ | CTCPLX_:
1040-
if rv.U.(*Mpcplx).Real.CmpFloat64(0) == 0 && rv.U.(*Mpcplx).Imag.CmpFloat64(0) == 0 {
1040+
if !cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx)) {
10411041
yyerror("complex division by zero")
10421042
rv.U.(*Mpcplx).Real.SetFloat64(1.0)
10431043
rv.U.(*Mpcplx).Imag.SetFloat64(0.0)
10441044
break
10451045
}
10461046

1047-
cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))
1048-
10491047
case OEQ_ | CTNIL_:
10501048
goto settrue
10511049

@@ -1591,14 +1589,19 @@ func cmplxmpy(v *Mpcplx, rv *Mpcplx) {
15911589

15921590
// complex divide v /= rv
15931591
// (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
1594-
func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
1592+
func cmplxdiv(v *Mpcplx, rv *Mpcplx) bool {
1593+
if rv.Real.CmpFloat64(0) == 0 && rv.Imag.CmpFloat64(0) == 0 {
1594+
return false
1595+
}
1596+
15951597
var ac Mpflt
15961598
var bd Mpflt
15971599
var bc Mpflt
15981600
var ad Mpflt
15991601
var cc_plus_dd Mpflt
16001602

16011603
cc_plus_dd.Set(&rv.Real)
1604+
16021605
cc_plus_dd.Mul(&rv.Real) // cc
16031606

16041607
ac.Set(&rv.Imag)
@@ -1607,6 +1610,14 @@ func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
16071610

16081611
cc_plus_dd.Add(&ac) // cc+dd
16091612

1613+
// We already checked that c and d are not both zero, but we can't
1614+
// assume that c²+d² != 0 follows, because for tiny values of c
1615+
// and/or d c²+d² can underflow to zero. Check that c²+d² is
1616+
// nonzero,return if it's not.
1617+
if cc_plus_dd.CmpFloat64(0) == 0 {
1618+
return false
1619+
}
1620+
16101621
ac.Set(&v.Real)
16111622

16121623
ac.Mul(&rv.Real) // ac
@@ -1632,6 +1643,8 @@ func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
16321643

16331644
v.Imag.Sub(&ad) // bc-ad
16341645
v.Imag.Quo(&cc_plus_dd) // (bc+ad)/(cc+dd)
1646+
1647+
return true
16351648
}
16361649

16371650
// Is n a Go language constant (as opposed to a compile-time constant)?

src/go/types/stdlib_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ func TestStdFixed(t *testing.T) {
171171
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
172172
"issue18882.go", // go/types doesn't check validity of //go:xxx directives
173173
"issue20232.go", // go/types handles larger constants than gc
174+
"issue20227.go", // go/types does not handle this yet
174175
)
175176
}
176177

test/fixedbugs/issue20227.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// errorcheck
2+
3+
// Copyright 2017 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Issue 20227: panic while constructing constant "1i/1e-600000000"
8+
9+
package p
10+
11+
var _ = 1 / 1e-600000000i // ERROR "complex division by zero"
12+
var _ = 1i / 1e-600000000 // ERROR "complex division by zero"
13+
var _ = 1i / 1e-600000000i // ERROR "complex division by zero"
14+
15+
var _ = 1 / (1e-600000000 + 1e-600000000i) // ERROR "complex division by zero"
16+
var _ = 1i / (1e-600000000 + 1e-600000000i) // ERROR "complex division by zero"

0 commit comments

Comments
 (0)