diff options
| author | fanzha02 <fannie.zhang@arm.com> | 2021-12-27 16:38:48 +0800 |
|---|---|---|
| committer | Fannie Zhang <Fannie.Zhang@arm.com> | 2021-12-29 04:10:07 +0000 |
| commit | 91e782106ea465acc6a4c719081cefb690b28533 (patch) | |
| tree | dc69bb7edd41acb438b4bb0564467583eb5f806a /misc | |
| parent | a78532a4121d26c33ee3ce69b3dda3a608f5a077 (diff) | |
| download | go-91e782106ea465acc6a4c719081cefb690b28533.tar.xz | |
runtime: fix the issue that the -asan option cannot print where the error occurred
The current -asan option does not print where the error occurred. The
reason is that the current implementation calls incorrect asan runtime
functions, which do not pass sp and pc where asan runtime functions are
called, and report the stack trace from the native code. But asan runtime
functions are called from cgo on a separated stack, so it cannot dump the
Go stack trace correctly.
The correct asan runtime function we should call is __asan_report_error,
which will pass sp and pc, and report where the error occurred correctly.
This patch fixes this issue.
Add the test cases.
Fixes #50362
Change-Id: I12ee1d46c7ae069ddef3d23f2fe86e112db60045
Reviewed-on: https://go-review.googlesource.com/c/go/+/374395
Trust: Fannie Zhang <Fannie.Zhang@arm.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'misc')
| -rw-r--r-- | misc/cgo/testsanitizers/asan_test.go | 13 | ||||
| -rw-r--r-- | misc/cgo/testsanitizers/cc_test.go | 2 | ||||
| -rw-r--r-- | misc/cgo/testsanitizers/testdata/asan1_fail.go | 2 | ||||
| -rw-r--r-- | misc/cgo/testsanitizers/testdata/asan2_fail.go | 2 |
4 files changed, 13 insertions, 6 deletions
diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go index dbcce2fe28..cd1e9f354b 100644 --- a/misc/cgo/testsanitizers/asan_test.go +++ b/misc/cgo/testsanitizers/asan_test.go @@ -33,11 +33,12 @@ func TestASAN(t *testing.T) { cases := []struct { src string memoryAccessError string + errorLocation string }{ - {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free"}, - {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow"}, - {src: "asan3_fail.go", memoryAccessError: "use-after-poison"}, - {src: "asan4_fail.go", memoryAccessError: "use-after-poison"}, + {src: "asan1_fail.go", memoryAccessError: "heap-use-after-free", errorLocation: "asan1_fail.go:25"}, + {src: "asan2_fail.go", memoryAccessError: "heap-buffer-overflow", errorLocation: "asan2_fail.go:31"}, + {src: "asan3_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan3_fail.go:13"}, + {src: "asan4_fail.go", memoryAccessError: "use-after-poison", errorLocation: "asan4_fail.go:13"}, {src: "asan_useAfterReturn.go"}, } for _, tc := range cases { @@ -56,6 +57,10 @@ func TestASAN(t *testing.T) { if tc.memoryAccessError != "" { out, err := cmd.CombinedOutput() if err != nil && strings.Contains(string(out), tc.memoryAccessError) { + // Check if -asan option can correctly print where the error occured. + if tc.errorLocation != "" && !strings.Contains(string(out), tc.errorLocation) { + t.Errorf("%#q exited without expected location of the error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.errorLocation, out) + } return } t.Fatalf("%#q exited without expected memory access error\n%s; got failure\n%s", strings.Join(cmd.Args, " "), tc.memoryAccessError, out) diff --git a/misc/cgo/testsanitizers/cc_test.go b/misc/cgo/testsanitizers/cc_test.go index b776afa3e6..0ce4f75935 100644 --- a/misc/cgo/testsanitizers/cc_test.go +++ b/misc/cgo/testsanitizers/cc_test.go @@ -269,6 +269,8 @@ func configure(sanitizer string) *config { case "address": c.goFlags = append(c.goFlags, "-asan") + // Set the debug mode to print the C stack trace. + c.cFlags = append(c.cFlags, "-g") default: panic(fmt.Sprintf("unrecognized sanitizer: %q", sanitizer)) diff --git a/misc/cgo/testsanitizers/testdata/asan1_fail.go b/misc/cgo/testsanitizers/testdata/asan1_fail.go index e60db76981..80289e5c30 100644 --- a/misc/cgo/testsanitizers/testdata/asan1_fail.go +++ b/misc/cgo/testsanitizers/testdata/asan1_fail.go @@ -22,7 +22,7 @@ func main() { // C passes Go an invalid pointer. a := C.test() // Use after free - *a = 2 + *a = 2 // BOOM // We shouldn't get here; asan should stop us first. fmt.Println(*a) } diff --git a/misc/cgo/testsanitizers/testdata/asan2_fail.go b/misc/cgo/testsanitizers/testdata/asan2_fail.go index e35670c440..3ab0608571 100644 --- a/misc/cgo/testsanitizers/testdata/asan2_fail.go +++ b/misc/cgo/testsanitizers/testdata/asan2_fail.go @@ -28,7 +28,7 @@ func main() { a := C.f() q5 := (*C.int)(unsafe.Add(unsafe.Pointer(a), 4*5)) // Access to C pointer out of bounds. - *q5 = 100 + *q5 = 100 // BOOM // We shouldn't get here; asan should stop us first. fmt.Printf("q5: %d, %x\n", *q5, q5) } |
