From: Russ Cox Date: Mon, 29 Jun 2015 03:25:38 +0000 (-0400) Subject: cmd/compile: reject large floating point exponents without math/big X-Git-Tag: go1.5beta1~44 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=1122836b5f07bc9d76ec8667bab34f97e48a75e5;p=gostls13.git 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 --- diff --git a/src/cmd/compile/internal/gc/mparith3.go b/src/cmd/compile/internal/gc/mparith3.go index bda35bc192..bf37f2d607 100644 --- a/src/cmd/compile/internal/gc/mparith3.go +++ b/src/cmd/compile/internal/gc/mparith3.go @@ -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 } } diff --git a/src/go/types/stdlib_test.go b/src/go/types/stdlib_test.go index c7fe8dfeae..2014e98467 100644 --- a/src/go/types/stdlib_test.go +++ b/src/go/types/stdlib_test.go @@ -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 index 0000000000..fd1fab338a --- /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 0000000000..00effbcbb9 --- /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) + } + } +}