Prevent Memory Aliasing

Cette page n'est pas encore disponible en français, sa traduction est en cours.
Si vous avez des questions ou des retours sur notre projet de traduction actuel, n'hésitez pas à nous contacter.

Metadata

ID: go-security/range-memory-aliasing

Language: Go

Severity: Warning

Category: Security

Description

Implicit memory aliasing in for loops refers to a scenario in Go programming when two or more pointers reference the same location in memory, creating unexpected side effects. This often results in a common mistake amongst Go programmers due to the ‘range’ clause.

Consider this example, where a slice of pointers is created in a loop:

data := []int{1, 2, 3}
pointers := make([]*int, 3)
for i, v := range data {
    pointers[i] = &v
}

You might expect the ‘pointers’ slice to hold addresses of elements in ‘data’ slice, but that’s not the case. In each iteration of the loop, variable ‘v’ gets a new value but its memory address doesn’t change because it’s a loop variable. As a result, each element in ‘pointers’ slice points to the same memory location - the address of the loop variable ‘v’. The final value of ‘v’ is ‘3’, and since all pointers point to ‘v’, dereferencing the pointers would yield ‘3’ regardless of the pointer’s index in the slice.

To avoid implicit memory aliasing in for loops in Go, you should address the actual elements in the original data structure, like so:

data := []int{1, 2, 3}
pointers := make([]*int, 3)
for i := range data {
    pointers[i] = &data[i]
}

In this example, each pointer in the ‘pointers’ slice correctly points to the respective element in the ‘data’ slice.

Learn More

Non-Compliant Code Examples

import (
    "fmt"
)

func main() {
    data := []int{1, 2, 3}
    pointers := make([]*int, 3)
    for i, v := range data {
        pointers[i] = &v
    }
}
import (
    "fmt"
)

func main() {
    for _, n := range []int{1, 2, 3, 4} {
        fmt.Printf("%p\n", &n)
        v = &n
        v = foo(&n)
        v := &n
    }
}

Compliant Code Examples

import (
    "fmt"
)

func main() {
    data := []int{1, 2, 3}
    pointers := make([]*int, 3)
    for i := range data {
        pointers[i] = &data[i]
    }
}
import (
    "fmt"
)

func main() {
    for _, n := range []int{1, 2, 3, 4} {
        fmt.Printf("%p\n", n)
        v = ++n
        v = foo(--n)
        v := n
    }
}
https://static.datadoghq.com/static/images/logos/github_avatar.svg https://static.datadoghq.com/static/images/logos/vscode_avatar.svg jetbrains

Seamless integrations. Try Datadog Code Analysis