]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: reject large floating point exponents without math/big
authorRuss Cox <rsc@golang.org>
Mon, 29 Jun 2015 03:25:38 +0000 (23:25 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 29 Jun 2015 21:18:01 +0000 (21:18 +0000)
For #11326 (but not a fix).

Change-Id: Ic51814f5cd7357427c3fd990a5522775d05e7987
Reviewed-on: https://go-review.googlesource.com/11673
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/mparith3.go
src/go/types/stdlib_test.go
test/fixedbugs/issue11326.go [new file with mode: 0644]
test/fixedbugs/issue11326b.go [new file with mode: 0644]

index bda35bc19230d75884ba2277725dd5840bc184a8..bf37f2d60786c4affce2dbb22975f09f3d648a89 100644 (file)
@@ -9,6 +9,7 @@ import (
        "cmd/internal/obj"
        "fmt"
        "math"
+       "strings"
 )
 
 /// implements float arihmetic
@@ -153,6 +154,30 @@ func mpatoflt(a *Mpflt, as string) {
                as = as[1:]
        }
 
+       // The spec requires accepting exponents that fit in int32.
+       // Don't accept much more than that.
+       // Count digits in exponent and stop early if there are too many.
+       if i := strings.Index(as, "e"); i >= 0 {
+               i++
+               if i < len(as) && (as[i] == '-' || as[i] == '+') {
+                       i++
+               }
+               for i < len(as) && as[i] == '0' {
+                       i++
+               }
+               // TODO(rsc): This should be > 10, because we're supposed
+               // to accept any signed 32-bit int as an exponent.
+               // But that's not working terribly well, so we deviate from the
+               // spec in order to make sure that what we accept works.
+               // We can remove this restriction once those larger exponents work.
+               // See golang.org/issue/11326 and test/fixedbugs/issue11326*.go.
+               if len(as)-i > 8 {
+                       Yyerror("malformed constant: %s (exponent too large)", as)
+                       a.Val.SetUint64(0)
+                       return
+               }
+       }
+
        f, ok := a.Val.SetString(as)
        if !ok {
                // At the moment we lose precise error cause;
@@ -164,11 +189,13 @@ func mpatoflt(a *Mpflt, as string) {
                // TODO(gri) use different conversion function or check separately
                Yyerror("malformed constant: %s", as)
                a.Val.SetUint64(0)
+               return
        }
 
        if f.IsInf() {
                Yyerror("constant too large: %s", as)
                a.Val.SetUint64(0)
+               return
        }
 }
 
index c7fe8dfeae1074d25850071285ad8a9a5cceaa06..2014e98467a09dad3b9a3e742c9599a97cf08731 100644 (file)
@@ -144,10 +144,12 @@ func TestStdFixed(t *testing.T) {
 
        testTestDir(t, filepath.Join(runtime.GOROOT(), "test", "fixedbugs"),
                "bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
-               "bug459.go",    // possibly incorrect test - see issue 6703 (pending spec clarification)
-               "issue3924.go", // possibly incorrect test - see issue 6671 (pending spec clarification)
-               "issue6889.go", // gc-specific test
-               "issue7746.go", // large constants - consumes too much memory
+               "bug459.go",      // possibly incorrect test - see issue 6703 (pending spec clarification)
+               "issue3924.go",   // possibly incorrect test - see issue 6671 (pending spec clarification)
+               "issue6889.go",   // gc-specific test
+               "issue7746.go",   // large constants - consumes too much memory
+               "issue11326.go",  // large constants
+               "issue11326b.go", // large constants
        )
 }
 
diff --git a/test/fixedbugs/issue11326.go b/test/fixedbugs/issue11326.go
new file mode 100644 (file)
index 0000000..fd1fab3
--- /dev/null
@@ -0,0 +1,28 @@
+// errorcheck
+
+// Copyright 2015 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.
+
+package main
+
+import "fmt"
+
+func main() {
+       var g = 1e81391777742999 // ERROR "exponent too large"
+       // The next should only cause a problem when converted to float64
+       // by the assignment, but instead the compiler rejects it outright,
+       // rather than mishandle it. Specifically, when handled, 'var h' prints:
+       //      issue11326.go:N: constant 0.93342e+536870911 overflows float64
+       // The rejection of 'var i' is just insurance. It seems to work correctly.
+       // See golang.org/issue/11326.
+       // var h = 1e2147483647     // should be "1.00000e+2147483647 overflows float64"
+       var h = 1e2147483647 // ERROR "exponent too large"
+       // var i = 1e214748364  // should be "1.00000e\+214748364 overflows float64"
+       var i = 1e214748364 // ERROR "exponent too large"
+       var j = 1e21474836  // ERROR "1.00000e\+21474836 overflows float64"
+       var k = 1e2147483   // ERROR "1.00000e\+2147483 overflows float64"
+       var l = 1e214748    // ERROR "1.00000e\+214748 overflows float64"
+       var m = 1e21474     // ERROR "1.00000e\+21474 overflows float64"
+       fmt.Println(g)
+}
diff --git a/test/fixedbugs/issue11326b.go b/test/fixedbugs/issue11326b.go
new file mode 100644 (file)
index 0000000..00effbc
--- /dev/null
@@ -0,0 +1,44 @@
+// run
+
+// Copyright 2015 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.
+
+package main
+
+func main() {
+       /* TODO(rsc): Should work but does not. See golang.org/issue/11326.
+       {
+               const n = 1e2147483647
+               const d = 1e2147483646
+               x := n / d
+               if x != 10.0 {
+                       println("incorrect value:", x)
+               }
+       }
+       {
+               const n = 1e214748364
+               const d = 1e214748363
+               x := n / d
+               if x != 10.0 {
+                       println("incorrect value:", x)
+               }
+       }
+       */
+       {
+               const n = 1e21474836
+               const d = 1e21474835
+               x := n / d
+               if x != 10.0 {
+                       println("incorrect value:", x)
+               }
+       }
+       {
+               const n = 1e2147483
+               const d = 1e2147482
+               x := n / d
+               if x != 10.0 {
+                       println("incorrect value:", x)
+               }
+       }
+}