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

// Check for invalid cgo pointer passing.
// This looks for code that uses cgo to call C code passing values
// whose types are almost always invalid according to the cgo pointer
// sharing rules.
// Specifically, it warns about attempts to pass a Go chan, map, func,
// or slice to C, either directly, or via a pointer, array, or struct.

package main

import (
	"go/ast"
	"go/token"
	"go/types"
)

func init() {
	register("cgocall",
		"check for types that may not be passed to cgo calls",
		checkCgoCall,
		callExpr)
}

func checkCgoCall(f *File, node ast.Node) {
	x := node.(*ast.CallExpr)

	// We are only looking for calls to functions imported from
	// the "C" package.
	sel, ok := x.Fun.(*ast.SelectorExpr)
	if !ok {
		return
	}
	id, ok := sel.X.(*ast.Ident)
	if !ok {
		return
	}

	pkgname, ok := f.pkg.uses[id].(*types.PkgName)
	if !ok || pkgname.Imported().Path() != "C" {
		return
	}

	// A call to C.CBytes passes a pointer but is always safe.
	if sel.Sel.Name == "CBytes" {
		return
	}

	for _, arg := range x.Args {
		if !typeOKForCgoCall(cgoBaseType(f, arg), make(map[types.Type]bool)) {
			f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
		}

		// Check for passing the address of a bad type.
		if conv, ok := arg.(*ast.CallExpr); ok && len(conv.Args) == 1 && f.hasBasicType(conv.Fun, types.UnsafePointer) {
			arg = conv.Args[0]
		}
		if u, ok := arg.(*ast.UnaryExpr); ok && u.Op == token.AND {
			if !typeOKForCgoCall(cgoBaseType(f, u.X), make(map[types.Type]bool)) {
				f.Badf(arg.Pos(), "possibly passing Go type with embedded pointer to C")
			}
		}
	}
}

// cgoBaseType tries to look through type conversions involving
// unsafe.Pointer to find the real type. It converts:
//   unsafe.Pointer(x) => x
//   *(*unsafe.Pointer)(unsafe.Pointer(&x)) => x
func cgoBaseType(f *File, arg ast.Expr) types.Type {
	switch arg := arg.(type) {
	case *ast.CallExpr:
		if len(arg.Args) == 1 && f.hasBasicType(arg.Fun, types.UnsafePointer) {
			return cgoBaseType(f, arg.Args[0])
		}
	case *ast.StarExpr:
		call, ok := arg.X.(*ast.CallExpr)
		if !ok || len(call.Args) != 1 {
			break
		}
		// Here arg is *f(v).
		t := f.pkg.types[call.Fun].Type
		if t == nil {
			break
		}
		ptr, ok := t.Underlying().(*types.Pointer)
		if !ok {
			break
		}
		// Here arg is *(*p)(v)
		elem, ok := ptr.Elem().Underlying().(*types.Basic)
		if !ok || elem.Kind() != types.UnsafePointer {
			break
		}
		// Here arg is *(*unsafe.Pointer)(v)
		call, ok = call.Args[0].(*ast.CallExpr)
		if !ok || len(call.Args) != 1 {
			break
		}
		// Here arg is *(*unsafe.Pointer)(f(v))
		if !f.hasBasicType(call.Fun, types.UnsafePointer) {
			break
		}
		// Here arg is *(*unsafe.Pointer)(unsafe.Pointer(v))
		u, ok := call.Args[0].(*ast.UnaryExpr)
		if !ok || u.Op != token.AND {
			break
		}
		// Here arg is *(*unsafe.Pointer)(unsafe.Pointer(&v))
		return cgoBaseType(f, u.X)
	}

	return f.pkg.types[arg].Type
}

// typeOKForCgoCall reports whether the type of arg is OK to pass to a
// C function using cgo. This is not true for Go types with embedded
// pointers. m is used to avoid infinite recursion on recursive types.
func typeOKForCgoCall(t types.Type, m map[types.Type]bool) bool {
	if t == nil || m[t] {
		return true
	}
	m[t] = true
	switch t := t.Underlying().(type) {
	case *types.Chan, *types.Map, *types.Signature, *types.Slice:
		return false
	case *types.Pointer:
		return typeOKForCgoCall(t.Elem(), m)
	case *types.Array:
		return typeOKForCgoCall(t.Elem(), m)
	case *types.Struct:
		for i := 0; i < t.NumFields(); i++ {
			if !typeOKForCgoCall(t.Field(i).Type(), m) {
				return false
			}
		}
	}
	return true
}
