You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			256 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
			
		
		
	
	
			256 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Plaintext
		
	
env GOGARBLE=test/main
 | 
						|
 | 
						|
garble build
 | 
						|
exec ./main
 | 
						|
cmp stdout main.stdout
 | 
						|
 | 
						|
! binsubstr main$exe 'garble_main.go' 'test/main' 'importedpkg.' 'DownstreamObfuscated' 'SiblingObfuscated' 'IndirectObfuscated' 'IndirectNamedWithoutReflect' 'AliasIndirectNamedWithReflect' 'AliasIndirectNamedWithoutReflect' 'FmtTypeField'
 | 
						|
binsubstr main$exe 'ReflectInDefined' 'ExportedField2' 'unexportedField2' 'IndirectUnobfuscated' 'IndirectNamedWithReflect'
 | 
						|
 | 
						|
[short] stop # no need to verify this with -short
 | 
						|
 | 
						|
# Check that the program works as expected without garble.
 | 
						|
go build
 | 
						|
exec ./main
 | 
						|
cmp stdout main.stdout
 | 
						|
 | 
						|
-- go.mod --
 | 
						|
module test/main
 | 
						|
 | 
						|
go 1.17
 | 
						|
-- garble_main.go --
 | 
						|
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"os"
 | 
						|
	"reflect"
 | 
						|
	"strings"
 | 
						|
	"text/template"
 | 
						|
 | 
						|
	"test/main/importedpkg"
 | 
						|
	"test/main/importedpkg2"
 | 
						|
)
 | 
						|
 | 
						|
func main() {
 | 
						|
	// Fields still work fine when they are not obfuscated.
 | 
						|
	fmt.Println(importedpkg.ReflectInDefinedVar.ExportedField2)
 | 
						|
	fmt.Println(importedpkg.ReflectInDefined{ExportedField2: 5})
 | 
						|
 | 
						|
	// Type names are not obfuscated either, when reflection is used.
 | 
						|
	printfWithoutPackage("%T\n", importedpkg.ReflectTypeOf(2))
 | 
						|
	printfWithoutPackage("%T\n", importedpkg.ReflectTypeOfIndirect(4))
 | 
						|
 | 
						|
	// More complex use of reflect.
 | 
						|
	v := importedpkg.ReflectValueOfVar
 | 
						|
	printfWithoutPackage("%#v\n", v)
 | 
						|
	method := reflect.ValueOf(&v).MethodByName("ExportedMethodName")
 | 
						|
	if method.IsValid() {
 | 
						|
		fmt.Println(method.Call(nil))
 | 
						|
	} else {
 | 
						|
		fmt.Println("method not found")
 | 
						|
	}
 | 
						|
 | 
						|
	// Use of a common library using reflect, encoding/json.
 | 
						|
	enc, _ := json.Marshal(EncodingT{Foo: 3})
 | 
						|
	fmt.Println(string(enc))
 | 
						|
 | 
						|
	// Another common library, text/template.
 | 
						|
	tmpl := template.Must(template.New("").Parse("Hello {{.Name}}."))
 | 
						|
	_ = tmpl.Execute(os.Stdout, struct{Name string}{Name: "Dave"})
 | 
						|
	fmt.Println() // Always print a newline.
 | 
						|
 | 
						|
	// Another complex case, involving embedding and another package.
 | 
						|
	outer := &importedpkg.EmbeddingOuter{}
 | 
						|
	outer.InnerField = 3
 | 
						|
	enc, _ = json.Marshal(outer)
 | 
						|
	fmt.Println(string(enc))
 | 
						|
 | 
						|
	// An edge case; the struct type is defined in a different package.
 | 
						|
	// Note that the struct type is unnamed, but it still has named fields.
 | 
						|
	// We only use reflection on it here, not the declaring package.
 | 
						|
	// As such, we should obfuscate the field name.
 | 
						|
	// Simply using the field name here used to cause build failures.
 | 
						|
	_ = reflect.TypeOf(importedpkg.UnnamedWithDownstreamReflect{})
 | 
						|
	fmt.Printf("%v\n", importedpkg.UnnamedWithDownstreamReflect{
 | 
						|
		DownstreamObfuscated: "downstream",
 | 
						|
	})
 | 
						|
 | 
						|
	// An edge case; the struct type is defined in package importedpkg2.
 | 
						|
	// importedpkg2 does not use reflection on it, so it's not obfuscated there.
 | 
						|
	// importedpkg uses reflection on a type containing ReflectInSiblingImport.
 | 
						|
	// If our logic is incorrect, we might inconsistently obfuscate the type.
 | 
						|
	// We should not obfuscate it when building any package.
 | 
						|
	fmt.Printf("%v\n", importedpkg2.ReflectInSiblingImport{
 | 
						|
		SiblingObfuscated: "sibling",
 | 
						|
	})
 | 
						|
 | 
						|
	// Using type aliases as both regular fields, and embedded fields.
 | 
						|
	var emb EmbeddingIndirect
 | 
						|
	emb.With.IndirectUnobfuscated = "indirect-with"
 | 
						|
	emb.Without.IndirectObfuscated = "indirect-without"
 | 
						|
	fmt.Printf("%v\n", emb)
 | 
						|
	printfWithoutPackage("%#v\n", emb.With)
 | 
						|
 | 
						|
	// TODO: don't obfuscate the embedded field name here
 | 
						|
	// printfWithoutPackage("%#v\n", importedpkg.ReflectEmbeddingAlias{})
 | 
						|
 | 
						|
	indirectReflection(IndirectReflection{})
 | 
						|
	fmt.Println(FmtType{})
 | 
						|
}
 | 
						|
 | 
						|
type EmbeddingIndirect struct {
 | 
						|
	// With field names, to test selectors above.
 | 
						|
	With importedpkg.AliasIndirectNamedWithReflect
 | 
						|
	Without importedpkg.AliasIndirectNamedWithoutReflect
 | 
						|
 | 
						|
	// Embedding used to crash garble, too.
 | 
						|
	importedpkg.AliasIndirectNamedWithReflect
 | 
						|
}
 | 
						|
 | 
						|
func printfWithoutPackage(format string, v interface{}) {
 | 
						|
	s := fmt.Sprintf(format, v)
 | 
						|
	if i := strings.IndexByte(s, '.'); i > 0 {
 | 
						|
		s = s[i+1:]
 | 
						|
	}
 | 
						|
	fmt.Print(s)
 | 
						|
}
 | 
						|
 | 
						|
type EncodingT struct {
 | 
						|
	Foo int
 | 
						|
}
 | 
						|
 | 
						|
type RecursiveStruct struct {
 | 
						|
	*RecursiveStruct
 | 
						|
	list []RecursiveStruct
 | 
						|
}
 | 
						|
 | 
						|
// This could crash or hang if we don't deal with loops.
 | 
						|
var _ = reflect.TypeOf(RecursiveStruct{})
 | 
						|
 | 
						|
type IndirectReflection struct {
 | 
						|
	ReflectionField string
 | 
						|
}
 | 
						|
 | 
						|
func indirectReflection(v interface{}) {
 | 
						|
	fmt.Println(reflect.TypeOf(v).Field(0).Name)
 | 
						|
}
 | 
						|
 | 
						|
type FmtType struct {
 | 
						|
	FmtTypeField int
 | 
						|
}
 | 
						|
 | 
						|
-- importedpkg/imported.go --
 | 
						|
package importedpkg
 | 
						|
 | 
						|
import (
 | 
						|
	"reflect"
 | 
						|
 | 
						|
	"test/main/importedpkg/indirect"
 | 
						|
	"test/main/importedpkg2"
 | 
						|
)
 | 
						|
 | 
						|
type ReflectTypeOf int
 | 
						|
 | 
						|
var _ = reflect.TypeOf(ReflectTypeOf(0))
 | 
						|
 | 
						|
type ReflectTypeOfIndirect int
 | 
						|
 | 
						|
var _ = reflect.TypeOf(new([]*ReflectTypeOfIndirect))
 | 
						|
 | 
						|
type ReflectValueOf struct {
 | 
						|
	ExportedField string
 | 
						|
 | 
						|
	unexportedField string
 | 
						|
}
 | 
						|
 | 
						|
func (r *ReflectValueOf) ExportedMethodName() string { return "method: " + r.ExportedField }
 | 
						|
 | 
						|
var ReflectValueOfVar = ReflectValueOf{ExportedField: "abc"}
 | 
						|
 | 
						|
var _ = reflect.TypeOf(ReflectValueOfVar)
 | 
						|
 | 
						|
type ReflectInDefined struct {
 | 
						|
	ExportedField2 int
 | 
						|
 | 
						|
	unexportedField2 int
 | 
						|
 | 
						|
	importedpkg2.ReflectInSiblingImport
 | 
						|
}
 | 
						|
 | 
						|
var ReflectInDefinedVar = ReflectInDefined{ExportedField2: 9000}
 | 
						|
 | 
						|
var _ = reflect.TypeOf(ReflectInDefinedVar)
 | 
						|
 | 
						|
var _ = reflect.TypeOf([]*struct{EmbeddingOuter}{})
 | 
						|
 | 
						|
type EmbeddingOuter struct {
 | 
						|
	EmbeddingInner
 | 
						|
	Anon struct {
 | 
						|
		AnonField int
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type EmbeddingInner struct {
 | 
						|
	InnerField int
 | 
						|
}
 | 
						|
 | 
						|
type UnnamedWithDownstreamReflect = struct {
 | 
						|
	DownstreamObfuscated string
 | 
						|
}
 | 
						|
 | 
						|
type (
 | 
						|
	AliasIndirectNamedWithReflect = indirect.IndirectNamedWithReflect
 | 
						|
	AliasIndirectNamedWithoutReflect = indirect.IndirectNamedWithoutReflect
 | 
						|
)
 | 
						|
 | 
						|
var _ = reflect.TypeOf(ReflectEmbeddingAlias{})
 | 
						|
 | 
						|
type ReflectEmbeddingAlias struct {
 | 
						|
	ReflectEmbeddedAlias
 | 
						|
}
 | 
						|
 | 
						|
type ReflectEmbeddedAlias = ReflectEmbeddingNamed
 | 
						|
 | 
						|
type ReflectEmbeddingNamed struct{}
 | 
						|
 | 
						|
-- importedpkg2/imported2.go --
 | 
						|
package importedpkg2
 | 
						|
 | 
						|
type ReflectInSiblingImport struct {
 | 
						|
	SiblingObfuscated string
 | 
						|
}
 | 
						|
 | 
						|
-- importedpkg/indirect/indirect.go --
 | 
						|
package indirect
 | 
						|
 | 
						|
import "reflect"
 | 
						|
 | 
						|
var _ = reflect.TypeOf(IndirectNamedWithReflect{})
 | 
						|
 | 
						|
type IndirectNamedWithReflect struct {
 | 
						|
	IndirectUnobfuscated string
 | 
						|
}
 | 
						|
 | 
						|
type IndirectNamedWithoutReflect struct {
 | 
						|
	IndirectObfuscated string
 | 
						|
}
 | 
						|
 | 
						|
-- main.stdout --
 | 
						|
9000
 | 
						|
{5 0 {}}
 | 
						|
ReflectTypeOf
 | 
						|
ReflectTypeOfIndirect
 | 
						|
ReflectValueOf{ExportedField:"abc", unexportedField:""}
 | 
						|
[method: abc]
 | 
						|
{"Foo":3}
 | 
						|
Hello Dave.
 | 
						|
{"InnerField":3,"Anon":{"AnonField":0}}
 | 
						|
{downstream}
 | 
						|
{sibling}
 | 
						|
{{indirect-with} {indirect-without} {}}
 | 
						|
IndirectNamedWithReflect{IndirectUnobfuscated:"indirect-with"}
 | 
						|
ReflectionField
 | 
						|
{0}
 |