13
13
*/
14
14
15
15
import cpp
16
- import semmle.code.cpp.controlflow.StackVariableReachability
16
+ import semmle.code.cpp.ir.IR
17
+ import semmle.code.cpp.ir.dataflow.MustFlow
17
18
18
19
/**
19
20
* Auxiliary predicate: Types that don't require initialization
@@ -33,31 +34,6 @@ predicate allocatedType(Type t) {
33
34
allocatedType ( t .getUnspecifiedType ( ) )
34
35
}
35
36
36
- /**
37
- * A declaration of a local variable that leaves the
38
- * variable uninitialized.
39
- */
40
- DeclStmt declWithNoInit ( LocalVariable v ) {
41
- result .getADeclaration ( ) = v and
42
- not exists ( v .getInitializer ( ) ) and
43
- /* The type of the variable is not stack-allocated. */
44
- exists ( Type t | t = v .getType ( ) | not allocatedType ( t ) )
45
- }
46
-
47
- class UninitialisedLocalReachability extends StackVariableReachability {
48
- UninitialisedLocalReachability ( ) { this = "UninitialisedLocal" }
49
-
50
- override predicate isSource ( ControlFlowNode node , StackVariable v ) { node = declWithNoInit ( v ) }
51
-
52
- override predicate isSink ( ControlFlowNode node , StackVariable v ) { useOfVarActual ( v , node ) }
53
-
54
- override predicate isBarrier ( ControlFlowNode node , StackVariable v ) {
55
- // only report the _first_ possibly uninitialized use
56
- useOfVarActual ( v , node ) or
57
- definitionBarrier ( v , node )
58
- }
59
- }
60
-
61
37
pragma [ noinline]
62
38
predicate containsInlineAssembly ( Function f ) { exists ( AsmStmt s | s .getEnclosingFunction ( ) = f ) }
63
39
@@ -82,8 +58,31 @@ VariableAccess commonException() {
82
58
containsInlineAssembly ( result .getEnclosingFunction ( ) )
83
59
}
84
60
85
- from UninitialisedLocalReachability r , LocalVariable v , VariableAccess va
61
+ predicate isSinkImpl ( Instruction sink , VariableAccess va ) {
62
+ exists ( LoadInstruction load |
63
+ va = load .getUnconvertedResultExpression ( ) and
64
+ not va = commonException ( ) and
65
+ sink = load .getSourceValue ( )
66
+ )
67
+ }
68
+
69
+ class MustFlow extends MustFlowConfiguration {
70
+ MustFlow ( ) { this = "MustFlow" }
71
+
72
+ override predicate isSource ( Instruction source ) {
73
+ source instanceof UninitializedInstruction and
74
+ exists ( Type t | t = source .getResultType ( ) | not allocatedType ( t ) )
75
+ }
76
+
77
+ override predicate isSink ( Operand sink ) { isSinkImpl ( sink .getDef ( ) , _) }
78
+
79
+ override predicate allowInterproceduralFlow ( ) { none ( ) }
80
+ }
81
+
82
+ from
83
+ VariableAccess va , LocalVariable v , MustFlow conf , MustFlowPathNode source , MustFlowPathNode sink
86
84
where
87
- r .reaches ( _, v , va ) and
88
- not va = commonException ( )
85
+ conf .hasFlowPath ( source , sink ) and
86
+ isSinkImpl ( sink .getInstruction ( ) , va ) and
87
+ v = va .getTarget ( )
89
88
select va , "The variable $@ may not be initialized at this access." , v , v .getName ( )
0 commit comments