aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2016-04-24 17:04:32 -0700
committerKeith Randall <khr@golang.org>2016-04-25 21:16:52 +0000
commit6f3f02f80d23d3bbc2857be147341517d1762fbd (patch)
tree1dd0d232571ed10060d8d2f8fc65fe506f6750da /src/runtime
parent8b92397bcdcd5d6de3f72951a5514933fee32eb2 (diff)
downloadgo-6f3f02f80d23d3bbc2857be147341517d1762fbd.tar.xz
runtime: zero tmpbuf between len and cap
Zero the entire buffer so we don't need to lower its capacity upon return. This lets callers do some appending without allocation. Zeroing is cheap, the byte buffer requires only 4 extra instructions. Fixes #14235 Change-Id: I970d7badcef047dafac75ac17130030181f18fe2 Reviewed-on: https://go-review.googlesource.com/22424 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/string.go6
-rw-r--r--src/runtime/string_test.go26
2 files changed, 26 insertions, 6 deletions
diff --git a/src/runtime/string.go b/src/runtime/string.go
index 112ce5d588..ef28ba9828 100644
--- a/src/runtime/string.go
+++ b/src/runtime/string.go
@@ -139,7 +139,8 @@ func slicebytetostringtmp(b []byte) string {
func stringtoslicebyte(buf *tmpBuf, s string) []byte {
var b []byte
if buf != nil && len(s) <= len(buf) {
- b = buf[:len(s):len(s)]
+ *buf = tmpBuf{}
+ b = buf[:len(s)]
} else {
b = rawbyteslice(len(s))
}
@@ -171,7 +172,8 @@ func stringtoslicerune(buf *[tmpStringBufSize]rune, s string) []rune {
}
var a []rune
if buf != nil && n <= len(buf) {
- a = buf[:n:n]
+ *buf = [tmpStringBufSize]rune{}
+ a = buf[:n]
} else {
a = rawruneslice(n)
}
diff --git a/src/runtime/string_test.go b/src/runtime/string_test.go
index ee9709e87d..0f1d82a481 100644
--- a/src/runtime/string_test.go
+++ b/src/runtime/string_test.go
@@ -238,17 +238,35 @@ func TestRangeStringCast(t *testing.T) {
}
}
+func isZeroed(b []byte) bool {
+ for _, x := range b {
+ if x != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+func isZeroedR(r []rune) bool {
+ for _, x := range r {
+ if x != 0 {
+ return false
+ }
+ }
+ return true
+}
+
func TestString2Slice(t *testing.T) {
// Make sure we don't return slices that expose
// an unzeroed section of stack-allocated temp buf
// between len and cap. See issue 14232.
s := "foož"
b := ([]byte)(s)
- if cap(b) != 5 {
- t.Errorf("want cap of 5, got %d", cap(b))
+ if !isZeroed(b[len(b):cap(b)]) {
+ t.Errorf("extra bytes not zeroed")
}
r := ([]rune)(s)
- if cap(r) != 4 {
- t.Errorf("want cap of 4, got %d", cap(r))
+ if !isZeroedR(r[len(r):cap(r)]) {
+ t.Errorf("extra runes not zeroed")
}
}