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.
garble/testdata/script/syntax.txtar

278 lines
5.3 KiB
Plaintext

exec garble build
exec ./main$exe
cmp stderr main.stderr
! binsubstr main$exe 'localName' 'globalConst' 'globalVar' 'globalType' 'valuable information' 'private.source' 'remoteIntReturn' 'intReturn' 'neverInlined'
[short] stop # no need to verify this with -short
# Check that the program works as expected without garble.
go build
exec ./main$exe
cmp stderr main.stderr
binsubstr main$exe 'globalVar' # 'globalType' matches on some, but not all, platforms
! binsubstr main$exe 'localName' 'globalConst' 'remoteIntReturn' 'intReturn'
-- extra/go.mod --
module private.source/extra
go 1.22
-- extra/extra.go --
package extra
func Func() string {
return "This is a separate module to obfuscate."
}
-- go.mod --
module test/main
go 1.22
// We include an extra module to obfuscate, included in the same original source
// code via a replace directive.
require private.source/extra v0.0.0-00010101000000-000000000000
replace private.source/extra => ./extra
-- main.go --
package main
import (
"go/ast"
"runtime"
"private.source/extra"
"test/main/sub"
)
// This comment contains valuable information. Ensure it's not in the final binary.
var V any
type T struct {
ast.Node
*ast.Ident
}
type Embedded int
type Embedding struct {
Embedded
}
type embedded int
type embedding struct {
embedded
}
// embedded fields whose type is in the universe scope used to crash garble
type EmbeddingUniverseScope struct {
error
int
string
}
// TODO: test that go:noinline still works without using debugdir
func ensureInlined(wantInlined bool) {
pc := make([]uintptr, 1)
// We skip two caller frames; runtime.Callers, and ensureInlined.
// This way, the frame we get is our caller, like neverInlined.
n := runtime.Callers(2, pc)
if n == 0 {
panic("got zero callers?")
}
pc = pc[:n]
frames := runtime.CallersFrames(pc)
frame, _ := frames.Next()
gotInlined := frame.Func == nil
if wantInlined && !gotInlined {
panic("caller should be inlined but wasn't")
} else if !wantInlined && gotInlined {
panic("caller shouldn't be inlined but was")
}
}
//go:noinline
func neverInlined() {
ensureInlined(false)
println("This func is never inlined.")
}
func alwaysInlined() {
ensureInlined(true)
println("This func is always inlined.")
}
type EmbeddingOuter struct {
EmbeddingInner
}
type EmbeddingInner struct {
SomeField int
}
func main() {
switch V := V.(type) {
case int:
var _ int = V
case nil:
println("nil case")
}
scopesTest()
println(extra.Func())
sub.Test()
neverInlined()
alwaysInlined()
_ = sub.EmbeddingExternalForeignAlias{
ExternalForeignAlias: nil,
Reader: nil,
}
var emb sub.EmbeddingAlias
_ = emb.EmbeddedAlias
_ = emb.Foo
_ = emb.EmbeddedAliasSameName
_ = emb.Bar
}
-- scopes.go --
package main
const globalConst = 1
type globalType int
var (
globalVar = 1
globalVarTyped globalType = 1
)
func scopesTest() {
println(globalVar, globalConst, globalVarTyped)
const localNameConst = 1
localNameShort := 4
type localNameType int
var (
localNameVar = 5
localNameTypeVar localNameType = 1
)
println(localNameConst, localNameShort, localNameVar, localNameTypeVar, input("input"))
}
func input(localNameParam string) (localNameReturn string) { return localNameParam }
-- sub/names.go --
package sub
import (
"io"
"test/main/external"
)
var someGlobalVar0 = "0"
var someGlobalVar1 = "1"
var someGlobalVar2 = "2"
func Test() {
var A, B, C, D, E string
noop(A, B, C, D, E)
if someGlobalVar0 != "0" || someGlobalVar1 != "1" || someGlobalVar2 != "2"{
panic("name collision detected")
}
}
func noop(...any) {}
// Funcs that almost look like test funcs used to make garble panic.
func TestFoo(s string) {}
func TestBar(*struct{}) {}
// If we obfuscate the alias name, we must obfuscate its use here too.
type EmbeddingAlias struct {
EmbeddedAlias
EmbeddedAliasSameName
}
type EmbeddedAlias = external.NamedExternal
type EmbeddedAliasSameName = external.EmbeddedAliasSameName
// We obfuscate the name foreignAlias, but not the name Reader,
// as it's not declared in a private package.
// Both names must do the same when used as struct fields,
// both in the struct declaration and in the composite literal below.
type embeddingForeignAlias struct {
foreignAlias
io.Reader
}
type foreignAlias = io.Reader
var _ = embeddingForeignAlias{
foreignAlias: nil,
Reader: nil,
}
// Similar to embeddingForeignAlias,
// but the alias is declared in a dependency,
// and this type is used in a dependent.
type EmbeddingExternalForeignAlias struct {
external.ExternalForeignAlias
io.Reader
}
// Like the cases above,
// but this time the alias doesn't rename its destination named type.
// We can't tell this apart from "struct { io.Reader }" at the type info level.
// It's fine to ignore the alias entirely, in this case.
type embeddingAliasSameName struct {
external.Reader
}
var _ = embeddingAliasSameName{
Reader: nil,
}
type embeddingBuiltinAlias struct {
byte
}
var _ = embeddingBuiltinAlias{3}
var _ = embeddingBuiltinAlias{byte: 3}
-- external/external.go --
package external
import "io"
type NamedExternal struct {
Foo int
}
type EmbeddedAliasSameName struct {
Bar int
}
type ExternalForeignAlias = io.Reader
type Reader = io.Reader
-- main.stderr --
nil case
1 1 1
1 4 5 1 input
This is a separate module to obfuscate.
This func is never inlined.
This func is always inlined.