hashicorp / hashicorp/terraform-plugin-sdk

Set implementation does not appropriately handle hash collisions

Open
#64 5 comments 0 reactions 0 assignees View on GitHub
bug subsystem/types terraform-plugin-framework
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.