From 904c1ed58d0e45180d4dcdc1ca300e8ed101642d Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 11 Mar 2021 11:05:35 -0500 Subject: [PATCH] don't pass unexpected marked values to TypeFunc ReturnTypeForValues was only checking an unmarking the top level value for TypeFuncs that did not expect marked values. Use ContainsMarked and UnmarkDeep to prepare the arguments. --- cty/function/function.go | 8 ++--- cty/function/function_test.go | 56 +++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/cty/function/function.go b/cty/function/function.go index efc83ad7..c00a0e7f 100644 --- a/cty/function/function.go +++ b/cty/function/function.go @@ -142,7 +142,7 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error) for i, spec := range f.spec.Params { val := posArgs[i] - if val.IsMarked() && !spec.AllowMarked { + if val.ContainsMarked() && !spec.AllowMarked { // During type checking we just unmark values and discard their // marks, under the assumption that during actual execution of // the function we'll do similarly and then re-apply the marks @@ -150,7 +150,7 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error) // inspects values (rather than just types) in its Type // implementation can potentially fail to take into account marks, // unless it specifically opts in to seeing them. - unmarked, _ := val.Unmark() + unmarked, _ := val.UnmarkDeep() newArgs := make([]cty.Value, len(args)) copy(newArgs, args) newArgs[i] = unmarked @@ -183,9 +183,9 @@ func (f Function) ReturnTypeForValues(args []cty.Value) (ty cty.Type, err error) for i, val := range varArgs { realI := i + len(posArgs) - if val.IsMarked() && !spec.AllowMarked { + if val.ContainsMarked() && !spec.AllowMarked { // See the similar block in the loop above for what's going on here. - unmarked, _ := val.Unmark() + unmarked, _ := val.UnmarkDeep() newArgs := make([]cty.Value, len(args)) copy(newArgs, args) newArgs[realI] = unmarked diff --git a/cty/function/function_test.go b/cty/function/function_test.go index c0e67bca..a01936be 100644 --- a/cty/function/function_test.go +++ b/cty/function/function_test.go @@ -122,6 +122,62 @@ func TestReturnTypeForValues(t *testing.T) { Args: []cty.Value{cty.StringVal("hello")}, WantErr: true, }, + { + Spec: &Spec{ + Params: []Parameter{ + { + Type: cty.List(cty.DynamicPseudoType), + }, + }, + Type: func(args []cty.Value) (cty.Type, error) { + ty := cty.Number + for i, arg := range args { + if arg.ContainsMarked() { + return ty, fmt.Errorf("arg %d %#v contains marks", i, arg) + } + } + return ty, nil + }, + Impl: stubImpl, + }, + Args: []cty.Value{ + cty.ListVal([]cty.Value{ + cty.StringVal("ok").Mark("marked"), + }), + }, + WantType: cty.Number, + }, + { + Spec: &Spec{ + Params: []Parameter{ + { + Type: cty.List(cty.String), + }, + }, + VarParam: &Parameter{ + Type: cty.List(cty.String), + }, + Type: func(args []cty.Value) (cty.Type, error) { + ty := cty.Number + for i, arg := range args { + if arg.ContainsMarked() { + return ty, fmt.Errorf("arg %d %#v contains marks", i, arg) + } + } + return ty, nil + }, + Impl: stubImpl, + }, + Args: []cty.Value{ + cty.ListVal([]cty.Value{ + cty.StringVal("one"), + }), + cty.ListVal([]cty.Value{ + cty.StringVal("two").Mark("marked"), + }), + }, + WantType: cty.Number, + }, } for i, test := range tests {