2023-03-15 16:00:52 +00:00
|
|
|
# Copyright (c) HashiCorp, Inc.
|
|
|
|
# SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2022-03-18 18:14:03 +00:00
|
|
|
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 ...
|
|
|
|
}
|