]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile, runtime: fix pedantic int->string conversions
authorMatthew Dempsky <mdempsky@google.com>
Thu, 31 Mar 2016 09:04:12 +0000 (02:04 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 31 Mar 2016 10:28:23 +0000 (10:28 +0000)
Previously, cmd/compile rejected constant int->string conversions if
the integer value did not fit into an "int" value. Also, runtime
incorrectly truncated 64-bit values to 32-bit before checking if
they're a valid Unicode code point. According to the Go spec, both of
these cases should instead yield "\uFFFD".

Fixes #15039.

Change-Id: I3c8a3ad9a0780c0a8dc1911386a523800fec9764
Reviewed-on: https://go-review.googlesource.com/21344
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/cmd/compile/internal/gc/const.go
src/runtime/string.go
test/fixedbugs/issue15039.go [new file with mode: 0644]

index af75580cbbefffd3cd93a12641067e13ebb5045e..49c2a8f41c7b2f672c980d30ca6f5f15e7e12c56 100644 (file)
@@ -468,12 +468,12 @@ func overflow(v Val, t *Type) {
 func tostr(v Val) Val {
        switch v.Ctype() {
        case CTINT, CTRUNE:
-               if v.U.(*Mpint).Cmp(Minintval[TINT]) < 0 || v.U.(*Mpint).Cmp(Maxintval[TINT]) > 0 {
-                       Yyerror("overflow in int -> string")
+               var i int64 = 0xFFFD
+               if u := v.U.(*Mpint); u.Cmp(Minintval[TUINT32]) >= 0 && u.Cmp(Maxintval[TUINT32]) <= 0 {
+                       i = u.Int64()
                }
-               r := uint(v.U.(*Mpint).Int64())
                v = Val{}
-               v.U = string(r)
+               v.U = string(i)
 
        case CTFLT:
                Yyerror("no float -> string")
index 3e49b9431e8be983550f86dacaf488a7c6ee9ca9..2d20e0a9c39256a9a31660ff7d9cb4e0529c5213 100644 (file)
@@ -236,6 +236,9 @@ func intstring(buf *[4]byte, v int64) string {
        } else {
                s, b = rawstring(4)
        }
+       if int64(rune(v)) != v {
+               v = runeerror
+       }
        n := runetochar(b, rune(v))
        return s[:n]
 }
diff --git a/test/fixedbugs/issue15039.go b/test/fixedbugs/issue15039.go
new file mode 100644 (file)
index 0000000..85d9e83
--- /dev/null
@@ -0,0 +1,25 @@
+// run
+
+// Copyright 2016 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() {
+       const fffd = "\uFFFD"
+
+       // runtime.intstring used to convert int64 to rune without checking
+       // for truncation.
+       u := uint64(0x10001f4a9)
+       big := string(u)
+       if big != fffd {
+               panic("big != bad")
+       }
+
+       // cmd/compile used to require integer constants to fit into an "int".
+       const huge = string(1<<100)
+       if huge != fffd {
+               panic("huge != bad")
+       }
+}