diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go index 487c68c..5f22a38 100644 --- a/pkg/runner/expression.go +++ b/pkg/runner/expression.go @@ -4,11 +4,11 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "fmt" "io" "os" "path/filepath" "regexp" + "strconv" "strings" "github.com/robertkrimen/otto" @@ -266,11 +266,35 @@ func vmEndsWith(vm *otto.Otto) { } func vmFormat(vm *otto.Otto) { - _ = vm.Set("format", func(s string, vals ...string) string { - for i, v := range vals { - s = strings.ReplaceAll(s, fmt.Sprintf("{%d}", i), v) - } - return s + _ = vm.Set("format", func(s string, vals ...otto.Value) string { + ex := regexp.MustCompile(`(\{[0-9]+\}|\{.?|\}.?)`) + return ex.ReplaceAllStringFunc(s, func(seg string) string { + switch seg { + case "{{": + return "{" + case "}}": + return "}" + default: + if len(seg) < 3 || !strings.HasPrefix(seg, "{") { + log.Errorf("The following format string is invalid: '%v'", s) + return "" + } + _i := seg[1 : len(seg)-1] + i, err := strconv.ParseInt(_i, 10, 32) + if err != nil { + log.Errorf("The following format string is invalid: '%v'. Error: %v", s, err) + return "" + } + if i >= int64(len(vals)) { + log.Errorf("The following format string references more arguments than were supplied: '%v'", s) + return "" + } + if vals[i].IsNull() || vals[i].IsUndefined() { + return "" + } + return vals[i].String() + } + }) }) } diff --git a/pkg/runner/expression_test.go b/pkg/runner/expression_test.go index a338187..2e9b47e 100644 --- a/pkg/runner/expression_test.go +++ b/pkg/runner/expression_test.go @@ -110,6 +110,14 @@ func TestEvaluate(t *testing.T) { {"env.key", "value", ""}, {"secrets.CASE_INSENSITIVE_SECRET", "value", ""}, {"secrets.case_insensitive_secret", "value", ""}, + {"format('{{0}}', 'test')", "{0}", ""}, + {"format('{{{0}}}', 'test')", "{test}", ""}, + {"format('}}')", "}", ""}, + {"format('echo Hello {0} ${{Test}}', 'World')", "echo Hello World ${Test}", ""}, + {"format('echo Hello {0} ${{Test}}', github.undefined_property)", "echo Hello ${Test}", ""}, + {"format('echo Hello {0}{1} ${{Te{0}st}}', github.undefined_property, 'World')", "echo Hello World ${Test}", ""}, + {"format('{0}', '{1}', 'World')", "{1}", ""}, + {"format('{{{0}', '{1}', 'World')", "{{1}", ""}, } for _, table := range tables {