Skip to content

Commit

Permalink
cmd/compile: don't panic in complex division
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
ALTree committed May 18, 2017
1 parent c7cae34 commit 2d1829b
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
21 changes: 17 additions & 4 deletions src/cmd/compile/internal/gc/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -1037,15 +1037,13 @@ func evconst(n *Node) {
cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))

case ODIV_ | CTCPLX_:
if rv.U.(*Mpcplx).Real.CmpFloat64(0) == 0 && rv.U.(*Mpcplx).Imag.CmpFloat64(0) == 0 {
if !cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx)) {
yyerror("complex division by zero")
rv.U.(*Mpcplx).Real.SetFloat64(1.0)
rv.U.(*Mpcplx).Imag.SetFloat64(0.0)
break
}

cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))

case OEQ_ | CTNIL_:
goto settrue

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

// complex divide v /= rv
// (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
func cmplxdiv(v *Mpcplx, rv *Mpcplx) bool {
if rv.Real.CmpFloat64(0) == 0 && rv.Imag.CmpFloat64(0) == 0 {
return false
}

var ac Mpflt
var bd Mpflt
var bc Mpflt
var ad Mpflt
var cc_plus_dd Mpflt

cc_plus_dd.Set(&rv.Real)

cc_plus_dd.Mul(&rv.Real) // cc

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

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

// We already checked that c and d are not both zero, but we can't
// assume that c²+d² != 0 follows, because for tiny values of c
// and/or d c²+d² can underflow to zero. Check that c²+d² is
// nonzero,return if it's not.
if cc_plus_dd.CmpFloat64(0) == 0 {
return false
}

ac.Set(&v.Real)

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

v.Imag.Sub(&ad) // bc-ad
v.Imag.Quo(&cc_plus_dd) // (bc+ad)/(cc+dd)

return true
}

// Is n a Go language constant (as opposed to a compile-time constant)?
Expand Down
1 change: 1 addition & 0 deletions src/go/types/stdlib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ func TestStdFixed(t *testing.T) {
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
"issue18882.go", // go/types doesn't check validity of //go:xxx directives
"issue20232.go", // go/types handles larger constants than gc
"issue20227.go", // go/types does not handle this yet
)
}

Expand Down
16 changes: 16 additions & 0 deletions test/fixedbugs/issue20227.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// errorcheck

// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Issue 20227: panic while constructing constant "1i/1e-600000000"

package p

var _ = 1 / 1e-600000000i // ERROR "complex division by zero"
var _ = 1i / 1e-600000000 // ERROR "complex division by zero"
var _ = 1i / 1e-600000000i // ERROR "complex division by zero"

var _ = 1 / (1e-600000000 + 1e-600000000i) // ERROR "complex division by zero"
var _ = 1i / (1e-600000000 + 1e-600000000i) // ERROR "complex division by zero"

0 comments on commit 2d1829b

Please sign in to comment.