From e6066711a0f92824ded94849e4f1085c2ba612c3 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 31 Mar 2016 02:04:12 -0700 Subject: [PATCH] cmd/compile, runtime: fix pedantic int->string conversions 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 --- src/cmd/compile/internal/gc/const.go | 8 ++++---- src/runtime/string.go | 3 +++ test/fixedbugs/issue15039.go | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 test/fixedbugs/issue15039.go diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index af75580cbb..49c2a8f41c 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -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") diff --git a/src/runtime/string.go b/src/runtime/string.go index 3e49b9431e..2d20e0a9c3 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -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 index 0000000000..85d9e8340a --- /dev/null +++ b/test/fixedbugs/issue15039.go @@ -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") + } +} -- 2.48.1