aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-06-02 13:59:38 +0200
committerRon Evans <[email protected]>2021-06-15 14:36:54 +0200
commit3a458ec75ca03bbe13c36afded6f59af3e772fbf (patch)
tree02c5d7d83be4e4f0788ecae02d02046bc9ae30a4
parent77647970613e6f4115c93521342c891aa2bba02c (diff)
downloadtinygo-3a458ec75ca03bbe13c36afded6f59af3e772fbf.tar.gz
tinygo-3a458ec75ca03bbe13c36afded6f59af3e772fbf.zip
main: make flash-command portable and safer to use
Previously, flash-command would assume it could execute a command straight via /bin/sh, at least on non-Windows systems. Otherwise it would just split the command using `strings.Split`. This is all a bit hacky, so I've replaced it with a proper solution: splitting the command _before_ substituting various paths using a real shell splitter (shlex.Split, from Google). This solves a few things: * It guards against special characters in path names. This can be an issue on Windows where the temporary path may contain spaces (this is uncommon on POSIX systems). * It is more portable, by disallowing the use of a shell. That way, it doesn't differentiate between Windows and non-Windows anymore.
-rw-r--r--main.go30
1 files changed, 15 insertions, 15 deletions
diff --git a/main.go b/main.go
index c85feb697..c3cca64f7 100644
--- a/main.go
+++ b/main.go
@@ -314,8 +314,10 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
case "", "command":
// Create the command.
flashCmd := config.Target.FlashCommand
- fileToken := "{" + fileExt[1:] + "}"
- flashCmd = strings.ReplaceAll(flashCmd, fileToken, result.Binary)
+ flashCmdList, err := shlex.Split(flashCmd)
+ if err != nil {
+ return fmt.Errorf("could not parse flash command %#v: %w", flashCmd, err)
+ }
if strings.Contains(flashCmd, "{port}") {
var err error
@@ -325,25 +327,23 @@ func Flash(pkgName, port string, options *compileopts.Options) error {
}
}
- flashCmd = strings.ReplaceAll(flashCmd, "{port}", port)
+ // Fill in fields in the command template.
+ fileToken := "{" + fileExt[1:] + "}"
+ for i, arg := range flashCmdList {
+ arg = strings.ReplaceAll(arg, fileToken, result.Binary)
+ arg = strings.ReplaceAll(arg, "{port}", port)
+ flashCmdList[i] = arg
+ }
// Execute the command.
- var cmd *exec.Cmd
- switch runtime.GOOS {
- case "windows":
- command := strings.Split(flashCmd, " ")
- if len(command) < 2 {
- return errors.New("invalid flash command")
- }
- cmd = executeCommand(config.Options, command[0], command[1:]...)
- default:
- cmd = executeCommand(config.Options, "/bin/sh", "-c", flashCmd)
+ if len(flashCmdList) < 2 {
+ return fmt.Errorf("invalid flash command: %#v", flashCmd)
}
-
+ cmd := executeCommand(config.Options, flashCmdList[0], flashCmdList[1:]...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = goenv.Get("TINYGOROOT")
- err := cmd.Run()
+ err = cmd.Run()
if err != nil {
return &commandError{"failed to flash", result.Binary, err}
}