trailofbits.go.anonymous-race-condition.anonymous-race-condition

Author
232
Download Count*
License
Possible race condition due to memory aliasing of variable $X
Run Locally
Run in CI
Defintion
rules:
- id: anonymous-race-condition
message: Possible race condition due to memory aliasing of variable `$X`
languages:
- go
severity: ERROR
metadata:
category: security
cwe: "CWE-362: Concurrent Execution using Shared Resource with Improper
Synchronization ('Race Condition')"
subcategory:
- vuln
confidence: MEDIUM
likelihood: HIGH
impact: MEDIUM
technology:
- --no-technology--
description: Race conditions within anonymous goroutines
references:
- https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables
license: CC-BY-NC-SA-4.0
patterns:
- pattern-either:
- pattern: |
for $Y, $X := range ... {
...
go func(...){
...
$FOO(..., $X, ...)
...
}(...)
...
}
- pattern: |
for $Y, $X := range ... {
...
go func(...){
...
$X(...)
...
}(...)
...
}
- pattern: |
for $X:=...;$Y;$Z {
...
go func(...) {
...
$FOO(..., $X,...)
...
}(...)
...
}
- pattern: |
for $Y, $X := range ... {
...
go func(...){
...
$X. ... .$M(...)
...
}(...)
...
}
- pattern-not: |
for $X, $Y := range ... {
...
go func(..., $V, ...){
...
$FOO(..., $V, ...)
...
}(..., $Y, ...)
...
}
- pattern-not: |
for $Y, $X := range ... {
...
go func(..., $CP, ...){
...
$CP(...)
...
}($X)
...
}
- pattern-not: |
for $X:=...;$Y;$Z {
...
go func(..., $V, ...) {
...
$FOO(..., $V,...)
...
}(..., $X, ...)
...
}
- pattern-not: |
for $X, $Y := range ... {
...
$COPY := $Y
...
go func(...){
...
$FOO(..., $COPY, ...)
...
}(...)
...
}
- pattern-not: |
for $X:=...;$Y;$Z {
...
$COPY := $X
...
go func(...) {
...
$FOO(..., $COPY,...)
...
}(...)
...
}
Examples
anonymous-race-condition.go
package main
import (
"fmt"
"sync"
)
type myval struct {
s string
}
type myval2 struct {
s myval
}
func (v *myval) Method(x string) {
fmt.Println(v.s + "-" + x)
}
var (
numbers = [6]string{"one", "two", "three", "four", "five", "six"}
)
var (
values = [3]myval2{myval2{myval{"a"}}, myval2{myval{"b"}}, myval2{myval{"c"}}}
)
func main() {
ConcurrentFunctions_TP(func1, func2)
ConcurrentFunctions_FP(func1, func2)
AnonRaceCond_1()
AnonRaceCond_1_FP()
AnonRaceCond_2()
AnonRaceCond_2_FP()
AnonRaceCond_3_FP()
AnonRaceCond_4()
AnonRaceCond_4_FP()
}
func func1() {
fmt.Println("I am function func1")
}
func func2() {
fmt.Println("I am function func2")
}
func ConcurrentFunctions_TP(fns ...func()) {
var wg sync.WaitGroup
// ruleid: anonymous-race-condition
for _, fn := range fns {
wg.Add(1)
go func() {
fn()
wg.Done()
}()
}
wg.Wait()
}
func ConcurrentFunctions_FP(fns ...func()) {
var wg sync.WaitGroup
// ok: anonymous-race-condition
for _, fn := range fns {
wg.Add(1)
go func(fn2 func()) {
fn2()
wg.Done()
}(fn)
}
wg.Wait()
}
func AnonRaceCond_1() {
var wg sync.WaitGroup
// ruleid: anonymous-race-condition
for _, num := range numbers {
wg.Add(1)
go func() {
fmt.Println(num)
wg.Done()
}()
}
wg.Wait()
}
func AnonRaceCond_1_FP() {
var wg sync.WaitGroup
// ok: anonymous-race-condition
for _, num := range numbers {
wg.Add(1)
go func(cpy string) {
fmt.Println(cpy)
wg.Done()
}(num)
}
wg.Wait()
}
func AnonRaceCond_2() {
var wg sync.WaitGroup
// ruleid: anonymous-race-condition
for i := 0; i< len(numbers); i++ {
wg.Add(1)
go func() {
fmt.Println(i)
wg.Done()
}()
}
wg.Wait()
}
func AnonRaceCond_2_FP() {
var wg sync.WaitGroup
// ok: anonymous-race-condition
for i := 0; i< len(numbers); i++ {
wg.Add(1)
go func(n int) {
fmt.Println(n)
wg.Done()
}(i)
}
wg.Wait()
}
func AnonRaceCond_3_FP() {
var wg sync.WaitGroup
// ok: anonymous-race-condition
for i := 0; i< len(numbers); i++ {
cpy := i
wg.Add(1)
go func() {
fmt.Println(cpy)
wg.Done()
}()
}
wg.Wait()
}
func AnonRaceCond_4() {
var wg sync.WaitGroup
// ruleid: anonymous-race-condition
for _, val := range values {
wg.Add(1)
go func() {
val.s.Method("test")
wg.Done()
}()
}
wg.Wait()
}
func AnonRaceCond_4_FP() {
var wg sync.WaitGroup
// ok: anonymous-race-condition
for _, val := range values {
wg.Add(1)
val := val
go func() {
val.s.Method("test")
wg.Done()
}()
}
wg.Wait()
}
Short Link: https://sg.run/BL22