From 2b1e650df2d3353d5ce862458b4a2b0b6d8513dc Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Tue, 19 Mar 2019 16:07:04 -0700 Subject: [PATCH] lang/funcs: Fix out-of-bounds ArgError in templatefile function The templatefile function only has two arguments, so ArgErrorf can be called with only zero or one as the argument index. If we are out of bounds then HCL itself will panic trying to build the error message for this call when called as an HCL function. Unfortunately there isn't really a great layer in Terraform to test for this class of bug systematically, because we are currently testing these functions directly rather than going through HCL to do it. For the moment we'll just live with that, but if we see this class of error arise again we might consider either reworking the tests in this package to work with HCL expression source code instead of direct calls or adding some additional tests elsewhere that do so. --- lang/funcs/filesystem.go | 4 ++-- lang/funcs/filesystem_test.go | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lang/funcs/filesystem.go b/lang/funcs/filesystem.go index ed8a9d1bc..7dfc90587 100644 --- a/lang/funcs/filesystem.go +++ b/lang/funcs/filesystem.go @@ -92,7 +92,7 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Fun renderTmpl := func(expr hcl.Expression, varsVal cty.Value) (cty.Value, error) { if varsTy := varsVal.Type(); !(varsTy.IsMapType() || varsTy.IsObjectType()) { - return cty.DynamicVal, function.NewArgErrorf(2, "invalid vars value: must be a map") // or an object, but we don't strongly distinguish these most of the time + return cty.DynamicVal, function.NewArgErrorf(1, "invalid vars value: must be a map") // or an object, but we don't strongly distinguish these most of the time } ctx := &hcl.EvalContext{ @@ -105,7 +105,7 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Fun for _, traversal := range expr.Variables() { root := traversal.RootName() if _, ok := ctx.Variables[root]; !ok { - return cty.DynamicVal, function.NewArgErrorf(2, "vars map does not contain key %q, referenced at %s", root, traversal[0].SourceRange()) + return cty.DynamicVal, function.NewArgErrorf(1, "vars map does not contain key %q, referenced at %s", root, traversal[0].SourceRange()) } } diff --git a/lang/funcs/filesystem_test.go b/lang/funcs/filesystem_test.go index c8e68d360..d64e78423 100644 --- a/lang/funcs/filesystem_test.go +++ b/lang/funcs/filesystem_test.go @@ -159,6 +159,12 @@ func TestTemplateFile(t *testing.T) { t.Run(fmt.Sprintf("TemplateFile(%#v, %#v)", test.Path, test.Vars), func(t *testing.T) { got, err := templateFileFn.Call([]cty.Value{test.Path, test.Vars}) + if argErr, ok := err.(function.ArgError); ok { + if argErr.Index < 0 || argErr.Index > 1 { + t.Errorf("ArgError index %d is out of range for templatefile (must be 0 or 1)", argErr.Index) + } + } + if test.Err { if err == nil { t.Fatal("succeeded; want error")