Skip to content

Commit 4a34c33

Browse files
json: Refuse to encode cty.DynamicVal
Two different bugs interacted here to cause a cty.DynamicVal to end up encoding as nothing at all, with no error: - The main marshal function was checking for dynamic type before checking for unknown value, so cty.DynamicVal was being passed to marshalDynamic. - marshalDynamic was not checking the error result from encoding the value, and so was successfully returning nothing at all. This situation will now return the same "value is not known" error that the function previously returned for all other situations where the given value is unknown. The JSON representation of cty values can only represent fully-known values.
1 parent 4b76b75 commit 4a34c33

File tree

2 files changed

+8
-5
lines changed

2 files changed

+8
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
* `msgpack`: Now uses string encoding instead of float encoding for a whole number that is too large to fit in any of MessagePack's integer types.
44
* `function/stdlib`: Type conversion functions (constructed with `MakeToFunc`) can now convert null values of unknown type into null values of the target type, rather than returning an unknown value in that case.
5+
* `json`: Will now correctly reject attempts to encode `cty.DynamicVal`, whereas before it would just produce an invalid JSON document without any error. (This is invalid because JSON encoding cannot support unknown values at all; `cty.DynamicVal` is a special case of unknown value where even the _type_ isn't known.)
56

67
# 1.14.3 (February 29, 2024)
78

cty/json/marshal.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ func marshal(val cty.Value, t cty.Type, path cty.Path, b *bytes.Buffer) error {
1212
if val.IsMarked() {
1313
return path.NewErrorf("value has marks, so it cannot be serialized as JSON")
1414
}
15+
if !val.IsKnown() {
16+
return path.NewErrorf("value is not known")
17+
}
1518

1619
// If we're going to decode as DynamicPseudoType then we need to save
1720
// dynamic type information to recover the real type.
@@ -24,10 +27,6 @@ func marshal(val cty.Value, t cty.Type, path cty.Path, b *bytes.Buffer) error {
2427
return nil
2528
}
2629

27-
if !val.IsKnown() {
28-
return path.NewErrorf("value is not known")
29-
}
30-
3130
// The caller should've guaranteed that the given val is conformant with
3231
// the given type t, so we'll proceed under that assumption here.
3332

@@ -185,7 +184,10 @@ func marshalDynamic(val cty.Value, path cty.Path, b *bytes.Buffer) error {
185184
return path.NewErrorf("failed to serialize type: %s", err)
186185
}
187186
b.WriteString(`{"value":`)
188-
marshal(val, val.Type(), path, b)
187+
err = marshal(val, val.Type(), path, b)
188+
if err != nil {
189+
return path.NewErrorf("failed to serialize value: %s", err)
190+
}
189191
b.WriteString(`,"type":`)
190192
b.Write(typeJSON)
191193
b.WriteRune('}')

0 commit comments

Comments
 (0)