1313 */
1414
1515import cpp
16- import semmle.code.cpp.controlflow.StackVariableReachability
16+ import semmle.code.cpp.ir.IR
17+ import semmle.code.cpp.ir.dataflow.MustFlow
1718
1819/**
1920 * Auxiliary predicate: Types that don't require initialization
@@ -33,31 +34,6 @@ predicate allocatedType(Type t) {
3334 allocatedType ( t .getUnspecifiedType ( ) )
3435}
3536
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-
6137pragma [ noinline]
6238predicate containsInlineAssembly ( Function f ) { exists ( AsmStmt s | s .getEnclosingFunction ( ) = f ) }
6339
@@ -82,8 +58,31 @@ VariableAccess commonException() {
8258 containsInlineAssembly ( result .getEnclosingFunction ( ) )
8359}
8460
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
8684where
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 ( )
8988select va , "The variable $@ may not be initialized at this access." , v , v .getName ( )
0 commit comments