// Copyright 2017 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.

// sanitizers_test checks the use of Go with sanitizers like msan, asan, etc.
// See https://github.com/google/sanitizers.
package sanitizers_test

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"syscall"
	"testing"
	"unicode"
)

var overcommit struct {
	sync.Once
	value int
	err   error
}

// requireOvercommit skips t if the kernel does not allow overcommit.
func requireOvercommit(t *testing.T) {
	t.Helper()

	overcommit.Once.Do(func() {
		var out []byte
		out, overcommit.err = os.ReadFile("/proc/sys/vm/overcommit_memory")
		if overcommit.err != nil {
			return
		}
		overcommit.value, overcommit.err = strconv.Atoi(string(bytes.TrimSpace(out)))
	})

	if overcommit.err != nil {
		t.Skipf("couldn't determine vm.overcommit_memory (%v); assuming no overcommit", overcommit.err)
	}
	if overcommit.value == 2 {
		t.Skip("vm.overcommit_memory=2")
	}
}

var env struct {
	sync.Once
	m   map[string]string
	err error
}

// goEnv returns the output of $(go env) as a map.
func goEnv(key string) (string, error) {
	env.Once.Do(func() {
		var out []byte
		out, env.err = exec.Command("go", "env", "-json").Output()
		if env.err != nil {
			return
		}

		env.m = make(map[string]string)
		env.err = json.Unmarshal(out, &env.m)
	})
	if env.err != nil {
		return "", env.err
	}

	v, ok := env.m[key]
	if !ok {
		return "", fmt.Errorf("`go env`: no entry for %v", key)
	}
	return v, nil
}

// replaceEnv sets the key environment variable to value in cmd.
func replaceEnv(cmd *exec.Cmd, key, value string) {
	if cmd.Env == nil {
		cmd.Env = os.Environ()
	}
	cmd.Env = append(cmd.Env, key+"="+value)
}

// mustRun executes t and fails cmd with a well-formatted message if it fails.
func mustRun(t *testing.T, cmd *exec.Cmd) {
	t.Helper()
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("%#q exited with %v\n%s", strings.Join(cmd.Args, " "), err, out)
	}
}

// cc returns a cmd that executes `$(go env CC) $(go env GOGCCFLAGS) $args`.
func cc(args ...string) (*exec.Cmd, error) {
	CC, err := goEnv("CC")
	if err != nil {
		return nil, err
	}

	GOGCCFLAGS, err := goEnv("GOGCCFLAGS")
	if err != nil {
		return nil, err
	}

	// Split GOGCCFLAGS, respecting quoting.
	//
	// TODO(bcmills): This code also appears in
	// misc/cgo/testcarchive/carchive_test.go, and perhaps ought to go in
	// src/cmd/dist/test.go as well. Figure out where to put it so that it can be
	// shared.
	var flags []string
	quote := '\000'
	start := 0
	lastSpace := true
	backslash := false
	for i, c := range GOGCCFLAGS {
		if quote == '\000' && unicode.IsSpace(c) {
			if !lastSpace {
				flags = append(flags, GOGCCFLAGS[start:i])
				lastSpace = true
			}
		} else {
			if lastSpace {
				start = i
				lastSpace = false
			}
			if quote == '\000' && !backslash && (c == '"' || c == '\'') {
				quote = c
				backslash = false
			} else if !backslash && quote == c {
				quote = '\000'
			} else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
				backslash = true
			} else {
				backslash = false
			}
		}
	}
	if !lastSpace {
		flags = append(flags, GOGCCFLAGS[start:])
	}

	cmd := exec.Command(CC, flags...)
	cmd.Args = append(cmd.Args, args...)
	return cmd, nil
}

type version struct {
	name         string
	major, minor int
}

var compiler struct {
	sync.Once
	version
	err error
}

// compilerVersion detects the version of $(go env CC).
//
// It returns a non-nil error if the compiler matches a known version schema but
// the version could not be parsed, or if $(go env CC) could not be determined.
func compilerVersion() (version, error) {
	compiler.Once.Do(func() {
		compiler.err = func() error {
			compiler.name = "unknown"

			cmd, err := cc("--version")
			if err != nil {
				return err
			}
			out, err := cmd.Output()
			if err != nil {
				// Compiler does not support "--version" flag: not Clang or GCC.
				return nil
			}

			var match [][]byte
			if bytes.HasPrefix(out, []byte("gcc")) {
				compiler.name = "gcc"
				cmd, err := cc("-v")
				if err != nil {
					return err
				}
				out, err := cmd.CombinedOutput()
				if err != nil {
					// gcc, but does not support gcc's "-v" flag?!
					return err
				}
				gccRE := regexp.MustCompile(`gcc version (\d+)\.(\d+)`)
				match = gccRE.FindSubmatch(out)
			} else {
				clangRE := regexp.MustCompile(`clang version (\d+)\.(\d+)`)
				if match = clangRE.FindSubmatch(out); len(match) > 0 {
					compiler.name = "clang"
				}
			}

			if len(match) < 3 {
				return nil // "unknown"
			}
			if compiler.major, err = strconv.Atoi(string(match[1])); err != nil {
				return err
			}
			if compiler.minor, err = strconv.Atoi(string(match[2])); err != nil {
				return err
			}
			return nil
		}()
	})
	return compiler.version, compiler.err
}

// compilerSupportsLocation reports whether the compiler should be
// able to provide file/line information in backtraces.
func compilerSupportsLocation() bool {
	compiler, err := compilerVersion()
	if err != nil {
		return false
	}
	switch compiler.name {
	case "gcc":
		return compiler.major >= 10
	case "clang":
		return true
	default:
		return false
	}
}

// compilerRequiredAsanVersion reports whether the compiler is the version required by Asan.
func compilerRequiredAsanVersion() bool {
	compiler, err := compilerVersion()
	if err != nil {
		return false
	}
	switch compiler.name {
	case "gcc":
		return compiler.major >= 7
	case "clang":
		return compiler.major >= 9
	default:
		return false
	}
}

type compilerCheck struct {
	once sync.Once
	err  error
	skip bool // If true, skip with err instead of failing with it.
}

type config struct {
	sanitizer string

	cFlags, ldFlags, goFlags []string

	sanitizerCheck, runtimeCheck compilerCheck
}

var configs struct {
	sync.Mutex
	m map[string]*config
}

// configure returns the configuration for the given sanitizer.
func configure(sanitizer string) *config {
	configs.Lock()
	defer configs.Unlock()
	if c, ok := configs.m[sanitizer]; ok {
		return c
	}

	c := &config{
		sanitizer: sanitizer,
		cFlags:    []string{"-fsanitize=" + sanitizer},
		ldFlags:   []string{"-fsanitize=" + sanitizer},
	}

	if testing.Verbose() {
		c.goFlags = append(c.goFlags, "-x")
	}

	switch sanitizer {
	case "memory":
		c.goFlags = append(c.goFlags, "-msan")

	case "thread":
		c.goFlags = append(c.goFlags, "--installsuffix=tsan")
		compiler, _ := compilerVersion()
		if compiler.name == "gcc" {
			c.cFlags = append(c.cFlags, "-fPIC")
			c.ldFlags = append(c.ldFlags, "-fPIC", "-static-libtsan")
		}

	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))
	}

	if configs.m == nil {
		configs.m = make(map[string]*config)
	}
	configs.m[sanitizer] = c
	return c
}

// goCmd returns a Cmd that executes "go $subcommand $args" with appropriate
// additional flags and environment.
func (c *config) goCmd(subcommand string, args ...string) *exec.Cmd {
	cmd := exec.Command("go", subcommand)
	cmd.Args = append(cmd.Args, c.goFlags...)
	cmd.Args = append(cmd.Args, args...)
	replaceEnv(cmd, "CGO_CFLAGS", strings.Join(c.cFlags, " "))
	replaceEnv(cmd, "CGO_LDFLAGS", strings.Join(c.ldFlags, " "))
	return cmd
}

// skipIfCSanitizerBroken skips t if the C compiler does not produce working
// binaries as configured.
func (c *config) skipIfCSanitizerBroken(t *testing.T) {
	check := &c.sanitizerCheck
	check.once.Do(func() {
		check.skip, check.err = c.checkCSanitizer()
	})
	if check.err != nil {
		t.Helper()
		if check.skip {
			t.Skip(check.err)
		}
		t.Fatal(check.err)
	}
}

var cMain = []byte(`
int main() {
	return 0;
}
`)

func (c *config) checkCSanitizer() (skip bool, err error) {
	dir, err := os.MkdirTemp("", c.sanitizer)
	if err != nil {
		return false, fmt.Errorf("failed to create temp directory: %v", err)
	}
	defer os.RemoveAll(dir)

	src := filepath.Join(dir, "return0.c")
	if err := os.WriteFile(src, cMain, 0600); err != nil {
		return false, fmt.Errorf("failed to write C source file: %v", err)
	}

	dst := filepath.Join(dir, "return0")
	cmd, err := cc(c.cFlags...)
	if err != nil {
		return false, err
	}
	cmd.Args = append(cmd.Args, c.ldFlags...)
	cmd.Args = append(cmd.Args, "-o", dst, src)
	out, err := cmd.CombinedOutput()
	if err != nil {
		if bytes.Contains(out, []byte("-fsanitize")) &&
			(bytes.Contains(out, []byte("unrecognized")) ||
				bytes.Contains(out, []byte("unsupported"))) {
			return true, errors.New(string(out))
		}
		return true, fmt.Errorf("%#q failed: %v\n%s", strings.Join(cmd.Args, " "), err, out)
	}

	if out, err := exec.Command(dst).CombinedOutput(); err != nil {
		if os.IsNotExist(err) {
			return true, fmt.Errorf("%#q failed to produce executable: %v", strings.Join(cmd.Args, " "), err)
		}
		snippet, _, _ := bytes.Cut(out, []byte("\n"))
		return true, fmt.Errorf("%#q generated broken executable: %v\n%s", strings.Join(cmd.Args, " "), err, snippet)
	}

	return false, nil
}

// skipIfRuntimeIncompatible skips t if the Go runtime is suspected not to work
// with cgo as configured.
func (c *config) skipIfRuntimeIncompatible(t *testing.T) {
	check := &c.runtimeCheck
	check.once.Do(func() {
		check.skip, check.err = c.checkRuntime()
	})
	if check.err != nil {
		t.Helper()
		if check.skip {
			t.Skip(check.err)
		}
		t.Fatal(check.err)
	}
}

func (c *config) checkRuntime() (skip bool, err error) {
	if c.sanitizer != "thread" {
		return false, nil
	}

	// libcgo.h sets CGO_TSAN if it detects TSAN support in the C compiler.
	// Dump the preprocessor defines to check that works.
	// (Sometimes it doesn't: see https://golang.org/issue/15983.)
	cmd, err := cc(c.cFlags...)
	if err != nil {
		return false, err
	}
	cmd.Args = append(cmd.Args, "-dM", "-E", "../../../src/runtime/cgo/libcgo.h")
	cmdStr := strings.Join(cmd.Args, " ")
	out, err := cmd.CombinedOutput()
	if err != nil {
		return false, fmt.Errorf("%#q exited with %v\n%s", cmdStr, err, out)
	}
	if !bytes.Contains(out, []byte("#define CGO_TSAN")) {
		return true, fmt.Errorf("%#q did not define CGO_TSAN", cmdStr)
	}
	return false, nil
}

// srcPath returns the path to the given file relative to this test's source tree.
func srcPath(path string) string {
	return filepath.Join("testdata", path)
}

// A tempDir manages a temporary directory within a test.
type tempDir struct {
	base string
}

func (d *tempDir) RemoveAll(t *testing.T) {
	t.Helper()
	if d.base == "" {
		return
	}
	if err := os.RemoveAll(d.base); err != nil {
		t.Fatalf("Failed to remove temp dir: %v", err)
	}
}

func (d *tempDir) Join(name string) string {
	return filepath.Join(d.base, name)
}

func newTempDir(t *testing.T) *tempDir {
	t.Helper()
	dir, err := os.MkdirTemp("", filepath.Dir(t.Name()))
	if err != nil {
		t.Fatalf("Failed to create temp dir: %v", err)
	}
	return &tempDir{base: dir}
}

// hangProneCmd returns an exec.Cmd for a command that is likely to hang.
//
// If one of these tests hangs, the caller is likely to kill the test process
// using SIGINT, which will be sent to all of the processes in the test's group.
// Unfortunately, TSAN in particular is prone to dropping signals, so the SIGINT
// may terminate the test binary but leave the subprocess running. hangProneCmd
// configures subprocess to receive SIGKILL instead to ensure that it won't
// leak.
func hangProneCmd(name string, arg ...string) *exec.Cmd {
	cmd := exec.Command(name, arg...)
	cmd.SysProcAttr = &syscall.SysProcAttr{
		Pdeathsig: syscall.SIGKILL,
	}
	return cmd
}

// mSanSupported is a copy of the function cmd/internal/sys.MSanSupported,
// because the internal pacakage can't be used here.
func mSanSupported(goos, goarch string) bool {
	switch goos {
	case "linux":
		return goarch == "amd64" || goarch == "arm64"
	default:
		return false
	}
}

// aSanSupported is a copy of the function cmd/internal/sys.ASanSupported,
// because the internal pacakage can't be used here.
func aSanSupported(goos, goarch string) bool {
	switch goos {
	case "linux":
		return goarch == "amd64" || goarch == "arm64" || goarch == "riscv64"
	default:
		return false
	}
}
