Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflection with module #403

Closed
CrookedCrane opened this issue Oct 1, 2021 · 4 comments
Closed

Reflection with module #403

CrookedCrane opened this issue Oct 1, 2021 · 4 comments

Comments

@CrookedCrane
Copy link

What version of Garble and Go are you using?

$ garble version
0.4.0
$ go version
go1.17 windows/amd64

What environment are you running Garble on?

go env Output
$ go env
set GO111MODULE=on
set GOARCH=amd64
set GOBIN=
set GOCACHE=C:\Users\CrookedCrane\AppData\Local\go-build
set GOENV=C:\Users\CrookedCrane\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\CrookedCrane\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\CrookedCrane\go
set GOPRIVATE=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Users\CrookedCrane\sdk\go1.17
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Users\CrookedCrane\sdk\go1.17\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.17
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=C:\Users\CrookedCrane\sdk\go1.17\src\main\go.mod
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\CrookedCrane\AppData\Local\Temp\go-build3937438513=/tmp/go-build -gno-record-gcc-switches

What did you do?

run binary built from

main.go
package main

import (
"fmt"
struc "main/structure"
"reflect"
)

func GetMyStructInformation(input interface{}) (strOut string, numOut int) {
ptr := reflect.ValueOf(input)
value := reflect.Indirect(ptr)
strOut = value.FieldByName("MyString").String()
numOut = int(value.FieldByName("MyNumber").Int())
return
}

func main() {
myItem := &struc.MyStruct{MyString: "This is a string", MyNumber: 1000}
_ = reflect.ValueOf(myItem)
str, num := GetMyStructInformation(myItem)
fmt.Println("The string is: ", str)
fmt.Println("The number is: ", num)
}

struct.go
package structure

type MyStruct struct {
MyString string
MyNumber int
}

project structure
main
|_____structure
         |_____struct.go
|_____go.mod
|_____main.go

What did you expect to see?

The string is:  This is a string
The number is:  1000

What did you see instead?

panic: reflect: call of reflect.Value.Int on zero Value

goroutine 1 [running]:
reflect.Value.Int(...)
        reflect/value.go:1334
main.GetMyStructInformation({0x152640, 0xc000004078})
        IgTaaCXu.go:1 +0x1a5
main.main()
        qB1_pSpU.go:1 +0xad

I noticed in the source code to ignore objects for obfuscation they must be declared and their reflection usage must be in the same package, and indeed when I move MyStruct's declaration into main.go it gives the inteded output. Since my project relies on a lot of plugins and reflection, can there be a way to make it happen cross packages?

@mvdan
Copy link
Member

mvdan commented Oct 1, 2021

For better or worse, Go builds one package at a time, and so we obfuscate one package at a time as well.

When we obfuscate main/structure, we have no knowledge of uses of reflection yet.

The alternative would be to analyze the entire package graph before starting the build. This would be very inefficient for large builds though, and would affect our ability to rely on the build cache for speed. So it doesn't feel like the right decision.

@CrookedCrane
Copy link
Author

So for this particular case (heavy use of cross package reflection), can I create a sort of objects-to-ignore list, like knownReflectAPIs but for objects to tell garble to ignore them?

@mvdan
Copy link
Member

mvdan commented Oct 1, 2021

The easiest way is to do something like:

package structure

// MyStruct is used via reflection in other packages. Let garble know.
var _ = reflect.TypeOf(MyStruct{})

type MyStruct struct {
    [...]
}

It's also nice because you annotate that information right next to the type definition.

mvdan added a commit to mvdan/garble-fork that referenced this issue Oct 22, 2021
We recently improved the automatic detection of reflection.
However, note that a hint may still be needed in some cases,
in particular when the reflection usage happens in a downstream package.

Keep making that suggestion.
Also mention that we obfuscate one package at a time.

I've also written down burrowers#406 with more ideas on how we could polish this
rough edge for end users in the future.

Fixes burrowers#403.
@mvdan
Copy link
Member

mvdan commented Oct 22, 2021

#409 documents the suggestion above again.

#406 is about improving these edge cases automatically in the future.

@lu4p lu4p closed this as completed in e7232da Oct 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants