make -literals succeed on all of std

Two bugs were remaining which made the build with -literals of std fail.

First, we were ignoring too many objects in constant expressions,
including type names. This resulted in type names declared in
dependencies which were incorrectly not obfuscated in the current
package:

	# go/constant
	O1ku7TCe.go:1: undefined: alzLJ5Fd.Word
	b0ieEGVQ.go:1: undefined: alzLJ5Fd.Word
	LEpgYKdb.go:4: undefined: alzLJ5Fd.Word
	FkhHJCfm.go:1: undefined: alzLJ5Fd.Word

This edge case is easy to reproduce, so a test case is added to
literals.txt.

The second issue is trickier; in some packages like os/user, we would
get syntax errors because of comments printed out of place:

	../tip/os/user/getgrouplist_unix.go:35:130: syntax error: unexpected newline, expecting comma or )

This is a similar kind of error that we tried to fix with e2f06cce94. In
particular, it's fixed by also setting CallExpr.Rparen in withPos. We
also add many other missing Pos fields for good measure, even though
we're not sure they help just yet.

Unfortunately, all my attempts to minimize this into a reproducible
failure have failed. We can't just copy the failing file from os/user,
as it only builds on some OSs. It seems like it was the perfect mix of
cgo (which adds line directive comments) plus unlucky positioning of
literals.

For that last reason, as well as for ensuring that -literals works well
with a wide variety of software, we add a build of all of std with
-literals when not testing with -short. This is akin to what we do in
goprivate.txt, but with the -literals flag. This does make "go test"
more expensive, but also more thorough.

Fixes #285, hopefully for good this time.
pull/303/head
Daniel Martí 3 years ago committed by lu4p
parent e2f06cce94
commit 6b1a062c6f

@ -191,14 +191,21 @@ func withPos(node ast.Node, pos token.Pos) ast.Node {
node.ValuePos = pos node.ValuePos = pos
case *ast.Ident: case *ast.Ident:
node.NamePos = pos node.NamePos = pos
case *ast.StarExpr:
node.Star = pos
case *ast.CompositeLit: case *ast.CompositeLit:
node.Lbrace = pos node.Lbrace = pos
node.Rbrace = pos
case *ast.ArrayType: case *ast.ArrayType:
node.Lbrack = pos node.Lbrack = pos
case *ast.FuncType: case *ast.FuncType:
node.Func = pos node.Func = pos
case *ast.BinaryExpr:
node.OpPos = pos
case *ast.StarExpr:
node.Star = pos
case *ast.CallExpr:
node.Lparen = pos
node.Rparen = pos
case *ast.GenDecl: case *ast.GenDecl:
node.TokPos = pos node.TokPos = pos
case *ast.ReturnStmt: case *ast.ReturnStmt:
@ -207,8 +214,8 @@ func withPos(node ast.Node, pos token.Pos) ast.Node {
node.For = pos node.For = pos
case *ast.RangeStmt: case *ast.RangeStmt:
node.For = pos node.For = pos
case *ast.CallExpr: case *ast.BranchStmt:
node.Lparen = pos node.TokPos = pos
} }
return true return true
}) })
@ -278,8 +285,13 @@ func RecordUsedAsConstants(node ast.Node, info *types.Info, ignoreObj map[types.
return true return true
} }
// Only record *types.Const objects.
// Other objects, such as builtins or type names,
// must not be recorded as they would be false positives.
obj := info.ObjectOf(ident) obj := info.ObjectOf(ident)
ignoreObj[obj] = true if _, ok := obj.(*types.Const); ok {
ignoreObj[obj] = true
}
return true return true
} }

@ -27,15 +27,11 @@ binsubstr main$exe 'Lorem' 'dolor' 'second assign' 'First Line' 'Second Line' 'm
# seconds, it means we're trying to obfuscate them. # seconds, it means we're trying to obfuscate them.
generate-literals extra_literals.go generate-literals extra_literals.go
# Also check that the binary is different from previous builds. garble -literals -debugdir=debug1 build
rm main$exe
garble -literals -debugdir=debug1 -seed=8J+Ri/Cfh6fwn4e+ build
! bincmp main$exe main_old$exe
exec ./main$exe exec ./main$exe
cmp stderr main.stderr cmp stderr main.stderr
# Check obfuscators # Check obfuscators.
# Xor obfuscator. Detect a[i] = a[i] (^|-|+) b[i] # Xor obfuscator. Detect a[i] = a[i] (^|-|+) b[i]
grep '^\s+\w+\[\w+\] = \w+\[\w+\] [\^\-+] \w+$' debug1/test/main/extra_literals.go grep '^\s+\w+\[\w+\] = \w+\[\w+\] [\^\-+] \w+$' debug1/test/main/extra_literals.go
@ -53,6 +49,11 @@ grep '^\s+\w+ = .*\bappend\(\w+,(\s+\w+\[\d+\][\^\-+]\w+\[\d+\],?)+\)$' debug1/t
# XorSeed obfuscator. Detect type decFunc func(byte) decFunc # XorSeed obfuscator. Detect type decFunc func(byte) decFunc
grep '^\s+type \w+ func\(byte\) \w+$' debug1/test/main/extra_literals.go grep '^\s+type \w+ func\(byte\) \w+$' debug1/test/main/extra_literals.go
# Finally, sanity check that we can build all of std with -literals.
# Analogous to goprivate.txt.
env GOPRIVATE='*'
garble -literals build std
-- go.mod -- -- go.mod --
module test/main module test/main
@ -60,6 +61,8 @@ go 1.16
-- main.go -- -- main.go --
package main package main
import "test/main/imported"
type strucTest struct { type strucTest struct {
field string field string
anotherfield string anotherfield string
@ -203,6 +206,11 @@ func constantTest() {
const f = "foo" // skip const f = "foo" // skip
const i = length + len(f) const i = length + len(f)
println(length, i) println(length, i)
// We should still obfuscate ImportedType here.
// Otherwise, the build will fail,
// as the name was obfuscated in the original package.
const impType = imported.ImportedType(3)
} }
func byteTest() { func byteTest() {
@ -242,6 +250,10 @@ const (
iota0 uint8 = iota iota0 uint8 = iota
iota1 iota1
) )
-- imported/imported.go --
package imported
type ImportedType int
-- directives.go -- -- directives.go --
// If we misplace any of the directives below, // If we misplace any of the directives below,
// cmd/compile will complain with "misplaced compiler directive". // cmd/compile will complain with "misplaced compiler directive".

Loading…
Cancel
Save