skip literals used in constant expressions

Fixes #39.
pull/51/head
lu4p 4 years ago committed by GitHub
parent c9bc7bac3b
commit f1bf6f91ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1
.gitignore vendored

@ -1 +1,2 @@
/garble
/test

@ -386,8 +386,10 @@ func transformCompile(args []string) ([]string, error) {
return nil, fmt.Errorf("typecheck error: %v", err)
}
blacklist := buildBlacklist(files, info, pkg)
if envGarbleLiterals {
files = obfuscateLiterals(files, info)
files = obfuscateLiterals(files, info, blacklist)
// ast changed so we need to typecheck again
pkg, err = origTypesConfig.Check(pkgPath, fset, files, info)
if err != nil {
@ -410,8 +412,6 @@ func transformCompile(args []string) ([]string, error) {
// log.Println(flags)
args = flags
blacklist := buildBlacklist(files, info, pkg)
pkgDebugDir := ""
if envGarbleDebugDir != "" {
osPkgPath := filepath.FromSlash(pkgPath)
@ -665,6 +665,10 @@ func buildBlacklist(files []*ast.File, info *types.Info, pkg *types.Package) map
}
}
visit := func(node ast.Node) bool {
if envGarbleLiterals {
constBlacklist(node, info, blacklist)
}
if node == nil {
if level == reflectCallLevel {
reflectCallLevel = -1

@ -43,7 +43,7 @@ func containsTypeDefStr(expr ast.Expr, info *types.Info) bool {
return false
}
func obfuscateLiterals(files []*ast.File, info *types.Info) []*ast.File {
func obfuscateLiterals(files []*ast.File, info *types.Info, blacklist map[types.Object]struct{}) []*ast.File {
pre := func(cursor *astutil.Cursor) bool {
switch x := cursor.Node().(type) {
case *ast.ValueSpec:
@ -91,6 +91,15 @@ func obfuscateLiterals(files []*ast.File, info *types.Info) []*ast.File {
return false
}
for _, name := range spec.Names {
obj := info.ObjectOf(name)
// The object itself is blacklisted, e.g. a value that needs to be constant
if _, ok := blacklist[obj]; ok {
return false
}
}
for _, val := range spec.Values {
if v, ok := val.(*ast.BasicLit); !ok || v.Kind != token.STRING {
return false // skip the block if it contains non basic literals
@ -306,3 +315,49 @@ func keyStmt(key []byte) *ast.GenDecl {
}},
}
}
func constBlacklist(node ast.Node, info *types.Info, blacklist map[types.Object]struct{}) {
blacklistObjects := func(node ast.Node) bool {
ident, ok := node.(*ast.Ident)
if !ok {
return true
}
obj := info.ObjectOf(ident)
blacklist[obj] = struct{}{}
return true
}
switch x := node.(type) {
// in a slice or array composite literal all explicit keys must be constant representable
case *ast.CompositeLit:
if _, ok := x.Type.(*ast.ArrayType); !ok {
break
}
for _, elt := range x.Elts {
if kv, ok := elt.(*ast.KeyValueExpr); ok {
ast.Inspect(kv.Key, blacklistObjects)
}
}
// in an array type the length must be a constant representable
case *ast.ArrayType:
if x.Len != nil {
ast.Inspect(x.Len, blacklistObjects)
}
// in a const declaration all values must be constant representable
case *ast.GenDecl:
if x.Tok != token.CONST {
break
}
for _, spec := range x.Specs {
spec := spec.(*ast.ValueSpec)
for _, val := range spec.Values {
ast.Inspect(val, blacklistObjects)
}
}
}
}

@ -78,6 +78,7 @@ func main() {
println(skip1, skip2)
println(i, foo, bar)
typedTest()
constantTest()
}
type stringType string
@ -98,7 +99,7 @@ func typedTest() {
println(skipTypedConst, skipTypedVar, skipTypedVarAssign)
y := stringTypeStruct{
str: "stringTypeField String", // obfuscate
str: "stringTypeField String", // obfuscate
strType: "stringTypeField strType", // skip
}
println(y.str, y.strType)
@ -120,6 +121,37 @@ func typedTest() {
println(stringTypeFunc("stringType func param")) // skip
}
// constantTest tests that string constants which need to be constant are skipped
func constantTest() {
const a = "foo" // skip
const length = len(a)
const b = "bar" // skip
type T [len(b)]byte
const c = "foo" // skip
var _ [len(c)]byte
const d = "foo" // skip
var arr = [5]string{len(d): "foo"}
for _, elm := range arr {
if elm != "" {
println(elm)
}
}
const e = "foo" // skip
var slice = []string{len(e): "foo"}
for _, elm := range slice {
if elm != "" {
println(elm)
}
}
const f = "foo" // skip
const i = length + len(f)
}
func stringTypeFunc(s stringType) stringType {
println(s)
return "stringType return" // skip
@ -141,4 +173,6 @@ skip typed const skip typed var skip typed var assign
stringTypeField String stringTypeField strType
stringType lambda func return
stringType func param
stringType return
stringType return
foo
foo

Loading…
Cancel
Save