always require one argument for "reverse"

The "reverse" command had many levels of optional arguments:

	garble [garble flags] reverse [build flags] [package] [files]

This was pretty confusing,
and could easily lead to people running the command incorrectly:

	# note that output.txt isn't a Go package!
	garble reverse output.txt

Moreover, it made the handling of Go build flags pretty confusing.
Should the command below work?

	garble reverse -tags=mytag

It also made it easy to not notice that one must supply the main package
to properly reverse some text that it produced, like a panic message.
With the package path being implicit,
one could mistakenly provide the wrong package by running garble
in a directory containing a different package.

See #394.
pull/398/head
Daniel Martí 4 years ago committed by lu4p
parent 08ec70e9a9
commit 1682e8ee10

@ -76,10 +76,12 @@ Similarly, to combine garble flags and Go build flags:
The following commands are supported: The following commands are supported:
build [packages] replace "go build" build replace "go build"
test [packages] replace "go test" test replace "go test"
version print Garble version version print Garble version
reverse [files] de-obfuscate output such as stack traces reverse de-obfuscate output such as stack traces
To learn more about a command, run "garble help <command>".
garble accepts the following flags before a command: garble accepts the following flags before a command:
@ -307,14 +309,19 @@ func mainErr(args []string) error {
// If we recognize an argument, we're not running within -toolexec. // If we recognize an argument, we're not running within -toolexec.
switch command, args := args[0], args[1:]; command { switch command, args := args[0], args[1:]; command {
case "help": case "help":
if len(args) > 0 { if hasHelpFlag(args) || len(args) > 1 {
return fmt.Errorf("the help command does not take arguments") fmt.Fprintf(os.Stderr, "usage: garble help [command]\n")
return errJustExit(2)
}
if len(args) == 1 {
return mainErr([]string{args[0], "-h"})
} }
usage() usage()
return errJustExit(2) return errJustExit(2)
case "version": case "version":
if len(args) > 0 { if hasHelpFlag(args) || len(args) > 0 {
return fmt.Errorf("the version command does not take arguments") fmt.Fprintf(os.Stderr, "usage: garble version\n")
return errJustExit(2)
} }
// don't overwrite the version if it was set by -ldflags=-X // don't overwrite the version if it was set by -ldflags=-X
if info, ok := debug.ReadBuildInfo(); ok && version == "(devel)" { if info, ok := debug.ReadBuildInfo(); ok && version == "(devel)" {
@ -1023,8 +1030,10 @@ func processImportCfg(flags []string) (newImportCfg string, _ error) {
return newCfg.Name(), nil return newCfg.Name(), nil
} }
type funcFullName = string type (
type reflectParameterPosition = int funcFullName = string
reflectParameterPosition = int
)
// knownReflectAPIs is a static record of what std APIs use reflection on their // knownReflectAPIs is a static record of what std APIs use reflection on their
// parameters, so we can avoid obfuscating types used with them. // parameters, so we can avoid obfuscating types used with them.

@ -19,24 +19,29 @@ import (
// commandReverse implements "garble reverse". // commandReverse implements "garble reverse".
func commandReverse(args []string) error { func commandReverse(args []string) error {
flags, args := splitFlagsFromArgs(args) flags, args := splitFlagsFromArgs(args)
if hasHelpFlag(flags) { if hasHelpFlag(flags) || len(args) == 0 {
fmt.Fprintf(os.Stderr, "usage: garble [garble flags] reverse [files]\n") fmt.Fprintf(os.Stderr, `
return errJustExit(2) usage: garble [garble flags] reverse [build flags] package [files]
}
For example, after building an obfuscated program as follows:
mainPkg := "." garble -literals build -tags=mytag ./cmd/mycmd
if len(args) > 0 {
mainPkg = args[0] One can reverse a captured panic stack trace as follows:
args = args[1:]
garble -literals reverse -tags=mytag ./cmd/mycmd panic-output.txt
`[1:])
return errJustExit(2)
} }
pkg, args := args[0], args[1:]
listArgs := []string{ listArgs := []string{
"-json", "-json",
"-deps", "-deps",
"-export", "-export",
} }
listArgs = append(listArgs, flags...) listArgs = append(listArgs, flags...)
listArgs = append(listArgs, mainPkg) listArgs = append(listArgs, pkg)
// TODO: We most likely no longer need this "list -toolexec" call, since // TODO: We most likely no longer need this "list -toolexec" call, since
// we use the original build IDs. // we use the original build IDs.
if _, err := toolexecCmd("list", listArgs); err != nil { if _, err := toolexecCmd("list", listArgs); err != nil {

@ -15,7 +15,12 @@ stderr 'garble \[garble flags\] command'
! stdout . ! stdout .
! garble help foo bar ! garble help foo bar
stderr 'does not take arguments' stderr 'usage: garble help'
! stderr 'Garble obfuscates Go code'
! stdout .
! garble help -h
stderr 'usage: garble help'
! stdout . ! stdout .
! garble build -h ! garble build -h
@ -35,7 +40,12 @@ stderr 'Run .go help test.'
! stdout . ! stdout .
! garble reverse -h ! garble reverse -h
stderr 'garble \[garble flags\] reverse \[files\]' stderr 'garble \[garble flags\] reverse \[build flags\] package \[files\]'
! stderr 'usage: go '
! stdout .
! garble help reverse
stderr 'garble \[garble flags\] reverse \[build flags\] package \[files\]'
! stderr 'usage: go ' ! stderr 'usage: go '
! stdout . ! stdout .
@ -59,10 +69,10 @@ garble version
stdout 'devel|^v0' stdout 'devel|^v0'
! garble version -flag ! garble version -flag
stderr 'does not take arguments' stderr 'usage: garble version'
! garble version arg ! garble version arg
stderr 'does not take arguments' stderr 'usage: garble version'
# We need a dummy module for "garble build -badflag". # We need a dummy module for "garble build -badflag".
-- go.mod -- -- go.mod --

@ -1,7 +1,7 @@
env GOPRIVATE=test/main env GOPRIVATE=test/main
# Unknown build flags should result in errors. # Unknown build flags should result in errors.
! garble reverse -badflag ! garble reverse -badflag=foo .
stderr 'flag provided but not defined' stderr 'flag provided but not defined'
garble build garble build
@ -16,7 +16,7 @@ grep 'goroutine 1 \[running\]' main.stderr
! grep 'ExportedLib(Type|Field)|unexportedMainFunc|test/main|main\.go|lib\.go' main.stderr ! grep 'ExportedLib(Type|Field)|unexportedMainFunc|test/main|main\.go|lib\.go' main.stderr
stdin main.stderr stdin main.stderr
garble reverse garble reverse .
cmp stdout reverse.stdout cmp stdout reverse.stdout
! garble build ./build-error ! garble build ./build-error
@ -39,12 +39,12 @@ exec ./main
cp stderr main-literals.stderr cp stderr main-literals.stderr
stdin main-literals.stderr stdin main-literals.stderr
garble -literals reverse garble -literals reverse .
cmp stdout reverse.stdout cmp stdout reverse.stdout
# Reversing a -literals output without the flag should fail. # Reversing a -literals output without the flag should fail.
stdin main-literals.stderr stdin main-literals.stderr
! garble reverse ! garble reverse .
cmp stdout main-literals.stderr cmp stdout main-literals.stderr
-- go.mod -- -- go.mod --

Loading…
Cancel
Save