forked from github/codeql-coding-standards
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNonRecursiveMutexRecursivelyLockedAudit.ql
More file actions
60 lines (56 loc) · 2.18 KB
/
NonRecursiveMutexRecursivelyLockedAudit.ql
File metadata and controls
60 lines (56 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* @id c/misra/non-recursive-mutex-recursively-locked-audit
* @name RULE-22-18: (Audit) Non-recursive mutexes shall not be recursively locked
* @description Mutexes that may be initialized without mtx_recursive shall not be locked by a
* thread that may have previously locked it.
* @kind problem
* @precision high
* @problem.severity error
* @tags external/misra/id/rule-22-18
* correctness
* concurrency
* external/misra/c/2012/amendment4
* external/misra/audit
* external/misra/obligation/required
*/
import cpp
import codeql.util.Boolean
import codingstandards.c.misra
import codingstandards.c.SubObjects
import codingstandards.cpp.ConcurrencyNew
import codingstandards.cpp.Type
predicate isTrackableMutex(CMutexFunctionCall lockCall, Boolean recursive) {
exists(SubObject mutex |
lockCall.getLockExpr() = mutex.getAnAddressOfExpr() and
mutex.isPrecise() and
forex(C11MutexSource init | init.getMutexExpr() = mutex.getAnAddressOfExpr() |
if init.isRecursive() then recursive = true else recursive = false
)
)
}
predicate definitelyDifferentMutexes(CMutexFunctionCall lockCall, CMutexFunctionCall coveredByLock) {
exists(SubObject a, SubObject b |
lockCall.getLockExpr() = a.getAnAddressOfExpr() and
coveredByLock.getLockExpr() = b.getAnAddressOfExpr() and
not a = b
)
}
from LockProtectedControlFlowNode n, CMutexFunctionCall lockCall, CMutexFunctionCall coveredByLock
where
not isExcluded(n, Concurrency9Package::nonRecursiveMutexRecursivelyLockedAuditQuery()) and
lockCall = n and
coveredByLock = n.coveredByLock() and
not coveredByLock = lockCall and
// If mutexes are provably different objects, they do not need to be audited
not definitelyDifferentMutexes(lockCall, coveredByLock) and
(
// If either mutex is not trackable, it should be audited
not isTrackableMutex(lockCall, _) or
not isTrackableMutex(coveredByLock, _)
) and
not (
// If either mutex is definitely recursive, it does not need to be audited
isTrackableMutex(lockCall, true) or
isTrackableMutex(coveredByLock, true)
)
select n, "Mutex locked after it was already $@.", coveredByLock, "previously locked"