From 51ff6f7b5c0040088a39dbb78a7a166c3fcbf89c Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 9 Nov 2020 21:37:20 +0700 Subject: [PATCH] fix: misuse of reflect.SliceHeader (#19875) Currently, unsafeBytesToString function violates the 6th rule of unsafe pointer usage. That is, reflect.SliceHeader/String header should never be used as plain struct. This misuse can make to silent memory corruption, which can be difficult to track down when problem occurred. Instead, use the more (right) idiom to convert slice of byte to string without heap allocation. goos: linux goarch: amd64 cpu: Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz BenchmarkInvalid-8 1000000000 0.497 ns/op 0 B/op 0 allocs/op BenchmarkValid-8 1000000000 0.239 ns/op 0 B/op 0 allocs/op PASS ok command-line-arguments 0.815s --- id.go | 9 +-------- models/inline_strconv_parse.go | 12 +----------- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/id.go b/id.go index 2e3df9dbd7..125c177f56 100644 --- a/id.go +++ b/id.go @@ -3,7 +3,6 @@ package influxdb import ( "encoding/binary" "encoding/hex" - "reflect" "strconv" "unsafe" ) @@ -83,13 +82,7 @@ func (i *ID) Decode(b []byte) error { } func unsafeBytesToString(in []byte) string { - src := *(*reflect.SliceHeader)(unsafe.Pointer(&in)) - dst := reflect.StringHeader{ - Data: src.Data, - Len: src.Len, - } - s := *(*string)(unsafe.Pointer(&dst)) - return s + return *(*string)(unsafe.Pointer(&in)) } // DecodeFromString parses s as a hex-encoded string. diff --git a/models/inline_strconv_parse.go b/models/inline_strconv_parse.go index 8db4837384..0ad5468994 100644 --- a/models/inline_strconv_parse.go +++ b/models/inline_strconv_parse.go @@ -1,7 +1,6 @@ package models // import "github.com/influxdata/influxdb/models" import ( - "reflect" "strconv" "unsafe" ) @@ -30,15 +29,6 @@ func parseBoolBytes(b []byte) (bool, error) { } // unsafeBytesToString converts a []byte to a string without a heap allocation. -// -// It is unsafe, and is intended to prepare input to short-lived functions -// that require strings. func unsafeBytesToString(in []byte) string { - src := *(*reflect.SliceHeader)(unsafe.Pointer(&in)) - dst := reflect.StringHeader{ - Data: src.Data, - Len: src.Len, - } - s := *(*string)(unsafe.Pointer(&dst)) - return s + return *(*string)(unsafe.Pointer(&in)) }