cmd/compile: reject large floating point exponents without math/big
For #11326 (but not a fix).
Change-Id: Ic51814f5cd7357427c3fd990a5522775d05e7987
Reviewed-on: https://go-review.googlesource.com/11673
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/src/cmd/compile/internal/gc/mparith3.go b/src/cmd/compile/internal/gc/mparith3.go
index bda35bc..bf37f2d 100644
--- a/src/cmd/compile/internal/gc/mparith3.go
+++ b/src/cmd/compile/internal/gc/mparith3.go
@@ -9,6 +9,7 @@
"cmd/internal/obj"
"fmt"
"math"
+ "strings"
)
/// implements float arihmetic
@@ -153,6 +154,30 @@
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 @@
// 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
}
}
diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go
index c7fe8df..2014e98 100644
--- a/src/go/types/stdlib_test.go
+++ b/src/go/types/stdlib_test.go
@@ -144,10 +144,12 @@
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
index 0000000..fd1fab3
--- /dev/null
+++ b/test/fixedbugs/issue11326.go
@@ -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
index 0000000..00effbc
--- /dev/null
+++ b/test/fixedbugs/issue11326b.go
@@ -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)
+ }
+ }
+}