From 79e500a2d30cc850b1a1437d7337a8079d119dc3 Mon Sep 17 00:00:00 2001 From: Matt Landis Date: Wed, 26 Aug 2020 12:45:11 -0400 Subject: [PATCH] tiltfile: add shlex.quote (#3720) --- go.mod | 1 + go.sum | 2 + internal/tiltfile/shlex/shlex.go | 30 ++++++++++ internal/tiltfile/shlex/shlex_test.go | 25 ++++++++ internal/tiltfile/tiltfile_state.go | 2 + .../github.com/alessio/shellescape/.gitignore | 24 ++++++++ .../alessio/shellescape/.travis.yml | 4 ++ vendor/github.com/alessio/shellescape/AUTHORS | 1 + vendor/github.com/alessio/shellescape/LICENSE | 21 +++++++ .../github.com/alessio/shellescape/README.md | 58 +++++++++++++++++++ vendor/github.com/alessio/shellescape/go.mod | 3 + .../alessio/shellescape/shellescape.go | 39 +++++++++++++ vendor/modules.txt | 3 + 13 files changed, 213 insertions(+) create mode 100644 internal/tiltfile/shlex/shlex.go create mode 100644 internal/tiltfile/shlex/shlex_test.go create mode 100644 vendor/github.com/alessio/shellescape/.gitignore create mode 100644 vendor/github.com/alessio/shellescape/.travis.yml create mode 100644 vendor/github.com/alessio/shellescape/AUTHORS create mode 100644 vendor/github.com/alessio/shellescape/LICENSE create mode 100644 vendor/github.com/alessio/shellescape/README.md create mode 100644 vendor/github.com/alessio/shellescape/go.mod create mode 100644 vendor/github.com/alessio/shellescape/shellescape.go diff --git a/go.mod b/go.mod index fc2cdc39b6..cee5e85ced 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.14 require ( github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d // indirect github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect + github.com/alessio/shellescape v1.2.2 github.com/bitly/go-hostpool v0.1.0 // indirect github.com/bitly/go-simplejson v0.5.0 // indirect github.com/blang/semver v3.5.1+incompatible diff --git a/go.sum b/go.sum index 6571ed1431..bd6f3bd935 100644 --- a/go.sum +++ b/go.sum @@ -51,6 +51,8 @@ github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0 github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alessio/shellescape v1.2.2 h1:8LnL+ncxhWT2TR00dfJRT25JWWrhkMZXneHVWnetDZg= +github.com/alessio/shellescape v1.2.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/benbjohnson/clock v1.0.0/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= diff --git a/internal/tiltfile/shlex/shlex.go b/internal/tiltfile/shlex/shlex.go new file mode 100644 index 0000000000..c79834237c --- /dev/null +++ b/internal/tiltfile/shlex/shlex.go @@ -0,0 +1,30 @@ +package shlex + +import ( + "go.starlark.net/starlark" + + "github.com/tilt-dev/tilt/internal/tiltfile/starkit" + + "github.com/alessio/shellescape" +) + +type Extension struct{} + +func NewExtension() Extension { + return Extension{} +} + +func (Extension) OnStart(env *starkit.Environment) error { + return env.AddBuiltin("shlex.quote", quote) +} + +func quote(thread *starlark.Thread, fn *starlark.Builtin, args starlark.Tuple, kwargs []starlark.Tuple) (starlark.Value, error) { + var s string + err := starkit.UnpackArgs(thread, fn.Name(), args, kwargs, + "name", &s) + if err != nil { + return nil, err + } + + return starlark.String(shellescape.Quote(s)), nil +} diff --git a/internal/tiltfile/shlex/shlex_test.go b/internal/tiltfile/shlex/shlex_test.go new file mode 100644 index 0000000000..318f312bb2 --- /dev/null +++ b/internal/tiltfile/shlex/shlex_test.go @@ -0,0 +1,25 @@ +package shlex + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/tilt-dev/tilt/internal/tiltfile/starkit" +) + +func TestQuote(t *testing.T) { + f := starkit.NewFixture(t, NewExtension()) + + f.File("Tiltfile", ` +s = shlex.quote("foo '$FOO'") +print(shlex.quote("foo '$FOO'")) + +`) + + _, err := f.ExecFile("Tiltfile") + require.NoError(t, err) + + require.Equal(t, `'foo '"'"'$FOO'"'"'' +`, f.PrintOutput()) +} diff --git a/internal/tiltfile/tiltfile_state.go b/internal/tiltfile/tiltfile_state.go index 2b6119b2ae..e849937233 100644 --- a/internal/tiltfile/tiltfile_state.go +++ b/internal/tiltfile/tiltfile_state.go @@ -29,6 +29,7 @@ import ( "github.com/tilt-dev/tilt/internal/tiltfile/k8scontext" "github.com/tilt-dev/tilt/internal/tiltfile/os" "github.com/tilt-dev/tilt/internal/tiltfile/secretsettings" + "github.com/tilt-dev/tilt/internal/tiltfile/shlex" "github.com/tilt-dev/tilt/internal/tiltfile/starkit" "github.com/tilt-dev/tilt/internal/tiltfile/starlarkstruct" "github.com/tilt-dev/tilt/internal/tiltfile/telemetry" @@ -200,6 +201,7 @@ func (s *tiltfileState) loadManifests(absFilename string, userConfigState model. updatesettings.NewExtension(), secretsettings.NewExtension(), encoding.NewExtension(), + shlex.NewExtension(), tiltextension.NewExtension(tiltextension.NewGithubFetcher(), tiltextension.NewLocalStore(filepath.Dir(absFilename))), ) if err != nil { diff --git a/vendor/github.com/alessio/shellescape/.gitignore b/vendor/github.com/alessio/shellescape/.gitignore new file mode 100644 index 0000000000..daf913b1b3 --- /dev/null +++ b/vendor/github.com/alessio/shellescape/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/vendor/github.com/alessio/shellescape/.travis.yml b/vendor/github.com/alessio/shellescape/.travis.yml new file mode 100644 index 0000000000..f5763c5aad --- /dev/null +++ b/vendor/github.com/alessio/shellescape/.travis.yml @@ -0,0 +1,4 @@ +language: go + +go: + - 1.14 diff --git a/vendor/github.com/alessio/shellescape/AUTHORS b/vendor/github.com/alessio/shellescape/AUTHORS new file mode 100644 index 0000000000..4a647a6f41 --- /dev/null +++ b/vendor/github.com/alessio/shellescape/AUTHORS @@ -0,0 +1 @@ +Alessio Treglia diff --git a/vendor/github.com/alessio/shellescape/LICENSE b/vendor/github.com/alessio/shellescape/LICENSE new file mode 100644 index 0000000000..9f760679f4 --- /dev/null +++ b/vendor/github.com/alessio/shellescape/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Alessio Treglia + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/alessio/shellescape/README.md b/vendor/github.com/alessio/shellescape/README.md new file mode 100644 index 0000000000..ce9e33f42c --- /dev/null +++ b/vendor/github.com/alessio/shellescape/README.md @@ -0,0 +1,58 @@ +[![GoDoc](https://godoc.org/github.com/alessio/shellescape?status.svg)](https://godoc.org/github.com/alessio/shellescape) +[![Travis-CI Status](https://api.travis-ci.org/alessio/shellescape.png?branch=master)](http://travis-ci.org/#!/alessio/shellescape) +[![Coverage](https://gocover.io/_badge/github.com/alessio/shellescape)](https://gocover.io/github.com/alessio/shellescape) +[![Coverage Status](https://coveralls.io/repos/github/alessio/shellescape/badge.svg?branch=master)](https://coveralls.io/github/alessio/shellescape?branch=master) +# shellescape +Escape arbitrary strings for safe use as command line arguments. +## Contents of the package + +This package provides the `shellescape.Quote()` function that returns a +shell-escaped copy of a string. This functionality could be helpful +in those cases where it is known that the output of a Go program will +be appended to/used in the context of shell programs' command line arguments. + +This work was inspired by the Python original package [shellescape] +(https://pypi.python.org/pypi/shellescape). + +## Usage + +The following snippet shows a typical unsafe idiom: + +```go +package main + +import ( + "fmt" + "os" +) + +func main() { + fmt.Printf("ls -l %s\n", os.Args[1]) +} +``` +_[See in Go Playground](https://play.golang.org/p/Wj2WoUfH_d)_ + +Especially when creating pipeline of commands which might end up being +executed by a shell interpreter, tt is particularly unsafe to not +escape arguments. + +`shellescape.Quote()` comes in handy and to safely escape strings: + +```go +package main + +import ( + "fmt" + "os" + + "gopkg.in/alessio/shellescape.v1" +) + +func main() { + fmt.Printf("ls -l %s\n", shellescape.Quote(os.Args[1])) +} +``` +_[See in Go Playground](https://play.golang.org/p/HJ_CXgSrmp)_ + +## The escargs utility +__escargs__ reads lines from the standard input and prints shell-escaped versions. Unlinke __xargs__, blank lines on the standard input are not discarded. diff --git a/vendor/github.com/alessio/shellescape/go.mod b/vendor/github.com/alessio/shellescape/go.mod new file mode 100644 index 0000000000..08d282650d --- /dev/null +++ b/vendor/github.com/alessio/shellescape/go.mod @@ -0,0 +1,3 @@ +module github.com/alessio/shellescape + +go 1.14 diff --git a/vendor/github.com/alessio/shellescape/shellescape.go b/vendor/github.com/alessio/shellescape/shellescape.go new file mode 100644 index 0000000000..56725d182a --- /dev/null +++ b/vendor/github.com/alessio/shellescape/shellescape.go @@ -0,0 +1,39 @@ +/* +Package shellescape provides the shellescape.Quote to escape arbitrary +strings for a safe use as command line arguments in the most common +POSIX shells. + +The original Python package which this work was inspired by can be found +at https://pypi.python.org/pypi/shellescape. +*/ +package shellescape // "import gopkg.in/alessio/shellescape.v1" + +/* +The functionality provided by shellescape.Quote could be helpful +in those cases where it is known that the output of a Go program will +be appended to/used in the context of shell programs' command line arguments. +*/ + +import ( + "regexp" + "strings" +) + +var pattern *regexp.Regexp + +func init() { + pattern = regexp.MustCompile(`[^\w@%+=:,./-]`) +} + +// Quote returns a shell-escaped version of the string s. The returned value +// is a string that can safely be used as one token in a shell command line. +func Quote(s string) string { + if len(s) == 0 { + return "''" + } + if pattern.MatchString(s) { + return "'" + strings.Replace(s, "'", "'\"'\"'", -1) + "'" + } + + return s +} diff --git a/vendor/modules.txt b/vendor/modules.txt index f8e227423e..6f511c702a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -52,6 +52,9 @@ github.com/PuerkitoBio/urlesc ## explicit github.com/agl/ed25519 github.com/agl/ed25519/edwards25519 +# github.com/alessio/shellescape v1.2.2 +## explicit +github.com/alessio/shellescape # github.com/apache/thrift v0.0.0-20171203172758-327ebb6c2b6d ## explicit # github.com/beorn7/perks v1.0.1