-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathUninitializedAtomicObject.ql
78 lines (72 loc) · 2.53 KB
/
UninitializedAtomicObject.ql
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
* @id c/misra/uninitialized-atomic-object
* @name RULE-9-7: Atomic objects shall be appropriately initialized before being accessed
* @description Atomic objects that do not have static storage duration shall be initialized with a
* value or by using 'atomic_init()'.
* @kind problem
* @precision high
* @problem.severity warning
* @tags external/misra/id/rule-9-7
* concurrency
* external/misra/c/2012/amendment4
* external/misra/obligation/mandatory
*/
import cpp
import codingstandards.c.misra
import codingstandards.cpp.StdFunctionOrMacro
import semmle.code.cpp.controlflow.Dominance
class ThreadSpawningFunction extends Function {
ThreadSpawningFunction() {
this.hasName("pthread_create")
or
this.hasName("thrd_create")
or
exists(FunctionCall fc |
fc.getTarget() instanceof ThreadSpawningFunction and
fc.getEnclosingFunction() = this
)
}
}
private string atomicInit() { result = "atomic_init" }
class AtomicInitAddressOfExpr extends AddressOfExpr {
AtomicInitAddressOfExpr() {
exists(StdFunctionOrMacro<C11FunctionWrapperMacro, atomicInit/0>::Call c |
this = c.getArgument(0)
)
}
}
ControlFlowNode getARequiredInitializationPoint(LocalScopeVariable v) {
result = v.getParentScope().(BlockStmt).getFollowingStmt()
or
exists(DeclStmt decl |
decl.getADeclaration() = v and
result =
any(FunctionCall fc |
fc.getTarget() instanceof ThreadSpawningFunction and
fc.getEnclosingBlock().getEnclosingBlock*() = v.getParentScope() and
fc.getAPredecessor*() = decl
)
)
}
from VariableDeclarationEntry decl, Variable v
where
not isExcluded(decl, Concurrency7Package::uninitializedAtomicObjectQuery()) and
v = decl.getVariable() and
v.getUnderlyingType().hasSpecifier("atomic") and
not v.isTopLevel() and
not exists(v.getInitializer()) and
exists(ControlFlowNode missingInitPoint |
missingInitPoint = getARequiredInitializationPoint(v) and
// Check for `atomic_init(&v)`
not exists(AtomicInitAddressOfExpr initialization |
initialization.getOperand().(VariableAccess).getTarget() = v and
dominates(initialization, missingInitPoint)
) and
// Check for `unknown_func(&v)` which may call `atomic_init` on `v`.
not exists(FunctionCall fc |
fc.getAnArgument().(AddressOfExpr).getOperand().(VariableAccess).getTarget() = v and
dominates(fc, missingInitPoint)
)
)
select decl,
"Atomic object '" + v.getName() + "' has no initializer or corresponding use of 'atomic_init()'."