mirror of
https://github.com/golang/go
synced 2024-11-02 09:03:03 +00:00
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 <bradfitz@golang.org>
This commit is contained in:
parent
e7538df701
commit
e6066711a0
3 changed files with 32 additions and 4 deletions
|
@ -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")
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
|
25
test/fixedbugs/issue15039.go
Normal file
25
test/fixedbugs/issue15039.go
Normal file
|
@ -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")
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue