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.
This commit is contained in:
parent
a4df1ba6d1
commit
2b1e650df2
|
@ -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) {
|
renderTmpl := func(expr hcl.Expression, varsVal cty.Value) (cty.Value, error) {
|
||||||
if varsTy := varsVal.Type(); !(varsTy.IsMapType() || varsTy.IsObjectType()) {
|
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{
|
ctx := &hcl.EvalContext{
|
||||||
|
@ -105,7 +105,7 @@ func MakeTemplateFileFunc(baseDir string, funcsCb func() map[string]function.Fun
|
||||||
for _, traversal := range expr.Variables() {
|
for _, traversal := range expr.Variables() {
|
||||||
root := traversal.RootName()
|
root := traversal.RootName()
|
||||||
if _, ok := ctx.Variables[root]; !ok {
|
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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,12 @@ func TestTemplateFile(t *testing.T) {
|
||||||
t.Run(fmt.Sprintf("TemplateFile(%#v, %#v)", test.Path, test.Vars), func(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})
|
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 test.Err {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("succeeded; want error")
|
t.Fatal("succeeded; want error")
|
||||||
|
|
Loading…
Reference in New Issue