lang: ast: Ensure a list doesn't sneak through type interpolation

If we had a single list wrapped in an interpolated string, it could
sneak through type unification, which is not correct. Wrapping a
variable by interpolation in a string, must force it to be a string.
This commit is contained in:
James Shubin
2024-03-20 18:06:29 -04:00
parent 340a832884
commit 946468dc99
8 changed files with 81 additions and 0 deletions

View File

@@ -5408,6 +5408,10 @@ func (obj *ExprStr) Interpolate() (interfaces.Expr, error) {
}, nil
}
// we got something, overwrite the existing static str
// ensure str, to avoid a pass-through list in a simple interpolation
if err := result.SetType(types.TypeStr); err != nil {
return nil, errwrap.Wrapf(err, "interpolated string expected a different type")
}
return result, nil // replacement
}

View File

@@ -41,6 +41,7 @@ import (
"github.com/purpleidea/mgmt/lang/funcs"
"github.com/purpleidea/mgmt/lang/interfaces"
"github.com/purpleidea/mgmt/lang/parser"
"github.com/purpleidea/mgmt/lang/types"
"github.com/purpleidea/mgmt/util"
"github.com/davecgh/go-spew/spew"
@@ -384,6 +385,9 @@ func TestInterpolateBasicStmt(t *testing.T) {
},
},
}
if err := resName.SetType(types.TypeStr); err != nil {
panic("could not set type")
}
exp := &ast.StmtProg{
Body: []interfaces.Stmt{
&ast.StmtRes{
@@ -574,6 +578,9 @@ func TestInterpolateBasicExpr(t *testing.T) {
},
},
}
if err := exp.SetType(types.TypeStr); err != nil {
panic("could not set type")
}
testCases = append(testCases, test{
name: "basic expansion",
ast: xast,

View File

@@ -0,0 +1,10 @@
-- main.mcl --
$name = ["a", "bb", "ccc",]
test $name {}
test "test" {}
#Test[$name] -> Test["test"] # must pass
Test["${name}"] -> Test["test"] # must fail
-- OUTPUT --
# err: errUnify: can't unify, invariant illogicality with equality: base kind does not match (Str != List)

View File

@@ -0,0 +1,16 @@
-- main.mcl --
$name = ["a", "bb", "ccc",]
test $name {}
test "test" {}
Test[$name] -> Test["test"] # must pass
#Test["${name}"] -> Test["test"] # must fail
-- OUTPUT --
Edge: test[a] -> test[test] # test[a] -> test[test]
Edge: test[bb] -> test[test] # test[bb] -> test[test]
Edge: test[ccc] -> test[test] # test[ccc] -> test[test]
Vertex: test[a]
Vertex: test[bb]
Vertex: test[ccc]
Vertex: test[test]

View File

@@ -0,0 +1,10 @@
-- main.mcl --
$name = ["a", "bb", "ccc",]
test $name {}
test "test" {}
#Test["test"] -> Test[$name] # must pass
Test["test"] -> Test["${name}"] # must fail
-- OUTPUT --
# err: errUnify: can't unify, invariant illogicality with equality: base kind does not match (Str != List)

View File

@@ -0,0 +1,16 @@
-- main.mcl --
$name = ["a", "bb", "ccc",]
test $name {}
test "test" {}
Test["test"] -> Test[$name] # must pass
#Test["test"] -> Test["${name}"] # must fail
-- OUTPUT --
Edge: test[test] -> test[a] # test[test] -> test[a]
Edge: test[test] -> test[bb] # test[test] -> test[bb]
Edge: test[test] -> test[ccc] # test[test] -> test[ccc]
Vertex: test[a]
Vertex: test[bb]
Vertex: test[ccc]
Vertex: test[test]

View File

@@ -0,0 +1,8 @@
-- main.mcl --
$name = ["a", "bb", "ccc",]
#test $name {} # must pass
test "${name}" {} # must fail
-- OUTPUT --
# err: errUnify: can't unify, invariant illogicality with equality: base kind does not match (Str != List)

View File

@@ -0,0 +1,10 @@
-- main.mcl --
$name = ["a", "bb", "ccc",]
test $name {} # must pass
#test "${name}" {} # must fail
-- OUTPUT --
Vertex: test[a]
Vertex: test[bb]
Vertex: test[ccc]