]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: don't panic in complex division
authorAlberto Donizetti <alb.donizetti@gmail.com>
Thu, 4 May 2017 09:25:01 +0000 (11:25 +0200)
committerAlberto Donizetti <alb.donizetti@gmail.com>
Thu, 18 May 2017 16:39:05 +0000 (16:39 +0000)
Updates #20227

Change-Id: Idadc3137490181a5d380367660cee21e8313cf3b
Reviewed-on: https://go-review.googlesource.com/42650
Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/const.go
src/go/types/stdlib_test.go
test/fixedbugs/issue20227.go [new file with mode: 0644]

index f9ea92ce502de7383eeb8fd4e31e82150762a940..a465d4a7bb543aa71bb9adde3fcc907bd7139c25 100644 (file)
@@ -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
 
@@ -1591,7 +1589,11 @@ 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
@@ -1599,6 +1601,7 @@ func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
        var cc_plus_dd Mpflt
 
        cc_plus_dd.Set(&rv.Real)
+
        cc_plus_dd.Mul(&rv.Real) // cc
 
        ac.Set(&rv.Imag)
@@ -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
@@ -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)?
index a268d3b3bb586808dff80b28baf8ea043ef4eb08..3f02dd98baf3e4ca5c694aaa895edcd3409e3dac 100644 (file)
@@ -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
        )
 }
 
diff --git a/test/fixedbugs/issue20227.go b/test/fixedbugs/issue20227.go
new file mode 100644 (file)
index 0000000..4448eb5
--- /dev/null
@@ -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"