From 71d915c3e3271fce4709a6c06bebc39c6e7a6a0f Mon Sep 17 00:00:00 2001 From: GrosQuildu Date: Wed, 3 Apr 2024 11:59:29 +0200 Subject: [PATCH 1/4] fix go lock rules messages --- go/missing-runlock-on-rwmutex.yaml | 2 +- go/missing-unlock-before-return.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go/missing-runlock-on-rwmutex.yaml b/go/missing-runlock-on-rwmutex.yaml index 616ab1c..bff5f87 100644 --- a/go/missing-runlock-on-rwmutex.yaml +++ b/go/missing-runlock-on-rwmutex.yaml @@ -1,7 +1,7 @@ rules: - id: missing-runlock-on-rwmutex message: >- - Missing `RUnlock` on an `RWMutex` lock before returning from a function + Missing `RUnlock` on an `RWMutex` (`$T` variable) lock before returning from a function languages: [go] severity: ERROR metadata: diff --git a/go/missing-unlock-before-return.yaml b/go/missing-unlock-before-return.yaml index cd640ea..679c5f6 100644 --- a/go/missing-unlock-before-return.yaml +++ b/go/missing-unlock-before-return.yaml @@ -1,7 +1,7 @@ rules: - id: missing-unlock-before-return message: >- - Missing mutex unlock before returning from a function. + Missing mutex unlock (`$T` variable) before returning from a function. This could result in panics resulting from double lock operations languages: [go] severity: ERROR From 9a4afe0e780a03064921b4d7f5aad9bbed21ded4 Mon Sep 17 00:00:00 2001 From: GrosQuildu Date: Wed, 3 Apr 2024 12:22:02 +0200 Subject: [PATCH 2/4] add types to go lock rules --- go/missing-runlock-on-rwmutex.yaml | 5 +++++ go/missing-unlock-before-return.yaml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/go/missing-runlock-on-rwmutex.yaml b/go/missing-runlock-on-rwmutex.yaml index bff5f87..375d5ae 100644 --- a/go/missing-runlock-on-rwmutex.yaml +++ b/go/missing-runlock-on-rwmutex.yaml @@ -21,6 +21,11 @@ rules: - pattern-either: - pattern: panic(...) - pattern: return ... + - metavariable-pattern: + metavariable: $T + patterns: + - pattern: | + ($T : sync.RWMutex) - pattern-inside: | $T.RLock() ... diff --git a/go/missing-unlock-before-return.yaml b/go/missing-unlock-before-return.yaml index 679c5f6..c5dfdc4 100644 --- a/go/missing-unlock-before-return.yaml +++ b/go/missing-unlock-before-return.yaml @@ -22,6 +22,11 @@ rules: - pattern-either: - pattern: panic(...) - pattern: return ... + - metavariable-pattern: + metavariable: $T + patterns: + - pattern: | + ($T : sync.Mutex) - pattern-inside: | $T.Lock() ... From 17b707c7cee32fb57b4f9e1d7b92b91d39a35a00 Mon Sep 17 00:00:00 2001 From: GrosQuildu Date: Wed, 3 Apr 2024 12:24:10 +0200 Subject: [PATCH 3/4] new types test for go lock rules --- go/missing-runlock-on-rwmutex.go | 15 +++++++++++++++ go/missing-unlock-before-return.go | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/go/missing-runlock-on-rwmutex.go b/go/missing-runlock-on-rwmutex.go index ac2621b..21df77e 100644 --- a/go/missing-runlock-on-rwmutex.go +++ b/go/missing-runlock-on-rwmutex.go @@ -14,6 +14,14 @@ type RWContainer struct { counters map[string]int } +type Fridge struct { + food int +} + +func (f *Fridge) RLock() { + fmt.Println(f.food) +} + func main() { c := RWContainer{ counters: map[string]int{"a": 0, "b": 0}, @@ -87,3 +95,10 @@ func (c *RWContainer) inc4FP(name string) RUnlocker { c.mu.Unlock() } } + +func (c *RWContainer) inc5(name string) error { + f := Fridge{food: 11} + f.RLock() + // ok: missing-runlock-on-rwmutex + return nil +} diff --git a/go/missing-unlock-before-return.go b/go/missing-unlock-before-return.go index 13624ad..1e7e961 100644 --- a/go/missing-unlock-before-return.go +++ b/go/missing-unlock-before-return.go @@ -14,6 +14,14 @@ type Container struct { counters map[string]int } +type Fridge struct { + food int +} + +func (f *Fridge) Lock() { + fmt.Println(f.food) +} + func main() { c := Container{ counters: map[string]int{"a": 0, "b": 0}, @@ -113,3 +121,12 @@ func (c *Container) inc4FP(name string) Unlocker { c.mu.Unlock() } } + +func (c *Container) inc5(name string) error { + f := Fridge{food: 11} + f.Lock() + // ok: missing-unlock-before-return + return nil +} + + From b7ed449bf69d71f7f5e82e6bf0b423ac9b81825c Mon Sep 17 00:00:00 2001 From: GrosQuildu Date: Wed, 3 Apr 2024 13:15:57 +0200 Subject: [PATCH 4/4] go lock rules - defer FP fix --- go/missing-runlock-on-rwmutex.go | 70 ++++++++++++++++++++++++++++ go/missing-runlock-on-rwmutex.yaml | 7 +++ go/missing-unlock-before-return.go | 70 ++++++++++++++++++++++++++++ go/missing-unlock-before-return.yaml | 7 +++ 4 files changed, 154 insertions(+) diff --git a/go/missing-runlock-on-rwmutex.go b/go/missing-runlock-on-rwmutex.go index 21df77e..faabfa6 100644 --- a/go/missing-runlock-on-rwmutex.go +++ b/go/missing-runlock-on-rwmutex.go @@ -61,6 +61,7 @@ func (c *RWContainer) inc(name string) error { return fmt.Errorf("letter not allowed") } c.mu.RUnlock() + // ok: missing-runlock-on-rwmutex return nil } @@ -84,6 +85,7 @@ func (c *RWContainer) inc_FP(name string) error { return fmt.Errorf("letter not allowed") } c.mu.RUnlock() + // ok: missing-runlock-on-rwmutex return nil } @@ -102,3 +104,71 @@ func (c *RWContainer) inc5(name string) error { // ok: missing-runlock-on-rwmutex return nil } + +func (c *RWContainer) inc6(name string) error { + c.mu.RLock() + c.counters[name]++ + defer func() { + fmt.Println("before runlock") + c.mu.RUnlock() + fmt.Println("after runlock") + }() + // ok: missing-runlock-on-rwmutex + return nil +} + +func (c *RWContainer) inc6b(name string) error { + c.mu.RLock() + unlocker := c.mu.RUnlock + c.counters[name]++ + defer func() { + fmt.Println("before runlock") + unlocker() + fmt.Println("after runlock") + }() + // todook: missing-runlock-on-rwmutex + return nil +} + +func (c *RWContainer) inc7(name string) error { + c.mu.RLock() + c.counters[name]++ + defer func(earlyExit bool) { + fmt.Println("before runlock") + if (earlyExit) { + // todoruleid: missing-runlock-on-rwmutex + return + } + c.mu.RUnlock() + fmt.Println("after runlock") + }(false) + // ok: missing-runlock-on-rwmutex + return nil +} + +func (c *RWContainer) inc8(name string) error { + c.mu.RLock() + c.counters[name]++ + _, err := fmt.Println("test if") + if err != nil { + c.mu.RUnlock() + // ok: missing-runlock-on-rwmutex + return nil, err + } + // ruleid: missing-runlock-on-rwmutex + return nil +} + +func (c *RWContainer) inc8b(name string) error { + c.mu.RLock() + c.counters[name]++ + unlocker := c.mu.RUnlock + _, err := fmt.Println("test if") + if err != nil { + unlocker() + // todook: missing-runlock-on-rwmutex + return nil, err + } + // ruleid: missing-runlock-on-rwmutex + return nil +} diff --git a/go/missing-runlock-on-rwmutex.yaml b/go/missing-runlock-on-rwmutex.yaml index 375d5ae..45e1b4d 100644 --- a/go/missing-runlock-on-rwmutex.yaml +++ b/go/missing-runlock-on-rwmutex.yaml @@ -35,6 +35,13 @@ rules: - pattern-not-inside: | defer $T.RUnlock() ... + - pattern-not-inside: | + defer func(...) { + ... + $T.RUnlock() + ... + }(...) + ... - pattern-not-inside: | $FOO(..., ..., func(...) { ... diff --git a/go/missing-unlock-before-return.go b/go/missing-unlock-before-return.go index 1e7e961..5b1c610 100644 --- a/go/missing-unlock-before-return.go +++ b/go/missing-unlock-before-return.go @@ -61,6 +61,7 @@ func (c *Container) inc(name string) error { return fmt.Errorf("letter not allowed") } c.mu.Unlock() + // ok: missing-unlock-before-return return nil } @@ -73,6 +74,7 @@ func (c *Container) inc_FP(name string) error { return fmt.Errorf("letter not allowed") } c.mu.Unlock() + // ok: missing-unlock-before-return return nil } @@ -86,6 +88,7 @@ func (c *Container) inc2(name string) error { panic("letter not allowed") } c.mu.Unlock() + // ok: missing-unlock-before-return return nil } @@ -98,6 +101,7 @@ func (c *Container) inc2_FP(name string) error { panic("letter not allowed") } c.mu.Unlock() + // ok: missing-unlock-before-return return nil } @@ -129,4 +133,70 @@ func (c *Container) inc5(name string) error { return nil } +func (c *Container) inc6(name string) error { + c.mu.Lock() + c.counters[name]++ + defer func() { + fmt.Println("before unlock") + c.mu.Unlock() + fmt.Println("after unlock") + }() + // ok: missing-unlock-before-return + return nil +} + +func (c *Container) inc6b(name string) error { + c.mu.Lock() + unlocker := c.mu.Unlock + c.counters[name]++ + defer func() { + fmt.Println("before unlock") + unlocker() + fmt.Println("after unlock") + }() + // todook: missing-unlock-before-return + return nil +} + +func (c *Container) inc7(name string) error { + c.mu.Lock() + c.counters[name]++ + defer func(earlyExit bool) { + fmt.Println("before unlock") + if (earlyExit) { + // todoruleid: missing-unlock-before-return + return + } + c.mu.Unlock() + fmt.Println("after unlock") + }(false) + // ok: missing-unlock-before-return + return nil +} + +func (c *Container) inc8(name string) error { + c.mu.Lock() + c.counters[name]++ + _, err := fmt.Println("test if") + if err != nil { + c.mu.Unlock() + // ok: missing-unlock-before-return + return nil, err + } + // ruleid: missing-unlock-before-return + return nil +} +func (c *Container) inc8b(name string) error { + c.mu.Lock() + c.counters[name]++ + unlocker := c.mu.Unlock + _, err := fmt.Println("test if") + if err != nil { + unlocker() + // todook: missing-unlock-before-return + return nil, err + } + // ruleid: missing-unlock-before-return + return nil +} diff --git a/go/missing-unlock-before-return.yaml b/go/missing-unlock-before-return.yaml index c5dfdc4..aceabd1 100644 --- a/go/missing-unlock-before-return.yaml +++ b/go/missing-unlock-before-return.yaml @@ -36,6 +36,13 @@ rules: - pattern-not-inside: | defer $T.Unlock() ... + - pattern-not-inside: | + defer func(...) { + ... + $T.Unlock() + ... + }(...) + ... - pattern-not-inside: | $FOO(..., ..., func(...) { ...