Skip to content

types: List/Map/Object/Set Values Are Not Concurrency/Modification Safe #556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
bflad opened this issue Nov 29, 2022 · 2 comments · Fixed by #591
Closed

types: List/Map/Object/Set Values Are Not Concurrency/Modification Safe #556

bflad opened this issue Nov 29, 2022 · 2 comments · Fixed by #591
Labels
bug Something isn't working
Milestone

Comments

@bflad
Copy link
Contributor

bflad commented Nov 29, 2022

Module version

v0.16.0

Relevant provider source code

// shared instantiation
obj := types.ObjectValueMust(/*...*/)

// across multiple goroutines, e.g. parallel unit testing of attribute plan modification
attributes := obj.Attributes()
attributes[/*...*/] = /*...*/

Expected Behavior

Callers would receive their own copy of the underlying attribute values map, not a direct reference to the map which can be modified.

Actual Behavior

(Object).Attributes() returns the underlying map reference directly, which can lead to unit testing failures such as:

fatal error: concurrent map iteration and map write

Presumably this is also an issue with:

  • (List).Elements()
  • (Map).Elements()
  • (Object).AttributeTypes()
  • (Set).Elements()

Some creation functions save their slice/map parameters directly, which could mean the caller could unexpectedly modify the values post-creation (needs to be verified):

  • ListValue() / ListValueMust()
  • MapValue() / MapValueMust()
  • ObjectNull() (attribute types) / ObjectUnknown() (attribute types) / ObjectValue() / ObjectValueFrom() (attribute types) / ObjectValueMust()
  • SetValue() / SetValueMust()
@bflad bflad added the bug Something isn't working label Nov 29, 2022
@bflad
Copy link
Contributor Author

bflad commented Nov 29, 2022

Sometimes the error is fatal error: concurrent map read and map write as well.

@bflad bflad added this to the v1.0.1 milestone Dec 16, 2022
bflad added a commit that referenced this issue Dec 16, 2022
…returns cannot mutate underlying data

Reference: #556
Reference: #582

This will ensure that the `Attributes()`, `AttributeTypes()`, and `Elements()` methods return a copy of the underlying map or slice of data, rather than a direct reference to the map or slice. This also prevents `Object`-based plan modification from returning a panic since the updated `Object` `Attributes()` implementation will return an empty map instead of a `nil` map. Provider implementations should always rely on `IsNull()` and `IsUnknown()` for verifying whether types are known, rather than a nil comparison. This is considered a bug fix for the intended behavior of these type implementations rather than a breaking change as it standardizes type handling expectations.

New unit testing failures before code updates:

```
--- FAIL: TestMapValueElements_immutable (0.00s)
    /Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/types/basetypes/map_test.go:604: unexpected Elements mutation

--- FAIL: TestNestedAttributeObjectPlanModify (0.00s)
    --- FAIL: TestNestedAttributeObjectPlanModify/response-planvalue-unknown-to-known-nested (0.00s)
panic: assignment to entry in nil map [recovered]
	panic: assignment to entry in nil map

goroutine 35 [running]:
testing.tRunner.func1.2({0x1010f0180, 0x10115b648})
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/testing/testing.go:1396 +0x1c8
testing.tRunner.func1()
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/testing/testing.go:1399 +0x378
panic({0x1010f0180, 0x10115b648})
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/runtime/panic.go:884 +0x204
github.com/hashicorp/terraform-plugin-framework/internal/fwserver.NestedAttributeObjectPlanModify({_, _}, {_, _}, {{{0x1400010d190, 0x1, 0x1}}, {0x1, {0x1400010d1b0, 0x1, ...}}, ...}, ...)
	/Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/internal/fwserver/attribute_plan_modification.go:1748 +0x510
```
bflad added a commit that referenced this issue Dec 16, 2022
…returns cannot mutate underlying data

Reference: #556
Reference: #582

This will ensure that the `Attributes()`, `AttributeTypes()`, and `Elements()` methods return a copy of the underlying map or slice of data, rather than a direct reference to the map or slice. This also prevents `Object`-based plan modification from returning a panic since the updated `Object` `Attributes()` implementation will return an empty map instead of a `nil` map. Provider implementations should always rely on `IsNull()` and `IsUnknown()` for verifying whether types are known, rather than a nil comparison. This is considered a bug fix for the intended behavior of these type implementations rather than a breaking change as it standardizes type handling expectations.

New unit testing failures before code updates:

```
--- FAIL: TestMapValueElements_immutable (0.00s)
    /Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/types/basetypes/map_test.go:604: unexpected Elements mutation

--- FAIL: TestNestedAttributeObjectPlanModify (0.00s)
    --- FAIL: TestNestedAttributeObjectPlanModify/response-planvalue-unknown-to-known-nested (0.00s)
panic: assignment to entry in nil map [recovered]
	panic: assignment to entry in nil map

goroutine 35 [running]:
testing.tRunner.func1.2({0x1010f0180, 0x10115b648})
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/testing/testing.go:1396 +0x1c8
testing.tRunner.func1()
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/testing/testing.go:1399 +0x378
panic({0x1010f0180, 0x10115b648})
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/runtime/panic.go:884 +0x204
github.com/hashicorp/terraform-plugin-framework/internal/fwserver.NestedAttributeObjectPlanModify({_, _}, {_, _}, {{{0x1400010d190, 0x1, 0x1}}, {0x1, {0x1400010d1b0, 0x1, ...}}, ...}, ...)
	/Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/internal/fwserver/attribute_plan_modification.go:1748 +0x510
```
bflad added a commit that referenced this issue Dec 19, 2022
…returns cannot mutate underlying data (#591)

Reference: #556
Reference: #582

This will ensure that the `Attributes()`, `AttributeTypes()`, and `Elements()` methods return a copy of the underlying map or slice of data, rather than a direct reference to the map or slice. This also prevents `Object`-based plan modification from returning a panic since the updated `Object` `Attributes()` implementation will return an empty map instead of a `nil` map. Provider implementations should always rely on `IsNull()` and `IsUnknown()` for verifying whether types are known, rather than a nil comparison. This is considered a bug fix for the intended behavior of these type implementations rather than a breaking change as it standardizes type handling expectations.

New unit testing failures before code updates:

```
--- FAIL: TestMapValueElements_immutable (0.00s)
    /Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/types/basetypes/map_test.go:604: unexpected Elements mutation

--- FAIL: TestNestedAttributeObjectPlanModify (0.00s)
    --- FAIL: TestNestedAttributeObjectPlanModify/response-planvalue-unknown-to-known-nested (0.00s)
panic: assignment to entry in nil map [recovered]
	panic: assignment to entry in nil map

goroutine 35 [running]:
testing.tRunner.func1.2({0x1010f0180, 0x10115b648})
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/testing/testing.go:1396 +0x1c8
testing.tRunner.func1()
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/testing/testing.go:1399 +0x378
panic({0x1010f0180, 0x10115b648})
	/opt/homebrew/Cellar/go/1.19.4/libexec/src/runtime/panic.go:884 +0x204
github.com/hashicorp/terraform-plugin-framework/internal/fwserver.NestedAttributeObjectPlanModify({_, _}, {_, _}, {{{0x1400010d190, 0x1, 0x1}}, {0x1, {0x1400010d1b0, 0x1, ...}}, ...}, ...)
	/Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/internal/fwserver/attribute_plan_modification.go:1748 +0x510
```
@github-actions
Copy link

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jan 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
1 participant