Commit dc9755c2 authored by Ian Lance Taylor's avatar Ian Lance Taylor

runtime: add missing race and msan checks to reflect functions

Add missing race and msan checks to reflect.typedmmemove and
reflect.typedslicecopy. Missing these checks caused the race detector
to miss races and caused msan to issue false positive errors.

Fixes #16281.

Change-Id: I500b5f92bd68dc99dd5d6f297827fd5d2609e88b
Reviewed-on: https://go-review.googlesource.com/24760
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
parent d9504d46
// 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
// Using reflect to set a value was not seen by msan.
/*
#include <stdlib.h>
extern void Go1(int*);
extern void Go2(char*);
// Use weak as a hack to permit defining a function even though we use export.
void C1() __attribute__ ((weak));
void C2() __attribute__ ((weak));
void C1() {
int i;
Go1(&i);
if (i != 42) {
abort();
}
}
void C2() {
char a[2];
a[1] = 42;
Go2(a);
if (a[0] != 42) {
abort();
}
}
*/
import "C"
import (
"reflect"
"unsafe"
)
//export Go1
func Go1(p *C.int) {
reflect.ValueOf(p).Elem().Set(reflect.ValueOf(C.int(42)))
}
//export Go2
func Go2(p *C.char) {
a := (*[2]byte)(unsafe.Pointer(p))
reflect.Copy(reflect.ValueOf(a[:1]), reflect.ValueOf(a[1:]))
}
func main() {
C.C1()
C.C2()
}
......@@ -88,6 +88,11 @@ if test "$msan" = "yes"; then
status=1
fi
if ! go run -msan msan5.go; then
echo "FAIL: msan5"
status=1
fi
if go run -msan msan_fail.go 2>/dev/null; then
echo "FAIL: msan_fail"
status=1
......
......@@ -185,6 +185,14 @@ func typedmemmove(typ *_type, dst, src unsafe.Pointer) {
//go:linkname reflect_typedmemmove reflect.typedmemmove
func reflect_typedmemmove(typ *_type, dst, src unsafe.Pointer) {
if raceenabled {
raceWriteObjectPC(typ, dst, getcallerpc(unsafe.Pointer(&typ)), funcPC(reflect_typedmemmove))
raceReadObjectPC(typ, src, getcallerpc(unsafe.Pointer(&typ)), funcPC(reflect_typedmemmove))
}
if msanenabled {
msanwrite(dst, typ.size)
msanread(src, typ.size)
}
typedmemmove(typ, dst, src)
}
......@@ -300,7 +308,23 @@ func reflect_typedslicecopy(elemType *_type, dst, src slice) int {
if n > src.len {
n = src.len
}
memmove(dst.array, src.array, uintptr(n)*elemType.size)
if n == 0 {
return 0
}
size := uintptr(n) * elemType.size
if raceenabled {
callerpc := getcallerpc(unsafe.Pointer(&elemType))
pc := funcPC(reflect_typedslicecopy)
racewriterangepc(dst.array, size, callerpc, pc)
racereadrangepc(src.array, size, callerpc, pc)
}
if msanenabled {
msanwrite(dst.array, size)
msanread(src.array, size)
}
memmove(dst.array, src.array, size)
return n
}
return typedslicecopy(elemType, dst, src)
......
// 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 race_test
import (
"reflect"
"testing"
)
func TestRaceReflectRW(t *testing.T) {
ch := make(chan bool, 1)
i := 0
v := reflect.ValueOf(&i)
go func() {
v.Elem().Set(reflect.ValueOf(1))
ch <- true
}()
_ = v.Elem().Int()
<-ch
}
func TestRaceReflectWW(t *testing.T) {
ch := make(chan bool, 1)
i := 0
v := reflect.ValueOf(&i)
go func() {
v.Elem().Set(reflect.ValueOf(1))
ch <- true
}()
v.Elem().Set(reflect.ValueOf(2))
<-ch
}
func TestRaceReflectCopyWW(t *testing.T) {
ch := make(chan bool, 1)
a := make([]byte, 2)
v := reflect.ValueOf(a)
go func() {
reflect.Copy(v, v)
ch <- true
}()
reflect.Copy(v, v)
<-ch
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment