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 ... }