diff --git a/README.md b/README.md index 83aaf5a..b56bd9b 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,6 @@ $ semgrep --config /path/to/semgrep-rules/hanging-goroutine.yml -o leaks.txt' | ID | Playground | Impact | Confidence | Description | | -- | :--------: | :----: | :--------: | ----------- | -| [anonymous-race-condition](go/anonymous-race-condition.yaml) | [🛝🔗](https://semgrep.dev/playground/r/trailofbits.go.anonymous-race-condition.anonymous-race-condition) | 🟧 | 🌗 | Race conditions within anonymous goroutines | | [hanging-goroutine](go/hanging-goroutine.yaml) | [🛝🔗](https://semgrep.dev/playground/r/trailofbits.go.hanging-goroutine.hanging-goroutine) | 🟩 | 🌗 | Goroutine leaks | | [invalid-usage-of-modified-variable](go/invalid-usage-of-modified-variable.yaml) | [🛝🔗](https://semgrep.dev/playground/r/trailofbits.go.invalid-usage-of-modified-variable.invalid-usage-of-modified-variable) | 🟧 | 🌘 | Possible unintentional assignment when an error occurs | | [iterate-over-empty-map](go/iterate-over-empty-map.yaml) | [🛝🔗](https://semgrep.dev/playground/r/trailofbits.go.iterate-over-empty-map.iterate-over-empty-map) | 🟩 | 🌗 | Probably redundant iteration over an empty map | diff --git a/go/anonymous-race-condition.go b/go/anonymous-race-condition.go deleted file mode 100644 index aeca06c..0000000 --- a/go/anonymous-race-condition.go +++ /dev/null @@ -1,309 +0,0 @@ -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() - AnonRaceCond_5() - AnonRaceCond_6() - AnonRaceCond_7() - AnonRaceCond_7_FP() - AnonRaceCond_8() - AnonRaceCond_8_FP() - AnonRaceCond_9() - AnonRaceCond_9_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() -} - -func AnonRaceCond_5() { - var wg sync.WaitGroup - // ok: anonymous-race-condition - for idx, val := range values { - wg.Add(1) - idx, val := idx, val - go func() { - val.s.Method("test") - fmt.Println("Completed index", idx) - wg.Done() - }() - } - - wg.Wait() -} - -func AnonRaceCond_6() { - var wg sync.WaitGroup - // ok: anonymous-race-condition - for idx, val := range values { - wg.Add(1) - idx, val := idx, val - go func() { - fmt.Println(val.s) - fmt.Println("Completed index", idx) - wg.Done() - }() - } - - wg.Wait() -} - -func AnonRaceCond_7() { - var wg sync.WaitGroup - // ruleid: anonymous-race-condition - for idx, val := range values { - wg.Add(1) - fmt.Println(val) - go func() { - fmt.Println("Completed index", idx) - wg.Done() - }() - } - - wg.Wait() -} - -func AnonRaceCond_7_FP() { - var wg sync.WaitGroup - // ok: anonymous-race-condition - for idx, val := range values { - wg.Add(1) - idx := idx - fmt.Println(val) - go func() { - fmt.Println("Completed index", idx) - wg.Done() - }() - } - - wg.Wait() -} - -func AnonRaceCond_8() { - var wg sync.WaitGroup - for _, num := range numbers { - // ruleid: anonymous-race-condition - for _, val := range values { - fmt.Println(num) - wg.Add(1) - go func() { - defer wg.Done() - fmt.Println(val) - }() - } - } - wg.Wait() -} - -func AnonRaceCond_8_FP() { - var wg sync.WaitGroup - // ok: anonymous-race-condition - for _, num := range numbers { - for _, val := range values { - num, val := num, val - fmt.Println(num) - wg.Add(1) - go func() { - defer wg.Done() - fmt.Println(val) - }() - } - } - wg.Wait() -} - -func AnonRaceCond_9() { - var wg sync.WaitGroup - // ruleid: anonymous-race-condition - for _, num := range numbers { - for _, val := range values { - fmt.Println(val) - wg.Add(1) - go func() { - defer wg.Done() - fmt.Println(num) - }() - } - } - wg.Wait() -} - -func AnonRaceCond_9_FP() { - var wg sync.WaitGroup - for _, num := range numbers { - // ruleid: anonymous-race-condition - for _, val := range values { - fmt.Println(num) - wg.Add(1) - go func() { - defer wg.Done() - fmt.Println(val) - }() - } - } - wg.Wait() -} diff --git a/go/anonymous-race-condition.yaml b/go/anonymous-race-condition.yaml deleted file mode 100644 index 3bcf075..0000000 --- a/go/anonymous-race-condition.yaml +++ /dev/null @@ -1,104 +0,0 @@ -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 - - patterns: - - pattern-either: - - pattern: | - for $Y, $X := range ... { - ... - go func(...){ - ... - $FOO(..., $X, ...) - ... - }(...) - ... - } - - pattern: | - for $Y, $X := range ... { - ... - go func(...){ - ... - $FOO(..., $Y, ...) - ... - }(...) - ... - } - - 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 := range ... { - ... - ..., $X := ..., $X - ... - go func(...){ - ... - $FOO(..., $X, ...) - ... - }(...) - ... - } - - pattern-not: | - for ..., $X := range ... { - ... - $X, ... := $X, ... - ... - go func(...){ - ... - $FOO(..., $X, ...) - ... - }(...) - ... - } - - pattern-not: | - for $Y, $X := range ... { - ... - $Y, $X := $Y, $X - ... - go func(...){ - ... - }(...) - ... - }