From 2b26183253550fb95b094ba3bf8402619235651f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Wed, 18 Nov 2020 12:23:47 +0000 Subject: [PATCH] reduce the amount of code to handle compiler directives (#199) First, we don't need the nameSpecialDirectives list as a separate thing. cgo types aren't obfuscated anymore, so the only item in that list that made a difference in the tests was go:linkname, which we'll overhaul soon. For now, keep its code around. Second, processDetachedDirectives can be replaced by just seven lines. Third, we don't need to separate build tag directives from the rest of the detached directives. Their relative order (with other comments) does not matater. Fourth and last, ranging over a nil slice is a no-op, so a nil check around a slice range is unnecessary. This is some prep work to make the patch to support go:linkname smaller and easier to review. --- line_obfuscator.go | 64 +++++++++++++++------------------------------- main.go | 29 +++++++++++---------- 2 files changed, 35 insertions(+), 58 deletions(-) diff --git a/line_obfuscator.go b/line_obfuscator.go index 01ce0eb..4972a98 100644 --- a/line_obfuscator.go +++ b/line_obfuscator.go @@ -16,23 +16,20 @@ import ( // Source: https://go.googlesource.com/go/+/refs/heads/master/src/cmd/compile/internal/syntax/parser_test.go#229 const PosMin = 1 -const buildTagPrefix = "// +build" - -// Source: https://go.googlesource.com/go/+/refs/heads/master/src/cmd/compile/internal/gc/noder.go#1493 -var nameSpecialDirectives = []string{ +// detachedDirectives is a list of Go compiler directives which don't need to go +// right next to a Go declaration. Unlike all other detached comments, these +// need to be kept around as they alter compiler behavior. +var detachedDirectives = []string{ + "// +build", "//go:linkname", - + "//go:cgo_ldflag", + "//go:cgo_dynamic_linker", "//go:cgo_export_static", "//go:cgo_export_dynamic", "//go:cgo_import_static", "//go:cgo_import_dynamic", } -var specialDirectives = append([]string{ - "//go:cgo_ldflag", - "//go:cgo_dynamic_linker", -}, nameSpecialDirectives...) - func isDirective(text string, directives []string) bool { for _, prefix := range directives { if strings.HasPrefix(text, prefix) { @@ -42,8 +39,10 @@ func isDirective(text string, directives []string) bool { return false } +// TODO(mvdan): replace getLocalName with proper support for go:linkname + func getLocalName(text string) (string, bool) { - if !isDirective(text, nameSpecialDirectives) { + if !strings.HasPrefix(text, "//go:linkname") { return "", false } parts := strings.Fields(text) @@ -76,7 +75,7 @@ func clearCommentGroup(group *ast.CommentGroup) *ast.CommentGroup { var comments []*ast.Comment for _, comment := range group.List { - if strings.HasPrefix(comment.Text, "//go:") && !isDirective(comment.Text, specialDirectives) { + if strings.HasPrefix(comment.Text, "//go:") { comments = append(comments, &ast.Comment{Text: comment.Text}) } } @@ -110,45 +109,22 @@ func clearNodeComments(node ast.Node) { } } -// processDetachedDire collects all not attached to declarations comments and build tags -// It returns detached comments and local name blacklist -func processDetachedDirectives(commentGroups []*ast.CommentGroup) (detachedComments, localNameBlacklist []string) { - var buildTags []string - var specialComments []string - for _, commentGroup := range commentGroups { - for _, comment := range commentGroup.List { - if strings.HasPrefix(comment.Text, buildTagPrefix) { - buildTags = append(buildTags, comment.Text) - continue - } - - if !isDirective(comment.Text, specialDirectives) { - continue - } - - specialComments = append(specialComments, comment.Text) - if localName, ok := getLocalName(comment.Text); ok { - localNameBlacklist = append(localNameBlacklist, localName) - } - } - } - - detachedComments = append(detachedComments, buildTags...) - detachedComments = append(detachedComments, specialComments...) - detachedComments = append(detachedComments, "") - return detachedComments, localNameBlacklist -} - // transformLineInfo removes the comment except go directives and build tags. Converts comments to the node view. // It returns comments not attached to declarations and names of declarations which cannot be renamed. -func transformLineInfo(file *ast.File, cgoFile bool) (detachedComments, localNameBlacklist []string, f *ast.File) { +func transformLineInfo(file *ast.File, cgoFile bool) (detachedComments []string, f *ast.File) { prefix := "" if cgoFile { prefix = "_cgo_" } // Save build tags and add file name leak protection - detachedComments, localNameBlacklist = processDetachedDirectives(file.Comments) + for _, group := range file.Comments { + for _, comment := range group.List { + if isDirective(comment.Text, detachedDirectives) { + detachedComments = append(detachedComments, comment.Text) + } + } + } detachedComments = append(detachedComments, "", "//line "+prefix+":1") file.Comments = nil @@ -174,5 +150,5 @@ func transformLineInfo(file *ast.File, cgoFile bool) (detachedComments, localNam return true } - return detachedComments, localNameBlacklist, astutil.Apply(file, pre, nil).(*ast.File) + return detachedComments, astutil.Apply(file, pre, nil).(*ast.File) } diff --git a/main.go b/main.go index 13a3dc1..10f7526 100644 --- a/main.go +++ b/main.go @@ -438,17 +438,20 @@ func transformCompile(args []string) ([]string, error) { detachedComments := make([][]string, len(files)) for i, file := range files { - name := filepath.Base(filepath.Clean(paths[i])) - cgoFile := strings.HasPrefix(name, "_cgo_") - fileDetachedComments, localNameBlacklist, file := transformLineInfo(file, cgoFile) - for _, name := range localNameBlacklist { - obj := tf.pkg.Scope().Lookup(name) - if obj != nil { - tf.blacklist[obj] = struct{}{} + for _, group := range file.Comments { + for _, comment := range group.List { + if name, _ := getLocalName(comment.Text); name != "" { + obj := tf.pkg.Scope().Lookup(name) + if obj != nil { + tf.blacklist[obj] = struct{}{} + } + } } } - detachedComments[i] = fileDetachedComments - files[i] = file + + name := filepath.Base(filepath.Clean(paths[i])) + cgoFile := strings.HasPrefix(name, "_cgo_") + detachedComments[i], files[i] = transformLineInfo(file, cgoFile) } obfSrcArchive := &bytes.Buffer{} @@ -505,11 +508,9 @@ func transformCompile(args []string) ([]string, error) { printWriter := io.MultiWriter(tempFile, obfSrc) fileDetachedComments := detachedComments[i] - if len(fileDetachedComments) > 0 { - for _, comment := range fileDetachedComments { - if _, err = printWriter.Write([]byte(comment + "\n")); err != nil { - return nil, err - } + for _, comment := range fileDetachedComments { + if _, err := printWriter.Write([]byte(comment + "\n")); err != nil { + return nil, err } } if err := printConfig.Fprint(printWriter, fset, file); err != nil {