Back to all reviewers

Prevent backing array surprises

opentofu/opentofu
Based on 4 comments
Go

When modifying slices in Go, be aware that appending to a slice with available capacity will modify the backing array, potentially affecting other slices that share the same backing storage. This can lead to subtle bugs where one operation unexpectedly affects seemingly unrelated variables.

Algorithms Go

Reviewer Prompt

When modifying slices in Go, be aware that appending to a slice with available capacity will modify the backing array, potentially affecting other slices that share the same backing storage. This can lead to subtle bugs where one operation unexpectedly affects seemingly unrelated variables.

For example, this code has a potential issue:

encryptCommand := append(cmd, "--encrypt") 
decryptCommand := append(cmd, "--decrypt")

If cmd has spare capacity, both slices will share the same backing array, and the second append will overwrite the last element of the first slice.

To avoid this problem:

  1. Use slices.Clip() to ensure a fresh backing array before appending:
    cmd = slices.Clip(cmd)
    encryptCommand := append(cmd, "--encrypt")
    decryptCommand := append(cmd, "--decrypt")
    
  2. Or explicitly create independent copies:
    encryptCommand := make([]string, len(cmd)+1)
    copy(encryptCommand, cmd)
    encryptCommand[len(cmd)] = "--encrypt"
    

This principle applies to other operations where deterministic behavior is crucial, such as:

  • Map iteration (use sorted keys for consistency)
  • Merging collections (consider equality semantics)
  • Boolean expressions (apply transformations consistently)

By understanding the memory model of your data structures, you’ll create more predictable, stable algorithms less prone to subtle side effects.

4
Comments Analyzed
Go
Primary Language
Algorithms
Category

Source Discussions