google / sanitizers

AddressSanitizer, ThreadSanitizer, MemorySanitizer
Other
11.32k stars 1.02k forks source link

sanitizer-leak is NOT detected when golang using cgo to call c library #1223

Open xqzhang2015 opened 4 years ago

xqzhang2015 commented 4 years ago

Previously I used clang-3.8.1 and sanitizer is crashed when using AddressSanitizer. BTW, leakSanitizer doesn't work at all.

Then I try to use clang-llvm-10.0, AddressSanitizer could detect the address issue and work normally.

But leak issue can NOT be detected when golang using cgo to call C.

// #include // // int test() // { // int p = (int )malloc(10 * sizeof(int)); // free(p); // p[1] = 42; // return p[1]; // } import "C" import "fmt"

func main() { fmt.Println(int(C.test())) // Output: 42 }


* Output

[root@380c7770b175 cplusplus]# CC="clang" CGO_CFLAGS="-O0 -g -fsanitize=address" CGO_LDFLAGS="-fsanitize=address" go run cgo-sanitizer.go

==25680==ERROR: AddressSanitizer: heap-use-after-free on address 0x604000000014 at pc 0x00000054fc2d bp 0x7ffd96a943b0 sp 0x7ffd96a943a8 WRITE of size 4 at 0x604000000014 thread T0

0 0x54fc2c in test (/tmp/go-build237509829/b001/exe/cgo-sanitizer+0x54fc2c)

#1 0x54fcc1 in _cgo_a3187169dba5_Cfunc_test (/tmp/go-build237509829/b001/exe/cgo-sanitizer+0x54fcc1)
#2 0x5159df  (/tmp/go-build237509829/b001/exe/cgo-sanitizer+0x5159df)

* cgo-sanitizer-leak.go: leak issue was not detected.
```golang
package main

// #include <stdlib.h>
//
// int *p;
// int test()
// {
//   p = (int *)malloc(10 * sizeof(int));
//   p = 0;
//   return 52;
// }
import "C"
import "fmt"

func main() {
  fmt.Println(int(C.test()))
  // Output: 52
}
[root@380c7770b175 cplusplus]# CC="clang" CGO_CFLAGS="-O0 -g -fsanitize=leak" CGO_LDFLAGS="-fsanitize=address" go run cgo-sanitizer-leak.go
52

[root@380c7770b175 cplusplus]# clang -v clang version 10.0.0 Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/local/llvm-10.0/bin Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.8.2 Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.8.5 Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/4.8.5 Candidate multilib: .;@m64 Candidate multilib: 32;@m32 Selected multilib: .;@m64

[root@380c7770b175 cplusplus]# go version go version go1.13.6 linux/amd64

3v1n0 commented 10 months ago

I'm not sure if this is a sanitizer issue, or more a go one.

The only way to get sanitizer work seems to manually call C.__lsan_do_leak_check() when needed.

zhangfannie commented 10 months ago

This is a matter of go. Currently, there is no support for leak checking before the go program exits.

And, for the first case, we recommend using CGO_CFLAGS="-O0" go build -asan cgo-sanitizer.go.