From 5e36dacf23d587ed46631a0230f3b9f68b3e2513 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 4 Aug 2021 14:45:37 -0400 Subject: [PATCH] cty: AsBigFloat does a shallow copy Use Float.Copy in AsBigFloat to ensure that there is no shared data between the mutable `*big.Float` and the `cty.Value` internal state. --- cty/value_ops.go | 4 +--- cty/value_ops_test.go | 13 +++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/cty/value_ops.go b/cty/value_ops.go index 8c37535c..8c42e795 100644 --- a/cty/value_ops.go +++ b/cty/value_ops.go @@ -1283,9 +1283,7 @@ func (val Value) AsBigFloat() *big.Float { } // Copy the float so that callers can't mutate our internal state - ret := *(val.v.(*big.Float)) - - return &ret + return new(big.Float).Copy(val.v.(*big.Float)) } // AsValueSlice returns a []cty.Value representation of a non-null, non-unknown diff --git a/cty/value_ops_test.go b/cty/value_ops_test.go index 4261a35d..e447c6b1 100644 --- a/cty/value_ops_test.go +++ b/cty/value_ops_test.go @@ -3432,3 +3432,16 @@ func TestHasWhollyKnownType(t *testing.T) { }) } } + +func TestFloatCopy(t *testing.T) { + // ensure manipulating floats does not modify the cty.Value + v := NumberFloatVal(1.9) + vString := v.GoString() + + // do something that will modify the internal big.Float mantissa + v.AsBigFloat().SetInt64(1) + + if vString != v.GoString() { + t.Fatalf("original value changed from %s to %#v", vString, v) + } +}