diff options
author | Ayke van Laethem <[email protected]> | 2021-06-02 13:59:38 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2021-06-15 14:36:54 +0200 |
commit | 3a458ec75ca03bbe13c36afded6f59af3e772fbf (patch) | |
tree | 02c5d7d83be4e4f0788ecae02d02046bc9ae30a4 | |
parent | 77647970613e6f4115c93521342c891aa2bba02c (diff) | |
download | tinygo-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.go | 30 |
1 files changed, 15 insertions, 15 deletions
@@ -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} } |