Skip to content

Commit

Permalink
Merge pull request #296 from compose-spec/fix-interpolation-interference
Browse files Browse the repository at this point in the history
Fix Interpolation interference from outer string
  • Loading branch information
ulyssessouza committed Aug 1, 2022
2 parents 56e6c33 + 5062118 commit ff627a8
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 20 deletions.
38 changes: 18 additions & 20 deletions template/template.go
Expand Up @@ -61,13 +61,14 @@ type SubstituteFunc func(string, Mapping) (string, bool, error)
// SubstituteWith substitute variables in the string with their values.
// It accepts additional substitute function.
func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, subsFuncs ...SubstituteFunc) (string, error) {
var err error
var outerErr error

if len(subsFuncs) == 0 {
_, subsFunc := getSubstitutionFunctionForTemplate(template)
subsFuncs = []SubstituteFunc{subsFunc}
}
result := pattern.ReplaceAllStringFunc(template, func(substring string) string {
_, subsFunc := getSubstitutionFunctionForTemplate(substring)
if len(subsFuncs) > 0 {
subsFunc = subsFuncs[0]
}

closingBraceIndex := getFirstBraceClosingIndex(substring)
rest := ""
if closingBraceIndex > -1 {
Expand All @@ -89,24 +90,21 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su
}

if substitution == "" {
err = &InvalidTemplateError{Template: template}
outerErr = &InvalidTemplateError{Template: template}
return ""
}

if braced {
for _, f := range subsFuncs {
var (
value string
applied bool
)
value, applied, err = f(substitution, mapping)
if err != nil {
return ""
}
if !applied {
continue
}
interpolatedNested, err := SubstituteWith(rest, mapping, pattern, subsFuncs...)
var (
value string
applied bool
)
value, applied, outerErr = subsFunc(substitution, mapping)
if outerErr != nil {
return ""
}
if applied {
interpolatedNested, err := SubstituteWith(rest, mapping, pattern)
if err != nil {
return ""
}
Expand All @@ -121,7 +119,7 @@ func SubstituteWith(template string, mapping Mapping, pattern *regexp.Regexp, su
return value
})

return result, err
return result, outerErr
}

func getSubstitutionFunctionForTemplate(template string) (string, SubstituteFunc) {
Expand Down
57 changes: 57 additions & 0 deletions template/template_test.go
Expand Up @@ -155,6 +155,63 @@ func TestNonAlphanumericDefault(t *testing.T) {
assert.Check(t, is.Equal("ok /non:-alphanumeric", result))
}

func TestInterpolationExternalInterference(t *testing.T) {
testCases := []struct {
name string
template string
expected string
}{
{
template: "-ok ${BAR:-defaultValue}",
expected: "-ok defaultValue",
},
{
template: "+ok ${UNSET:-${BAR-defaultValue}}",
expected: "+ok ",
},
{
template: "-ok ${FOO:-defaultValue}",
expected: "-ok first",
},
{
template: ":-ok ${UNSET-defaultValue}",
expected: ":-ok defaultValue",
},
{
template: ":-ok ${BAR-defaultValue}",
expected: ":-ok ",
},
{
template: ":?ok ${BAR-defaultValue}",
expected: ":?ok ",
},
{
template: ":?ok ${BAR:-defaultValue}",
expected: ":?ok defaultValue",
},
{
template: ":+ok ${BAR:-defaultValue}",
expected: ":+ok defaultValue",
},
{
template: "+ok ${BAR-defaultValue}",
expected: "+ok ",
},
{
template: "?ok ${BAR:-defaultValue}",
expected: "?ok defaultValue",
},
}
for i, tc := range testCases {
tc := tc
t.Run(fmt.Sprintf("Interpolation Should not be impacted by outer text: %d", i), func(t *testing.T) {
result, err := Substitute(tc.template, defaultMapping)
assert.NilError(t, err)
assert.Check(t, is.Equal(tc.expected, result))
})
}
}

func TestDefaultsWithNestedExpansion(t *testing.T) {
testCases := []struct {
template string
Expand Down

0 comments on commit ff627a8

Please sign in to comment.