| # Copyright (c) HashiCorp, Inc. |
| # SPDX-License-Identifier: MPL-2.0 |
| |
| rules: |
| - id: lock_not_unlocked |
| message: | |
| Lock $LOCK not unlocked on branch with $COND |
| languages: [go] |
| severity: WARNING |
| patterns: |
| - pattern: | |
| $LOCK.Lock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # manual unlock before return |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| if $COND { |
| ... |
| $LOCK.Unlock() |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| $LOCK.Unlock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # manual unlock with release function |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| $UNLOCKFN = $LOCK.Unlock |
| ... |
| if $COND { |
| ... |
| $UNLOCKFN() |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| $UNLOCKFN := $LOCK.Unlock |
| ... |
| if $COND { |
| ... |
| $UNLOCKFN() |
| ... |
| return ... |
| } |
| # defered unlock |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| defer $LOCK.Unlock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| if $COND { |
| ... |
| defer $LOCK.Unlock() |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| defer func(){ |
| ... |
| $LOCK.Unlock() |
| ... |
| }() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # deferred unlock with release function |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| $UNLOCKFN := $LOCK.Unlock |
| ... |
| defer func() { |
| ... |
| $UNLOCKFN() |
| ... |
| }() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.Lock() |
| ... |
| $UNLOCKFN = $LOCK.Unlock |
| ... |
| defer func() { |
| ... |
| $UNLOCKFN() |
| ... |
| }() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # variation where defer is called first, |
| # unlock function is changed afterwards |
| - pattern-not-inside: | |
| defer func() { |
| ... |
| $UNLOCKFN() |
| ... |
| }() |
| ... |
| $LOCK.Lock() |
| ... |
| $UNLOCKFN = $LOCK.Unlock |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # variation where defer is called previously, lock is reacquired |
| # maybe include the Unlock call here? |
| - pattern-not-inside: | |
| defer $LOCK.Unlock() |
| ... |
| $LOCK.Lock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| - id: read_lock_not_unlocked |
| message: | |
| Lock $LOCK not unlocked on branch with $COND |
| languages: [go] |
| severity: WARNING |
| patterns: |
| - pattern: | |
| $LOCK.RLock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # manual unlock before return |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| if $COND { |
| ... |
| $LOCK.RUnlock() |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| $LOCK.RUnlock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # manual unlock with release function |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| $UNLOCKFN = $LOCK.RUnlock |
| ... |
| if $COND { |
| ... |
| $UNLOCKFN() |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| $UNLOCKFN := $LOCK.RUnlock |
| ... |
| if $COND { |
| ... |
| $UNLOCKFN() |
| ... |
| return ... |
| } |
| # defered unlock |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| defer $LOCK.RUnlock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| if $COND { |
| ... |
| defer $LOCK.RUnlock() |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| defer func(){ |
| ... |
| $LOCK.RUnlock() |
| ... |
| }() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # deferred unlock with release function |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| $UNLOCKFN := $LOCK.RUnlock |
| ... |
| defer func() { |
| ... |
| $UNLOCKFN() |
| ... |
| }() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| - pattern-not: | |
| $LOCK.RLock() |
| ... |
| $UNLOCKFN = $LOCK.RUnlock |
| ... |
| defer func() { |
| ... |
| $UNLOCKFN() |
| ... |
| }() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # variation where defer is called first, |
| # unlock function is changed afterwards |
| - pattern-not-inside: | |
| defer func() { |
| ... |
| $UNLOCKFN() |
| ... |
| }() |
| ... |
| $LOCK.RLock() |
| ... |
| $UNLOCKFN = $LOCK.RUnlock |
| ... |
| if $COND { |
| ... |
| return ... |
| } |
| # variation where defer is called previously, lock is reacquired |
| # maybe include the Unlock call here? |
| - pattern-not-inside: | |
| defer $LOCK.RUnlock() |
| ... |
| $LOCK.RLock() |
| ... |
| if $COND { |
| ... |
| return ... |
| } |