funcs: Don't panic if templatefile path is sensitive

Previously we were partially propagating any marks from the path, but not
going all the way so we still ran into trouble when trying to use the
string containing the file contents.

Now we'll have loadTmpl also return the marks it had to read through to
actually parse the template, and then we'll use those (instead of the
original path marks) to mark the result. In practice the pathMarks and
the tmplMarks should always match today, but this is intentionally
structured to make the data flow clearer -- the marks always travel along
with whatever they related to -- so we're less likely to break this
accidentally under future maintenence.
pull/35220/head
Martin Atkins 2 years ago
parent ee5cda7000
commit 9dd28fc2e5

@ -72,20 +72,21 @@ func MakeFileFunc(baseDir string, encBase64 bool) function.Function {
// the templatefile function, since that would risk the same file being
// included into itself indefinitely.
func MakeTemplateFileFunc(baseDir string, funcsCb func() (funcs map[string]function.Function, fsFuncs collections.Set[string], templateFuncs collections.Set[string])) function.Function {
loadTmpl := func(fn string, marks cty.ValueMarks) (hcl.Expression, error) {
loadTmpl := func(fn string, marks cty.ValueMarks) (hcl.Expression, cty.ValueMarks, error) {
// We re-use File here to ensure the same filename interpretation
// as it does, along with its other safety checks.
tmplVal, err := File(baseDir, cty.StringVal(fn).WithMarks(marks))
if err != nil {
return nil, err
return nil, nil, err
}
tmplVal, marks = tmplVal.Unmark()
expr, diags := hclsyntax.ParseTemplate([]byte(tmplVal.AsString()), fn, hcl.Pos{Line: 1, Column: 1})
if diags.HasErrors() {
return nil, diags
return nil, nil, diags
}
return expr, nil
return expr, marks, nil
}
renderTmpl := makeRenderTemplateFunc(funcsCb, true)
@ -112,7 +113,7 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() (funcs map[string]funct
// return any type.
pathArg, pathMarks := args[0].Unmark()
expr, err := loadTmpl(pathArg.AsString(), pathMarks)
expr, _, err := loadTmpl(pathArg.AsString(), pathMarks)
if err != nil {
return cty.DynamicPseudoType, err
}
@ -124,12 +125,12 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() (funcs map[string]funct
},
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
pathArg, pathMarks := args[0].Unmark()
expr, err := loadTmpl(pathArg.AsString(), pathMarks)
expr, tmplMarks, err := loadTmpl(pathArg.AsString(), pathMarks)
if err != nil {
return cty.DynamicVal, err
}
result, err := renderTmpl(expr, args[1])
return result.WithMarks(pathMarks), err
return result.WithMarks(tmplMarks), err
},
})

@ -187,6 +187,18 @@ func TestTemplateFile(t *testing.T) {
cty.True, // since this template contains only an interpolation, its true value shines through
``,
},
{
// If the template filename is sensitive then we also treat the
// rendered result as sensitive, because the rendered result
// is likely to imply which filename was used.
// (Sensitive filenames seem pretty unlikely, but if they do
// crop up then we should handle them consistently with our
// usual sensitivity rules.)
cty.StringVal("testdata/hello.txt").Mark(marks.Sensitive),
cty.EmptyObjectVal,
cty.StringVal("Hello World").Mark(marks.Sensitive),
``,
},
}
funcs := map[string]function.Function{

Loading…
Cancel
Save