]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: don't panic in complex division
authorAlberto Donizetti <alb.donizetti@gmail.com>
Sat, 13 May 2017 17:11:44 +0000 (19:11 +0200)
committerAlberto Donizetti <alb.donizetti@gmail.com>
Mon, 5 Jun 2017 20:24:51 +0000 (20:24 +0000)
Make sure that in complex division we reject divisors that would
underflow to zero when using the textbook complex-division method we
currently use.

This change does for go/types what golang.org/cl/42650 did for gc.

Fixes #20227

Change-Id: Iaa784ac5e60141f51c501eb0e3ce0e9c1c2993d0
Reviewed-on: https://go-review.googlesource.com/44590
Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/expr.go
src/go/types/stdlib_test.go

index 7de13f5be6f00bc117c0eede133ad97bc7c716d6..7f54b0907192419f577c2b861fd3a0a798e36577 100644 (file)
@@ -800,10 +800,24 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
                return
        }
 
-       if (op == token.QUO || op == token.REM) && (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 {
-               check.invalidOp(y.pos(), "division by zero")
-               x.mode = invalid
-               return
+       if op == token.QUO || op == token.REM {
+               // check for zero divisor
+               if (x.mode == constant_ || isInteger(x.typ)) && y.mode == constant_ && constant.Sign(y.val) == 0 {
+                       check.invalidOp(y.pos(), "division by zero")
+                       x.mode = invalid
+                       return
+               }
+
+               // check for divisor underflow in complex division (see issue 20227)
+               if x.mode == constant_ && y.mode == constant_ && isComplex(x.typ) {
+                       re, im := constant.Real(y.val), constant.Imag(y.val)
+                       re2, im2 := constant.BinaryOp(re, token.MUL, re), constant.BinaryOp(im, token.MUL, im)
+                       if constant.Sign(re2) == 0 && constant.Sign(im2) == 0 {
+                               check.invalidOp(y.pos(), "division by zero")
+                               x.mode = invalid
+                               return
+                       }
+               }
        }
 
        if x.mode == constant_ && y.mode == constant_ {
index b9a6681e66aae11f65a33b73b10972f6fe4d7b9c..345c7897f36b3426a811a80e2fa9ee5941b23540 100644 (file)
@@ -171,7 +171,6 @@ 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
                "issue20529.go", // go/types does not have constraints on stack size
        )
 }