hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
41.68k stars 9.41k forks source link

Crash in v0.12-alpha1 with "values" function #19204

Closed apparentlymart closed 5 years ago

apparentlymart commented 5 years ago

In Terraform console in v0.12.0-alpha1, the following should produce a reasonable result:

> values({"a":[], "b": ["a"]})

I expected this to return the same tuple produced by the expression [[], ["a"]], but instead it crashed:

Error: Error in function call

  on <console-input> line 1:
  (source code not available)

Call to function "values" failed: panic in function implementation: returned
value cty.Value{ty: cty.Tuple([]cty.Type{cty.EmptyTuple,
cty.Tuple([]cty.Type{cty.String})}), v: []interface {}{[]interface {}{},
[]interface {}{"a"}}} does not conform to expected return type
cty.Tuple([]cty.Type{cty.Tuple([]cty.Type{cty.String}), cty.EmptyTuple}): 1
elements are required, but got 0
goroutine 1 [running]:
runtime/debug.Stack(0xc00002d9a0, 0x4706da, 0xc00002d9f0)
    /opt/go/src/runtime/debug/stack.go:24 +0xa7
github.com/zclconf/go-cty/cty/function.errorForPanic(0x2c31d20, 0xc00012ee30,
0xc00012ee30, 0xc0002a8000)
    /opt/gopath/src/github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function/error.go:44
+0x26
github.com/zclconf/go-cty/cty/function.Function.Call.func1(0xc00002dc20,
0xc00002dc40)
    /opt/gopath/src/github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function/function.go:239
+0x85
panic(0x2c31d20, 0xc00012ee30)
    /opt/go/src/runtime/panic.go:513 +0x1b9
github.com/zclconf/go-cty/cty/function.Function.Call(0xc00027aa80,
0xc00000d5c0, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/vendor/github.com/zclconf/go-cty/cty/function/function.go:252
+0x7a3
github.com/hashicorp/hcl2/hcl/hclsyntax.(*FunctionCallExpr).Value(0xc000138000,
0xc00000d460, 0x0, 0xc00002f460, 0x1, 0x1, 0x0, 0x0, 0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/vendor/github.com/hashicorp/hcl2/hcl/hclsyntax/expression.go:385
+0x12a1
github.com/hashicorp/terraform/lang.(*Scope).EvalExpr(0xc000566730, 0x3784220,
0xc000138000, 0x3785520, 0x5d6b080, 0x1, 0x0, 0x0, 0x0, 0xc000138000, ...)
    /opt/gopath/src/github.com/hashicorp/terraform/lang/eval.go:78 +0x1a2
github.com/hashicorp/terraform/repl.(*Session).handleEval(0xc00002f8b0,
0xc0002e0260, 0x1c, 0x1c, 0xc0002e0260, 0x1c, 0x0, 0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/repl/session.go:58 +0x24e
github.com/hashicorp/terraform/repl.(*Session).Handle(0xc00002f8b0,
0xc0002e0260, 0x1c, 0x0, 0x0, 0xc000545700, 0x0, 0x0, 0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/repl/session.go:43 +0xc5
github.com/hashicorp/terraform/command.(*ConsoleCommand).modeInteractive(0xc000550000,
0xc00002f8b0, 0x3789300, 0xc00027bbc0, 0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/command/console_interactive.go:48
+0x17c
github.com/hashicorp/terraform/command.(*ConsoleCommand).Run(0xc000550000,
0xc00000c090, 0x0, 0x0, 0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/command/console.go:138 +0xcc2
github.com/mitchellh/cli.(*CLI).Run(0xc0002e7e00, 0xc0002e7e00, 0xc000425d20,
0x1)
    /opt/gopath/src/github.com/hashicorp/terraform/vendor/github.com/mitchellh/cli/cli.go:255
+0x207
main.wrappedMain(0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/main.go:222 +0xacc
main.realMain(0x0)
    /opt/gopath/src/github.com/hashicorp/terraform/main.go:99 +0xb7
main.main()
    /opt/gopath/src/github.com/hashicorp/terraform/main.go:35 +0x2e
.

It looks like the function's Type callback iterated the map keys in a different order than its Impl callback, causing a type mismatch. ElementIterator on a map value in cty ought to iterate the keys in consistent lexicographical order, so this may be a cty bug rather than a bug in the function.

This example probably won't reproduce 100% of the time since I expect the map traversal order is Go's random order, rather than something deterministic.

ghost commented 4 years ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.