exclude identifiers used via reflection

If reflect.TypeOf or reflect.ValueOf are used on a type declared in the same package,
don't garble that type name or any of its fields.

Fixes #15.
pull/28/head
lu4p 4 years ago committed by GitHub
parent e8074d4665
commit 8b898ad0d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -319,6 +319,9 @@ func transformCompile(args []string) ([]string, error) {
flags = flagSetValue(flags, "-trimpath", tempDir+"=>;"+trimpath)
// log.Println(flags)
args = flags
blacklist := buildBlacklist(files, info)
// TODO: randomize the order and names of the files
for i, file := range files {
origName := filepath.Base(filepath.Clean(paths[i]))
@ -330,7 +333,7 @@ func transformCompile(args []string) ([]string, error) {
// messy.
name = "_cgo_" + name
default:
file = transformGo(file, info)
file = transformGo(file, info, blacklist)
}
tempFile := filepath.Join(tempDir, name)
f, err := os.Create(tempFile)
@ -444,8 +447,43 @@ func hashWith(salt, value string) string {
return "z" + sum[:length]
}
func buildBlacklist(files []*ast.File, info *types.Info) (blacklist []types.Object) {
pre := func(node ast.Node) bool {
nodeExpr, ok := node.(*ast.CallExpr)
if !ok {
return true
}
exprFunc, ok := nodeExpr.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
exprFuncType := info.ObjectOf(exprFunc.Sel)
if exprFuncType.Pkg().Path() == "reflect" && (exprFuncType.Name() == "TypeOf" || exprFuncType.Name() == "ValueOf") {
for _, arg := range nodeExpr.Args {
if expr, ok := arg.(*ast.CallExpr); ok {
if f, ok := expr.Fun.(*ast.Ident); ok {
blacklistItem := info.ObjectOf(f)
blacklist = append(blacklist, blacklistItem)
}
}
}
}
return true
}
for _, file := range files {
ast.Inspect(file, pre)
}
return blacklist
}
// transformGo garbles the provided Go syntax node.
func transformGo(file *ast.File, info *types.Info) *ast.File {
func transformGo(file *ast.File, info *types.Info, blacklist []types.Object) *ast.File {
// Remove all comments, minus the "//go:" compiler directives.
// The final binary should still not contain comment text, but removing
// it helps ensure that (and makes position info less predictable).
@ -497,6 +535,13 @@ func transformGo(file *ast.File, info *types.Info) *ast.File {
// about other -buildmode options?
return true // could be a Go plugin API
}
for _, item := range blacklist {
if item.Pkg().Path() == obj.Pkg().Path() && item.Name() == obj.Name() {
return true
}
}
// log.Printf("%#v %T", node, obj)
switch x := obj.(type) {
case *types.Var:

@ -3,6 +3,7 @@ exec ./main
cmp stdout main.stdout
! binsubstr main$exe 'ImportedVar' 'ImportedConst' 'ImportedFunc' 'ImportedType' 'main.go' 'imported.go'
binsubstr main$exe 'ImportedAPI'
[short] stop # checking that the build is reproducible is slow
@ -23,6 +24,7 @@ package main
import (
"fmt"
"reflect"
_ "unsafe"
"test/main/imported"
@ -38,6 +40,9 @@ func main() {
fmt.Println(imported.ImportedConst)
imported.ImportedFunc('x')
fmt.Println(imported.ImportedType(3))
api := new(imported.ImportedAPI)
fmt.Println(reflect.TypeOf(api))
linkedPrintln(nil)
fmt.Println(quote.Go())
}
@ -45,11 +50,14 @@ func main() {
imported var value
imported const value
3
*imported.ImportedAPI
<nil>
Don't communicate by sharing memory, share memory by communicating.
-- imported/imported.go --
package imported
import "reflect"
var ImportedVar = "imported var value"
const ImportedConst = "imported const value"
@ -59,3 +67,7 @@ func ImportedFunc(param rune) string {
}
type ImportedType int
type ImportedAPI int
var _ = reflect.TypeOf(ImportedAPI(0))
Loading…
Cancel
Save