hashicorp / hashicorp/terraform-plugin-sdk
Set implementation does not appropriately handle hash collisions
- Dominant language
- Go
- Stars
- 485
- Forks
- 244
- Avg merge
- 19h 57m
- Merged PRs (30d)
- 4
Description
The set implementation in [`helper/schema/set.go`](https://github.com/hashicorp/terraform/blob/8cf13d9582309f45e4a04cd4cd36e717b5b60c75/helper/schema/set.go) produces incorrect results if elements in the set have colliding hash code values.
This should be relatively rare in practice because the size of the sets represented by this implementation would typically be relatively small, but the consequences of a collision would be very surprising to encounter.
The method used by, e.g., `HashSet` in Java is to also require an equality operation to be defined for elements in the set. I don't think that would be possible without changing the interface of `TypeSet`, so I'm not sure what the best path forward is.
### Terraform Version
`Terraform v0.6.15-dev` (current `master` / 8cf13d9582309f45e4a04cd4cd36e717b5b60c75)
### Affected Resource(s)
All resources using `TypeSet`.
### Terraform Configuration Files
``` hcl
provider "aws" {
region = "us-east-1"
}
resource "aws_instance" "web" {
ami = "ami-408c7f28"
instance_type = "t1.micro"
tags {
Name = "HelloWorld"
}
// these security group IDs all have the same CRC32 hash code (1373619311)
// https://gist.github.com/mattmoyer/5565a1dd5795c0ff53daa8e73b06c37b
vpc_security_group_ids = [
"sg-8c0f398e",
"sg-3615fc73",
"sg-eaf01421",
]
}
```
### Expected Behavior
The `terraform plan` output should show all three security group associations.
### Actual Behavior
In this case, `aws_instance` uses the `HashString` helper which is a CRC32 checksum. The three security group IDs in this case were deliberately chosen as examples that have a colliding CRC32 value of 1373619311, so they collide and only one of them ends up in the `terraform plan` output:
```
[...]
+ aws_instance.web
ami: "" => "ami-408c7f28"
availability_zone: "" => ""
ebs_block_device.#: "" => ""
ephemeral_block_device.#: "" => ""
instance_state: "" => ""
instance_type: "" => "t1.micro"
key_name: "" => ""
placement_group: "" => ""
private_dns: "" => ""
private_ip: "" => ""
public_dns: "" => ""
public_ip: "" => ""
root_block_device.#: "" => ""
security_groups.#: "" => ""
source_dest_check: "" => "1"
subnet_id: "" => ""
tags.#: "" => "1"
tags.Name: "" => "HelloWorld"
tenancy: "" => ""
vpc_security_group_ids.#: "" => "1"
vpc_security_group_ids.1373619311: "" => "sg-eaf01421"
Plan: 1 to add, 0 to change, 0 to destroy.
```
A similar failure case exists for any other `SchemaSetFunc` implementation used with `TypeSet`, since they all output a 32 bit code that may have collisions.
### Steps to Reproduce
1. Copy the configuration pasted above into a `.tf` file, and run `terraform plan`.
Contributor guide
Assessment
This issue has not been assessed yet.