Skip to content

Commit c1ed908

Browse files
committed
C++: Use StackVariableReachability
This library is a drop-in replacement for `LocalScopeVariableReachability`, so no changes are expected.
1 parent 01ca63a commit c1ed908

File tree

6 files changed

+52
-58
lines changed

6 files changed

+52
-58
lines changed

cpp/ql/src/Critical/FileMayNotBeClosed.ql

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111

1212
import FileClosed
13-
import semmle.code.cpp.controlflow.LocalScopeVariableReachability
13+
import semmle.code.cpp.controlflow.StackVariableReachability
1414

1515
/**
1616
* Extend the NullValue class used by Nullness.qll to include simple -1 as a 'null' value
@@ -68,18 +68,18 @@ predicate fcloseCallOrIndirect(FunctionCall fc, Variable v) {
6868
)
6969
}
7070

71-
predicate fopenDefinition(LocalScopeVariable v, ControlFlowNode def) {
71+
predicate fopenDefinition(StackVariable v, ControlFlowNode def) {
7272
exists(Expr expr | exprDefinition(v, def, expr) and fopenCallOrIndirect(expr))
7373
}
7474

75-
class FOpenVariableReachability extends LocalScopeVariableReachabilityWithReassignment {
75+
class FOpenVariableReachability extends StackVariableReachabilityWithReassignment {
7676
FOpenVariableReachability() { this = "FOpenVariableReachability" }
7777

78-
override predicate isSourceActual(ControlFlowNode node, LocalScopeVariable v) {
78+
override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
7979
fopenDefinition(v, node)
8080
}
8181

82-
override predicate isSinkActual(ControlFlowNode node, LocalScopeVariable v) {
82+
override predicate isSinkActual(ControlFlowNode node, StackVariable v) {
8383
// node may be used in fopenReaches
8484
exists(node.(AnalysedExpr).getNullSuccessor(v)) or
8585
fcloseCallOrIndirect(node, v) or
@@ -88,15 +88,13 @@ class FOpenVariableReachability extends LocalScopeVariableReachabilityWithReassi
8888
v.getFunction() = node.(ReturnStmt).getEnclosingFunction()
8989
}
9090

91-
override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) {
92-
definitionBarrier(v, node)
93-
}
91+
override predicate isBarrier(ControlFlowNode node, StackVariable v) { definitionBarrier(v, node) }
9492
}
9593

9694
/**
9795
* The value from fopen at `def` is still held in Variable `v` upon entering `node`.
9896
*/
99-
predicate fopenVariableReaches(LocalScopeVariable v, ControlFlowNode def, ControlFlowNode node) {
97+
predicate fopenVariableReaches(StackVariable v, ControlFlowNode def, ControlFlowNode node) {
10098
exists(FOpenVariableReachability r |
10199
// reachability
102100
r.reachesTo(def, _, node, v)
@@ -107,25 +105,23 @@ predicate fopenVariableReaches(LocalScopeVariable v, ControlFlowNode def, Contro
107105
)
108106
}
109107

110-
class FOpenReachability extends LocalScopeVariableReachabilityExt {
108+
class FOpenReachability extends StackVariableReachabilityExt {
111109
FOpenReachability() { this = "FOpenReachability" }
112110

113-
override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
114-
fopenDefinition(v, node)
115-
}
111+
override predicate isSource(ControlFlowNode node, StackVariable v) { fopenDefinition(v, node) }
116112

117-
override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
113+
override predicate isSink(ControlFlowNode node, StackVariable v) {
118114
v.getFunction() = node.(ReturnStmt).getEnclosingFunction()
119115
}
120116

121117
override predicate isBarrier(
122-
ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v
118+
ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, StackVariable v
123119
) {
124120
isSource(source, v) and
125121
next = node.getASuccessor() and
126122
// the file (stored in any variable `v0`) opened at `source` is closed or
127123
// assigned to a global at node, or NULL checked on the edge node -> next.
128-
exists(LocalScopeVariable v0 | fopenVariableReaches(v0, source, node) |
124+
exists(StackVariable v0 | fopenVariableReaches(v0, source, node) |
129125
node.(AnalysedExpr).getNullSuccessor(v0) = next or
130126
fcloseCallOrIndirect(node, v0) or
131127
assignedToFieldOrGlobal(v0, node)
@@ -142,11 +138,11 @@ predicate fopenReaches(ControlFlowNode def, ControlFlowNode node) {
142138
exists(FOpenReachability r | r.reaches(def, _, node))
143139
}
144140

145-
predicate assignedToFieldOrGlobal(LocalScopeVariable v, Expr e) {
146-
// assigned to anything except a LocalScopeVariable
141+
predicate assignedToFieldOrGlobal(StackVariable v, Expr e) {
142+
// assigned to anything except a StackVariable
147143
// (typically a field or global, but for example also *ptr = v)
148144
e.(Assignment).getRValue() = v.getAnAccess() and
149-
not e.(Assignment).getLValue().(VariableAccess).getTarget() instanceof LocalScopeVariable
145+
not e.(Assignment).getLValue().(VariableAccess).getTarget() instanceof StackVariable
150146
or
151147
exists(Expr midExpr, Function mid, int arg |
152148
// indirect assignment
@@ -163,7 +159,7 @@ predicate assignedToFieldOrGlobal(LocalScopeVariable v, Expr e) {
163159
from ControlFlowNode def, ReturnStmt ret
164160
where
165161
fopenReaches(def, ret) and
166-
not exists(LocalScopeVariable v |
162+
not exists(StackVariable v |
167163
fopenVariableReaches(v, def, ret) and
168164
ret.getAChild*() = v.getAnAccess()
169165
)

cpp/ql/src/Critical/MemoryMayNotBeFreed.ql

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*/
1111

1212
import MemoryFreed
13-
import semmle.code.cpp.controlflow.LocalScopeVariableReachability
13+
import semmle.code.cpp.controlflow.StackVariableReachability
1414

1515
/**
1616
* 'call' is either a direct call to f, or a possible call to f
@@ -97,18 +97,18 @@ predicate freeCallOrIndirect(ControlFlowNode n, Variable v) {
9797
)
9898
}
9999

100-
predicate allocationDefinition(LocalScopeVariable v, ControlFlowNode def) {
100+
predicate allocationDefinition(StackVariable v, ControlFlowNode def) {
101101
exists(Expr expr | exprDefinition(v, def, expr) and allocCallOrIndirect(expr))
102102
}
103103

104-
class AllocVariableReachability extends LocalScopeVariableReachabilityWithReassignment {
104+
class AllocVariableReachability extends StackVariableReachabilityWithReassignment {
105105
AllocVariableReachability() { this = "AllocVariableReachability" }
106106

107-
override predicate isSourceActual(ControlFlowNode node, LocalScopeVariable v) {
107+
override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
108108
allocationDefinition(v, node)
109109
}
110110

111-
override predicate isSinkActual(ControlFlowNode node, LocalScopeVariable v) {
111+
override predicate isSinkActual(ControlFlowNode node, StackVariable v) {
112112
// node may be used in allocationReaches
113113
exists(node.(AnalysedExpr).getNullSuccessor(v)) or
114114
freeCallOrIndirect(node, v) or
@@ -117,15 +117,13 @@ class AllocVariableReachability extends LocalScopeVariableReachabilityWithReassi
117117
v.getFunction() = node.(ReturnStmt).getEnclosingFunction()
118118
}
119119

120-
override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) {
121-
definitionBarrier(v, node)
122-
}
120+
override predicate isBarrier(ControlFlowNode node, StackVariable v) { definitionBarrier(v, node) }
123121
}
124122

125123
/**
126124
* The value from allocation `def` is still held in Variable `v` upon entering `node`.
127125
*/
128-
predicate allocatedVariableReaches(LocalScopeVariable v, ControlFlowNode def, ControlFlowNode node) {
126+
predicate allocatedVariableReaches(StackVariable v, ControlFlowNode def, ControlFlowNode node) {
129127
exists(AllocVariableReachability r |
130128
// reachability
131129
r.reachesTo(def, _, node, v)
@@ -136,25 +134,25 @@ predicate allocatedVariableReaches(LocalScopeVariable v, ControlFlowNode def, Co
136134
)
137135
}
138136

139-
class AllocReachability extends LocalScopeVariableReachabilityExt {
137+
class AllocReachability extends StackVariableReachabilityExt {
140138
AllocReachability() { this = "AllocReachability" }
141139

142-
override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
140+
override predicate isSource(ControlFlowNode node, StackVariable v) {
143141
allocationDefinition(v, node)
144142
}
145143

146-
override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
144+
override predicate isSink(ControlFlowNode node, StackVariable v) {
147145
v.getFunction() = node.(ReturnStmt).getEnclosingFunction()
148146
}
149147

150148
override predicate isBarrier(
151-
ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v
149+
ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, StackVariable v
152150
) {
153151
isSource(source, v) and
154152
next = node.getASuccessor() and
155153
// the memory (stored in any variable `v0`) allocated at `source` is freed or
156154
// assigned to a global at node, or NULL checked on the edge node -> next.
157-
exists(LocalScopeVariable v0 | allocatedVariableReaches(v0, source, node) |
155+
exists(StackVariable v0 | allocatedVariableReaches(v0, source, node) |
158156
node.(AnalysedExpr).getNullSuccessor(v0) = next or
159157
freeCallOrIndirect(node, v0) or
160158
assignedToFieldOrGlobal(v0, node)
@@ -171,11 +169,11 @@ predicate allocationReaches(ControlFlowNode def, ControlFlowNode node) {
171169
exists(AllocReachability r | r.reaches(def, _, node))
172170
}
173171

174-
predicate assignedToFieldOrGlobal(LocalScopeVariable v, Expr e) {
175-
// assigned to anything except a LocalScopeVariable
172+
predicate assignedToFieldOrGlobal(StackVariable v, Expr e) {
173+
// assigned to anything except a StackVariable
176174
// (typically a field or global, but for example also *ptr = v)
177175
e.(Assignment).getRValue() = v.getAnAccess() and
178-
not e.(Assignment).getLValue().(VariableAccess).getTarget() instanceof LocalScopeVariable
176+
not e.(Assignment).getLValue().(VariableAccess).getTarget() instanceof StackVariable
179177
or
180178
exists(Expr midExpr, Function mid, int arg |
181179
// indirect assignment
@@ -192,7 +190,7 @@ predicate assignedToFieldOrGlobal(LocalScopeVariable v, Expr e) {
192190
from ControlFlowNode def, ReturnStmt ret
193191
where
194192
allocationReaches(def, ret) and
195-
not exists(LocalScopeVariable v |
193+
not exists(StackVariable v |
196194
allocatedVariableReaches(v, def, ret) and
197195
ret.getAChild*() = v.getAnAccess()
198196
)

cpp/ql/src/Critical/UseAfterFree.ql

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
*/
1111

1212
import cpp
13-
import semmle.code.cpp.controlflow.LocalScopeVariableReachability
13+
import semmle.code.cpp.controlflow.StackVariableReachability
1414

1515
/** `e` is an expression that frees the memory pointed to by `v`. */
16-
predicate isFreeExpr(Expr e, LocalScopeVariable v) {
16+
predicate isFreeExpr(Expr e, StackVariable v) {
1717
exists(VariableAccess va | va.getTarget() = v |
1818
exists(FunctionCall fc | fc = e |
1919
fc.getTarget().hasGlobalOrStdName("free") and
@@ -27,7 +27,7 @@ predicate isFreeExpr(Expr e, LocalScopeVariable v) {
2727
}
2828

2929
/** `e` is an expression that (may) dereference `v`. */
30-
predicate isDerefExpr(Expr e, LocalScopeVariable v) {
30+
predicate isDerefExpr(Expr e, StackVariable v) {
3131
v.getAnAccess() = e and dereferenced(e)
3232
or
3333
isDerefByCallExpr(_, _, e, v)
@@ -39,27 +39,27 @@ predicate isDerefExpr(Expr e, LocalScopeVariable v) {
3939
* or a source code function that dereferences the relevant
4040
* parameter.
4141
*/
42-
predicate isDerefByCallExpr(Call c, int i, VariableAccess va, LocalScopeVariable v) {
42+
predicate isDerefByCallExpr(Call c, int i, VariableAccess va, StackVariable v) {
4343
v.getAnAccess() = va and
4444
va = c.getAnArgumentSubExpr(i) and
4545
not c.passesByReference(i, va) and
4646
(c.getTarget().hasEntryPoint() implies isDerefExpr(_, c.getTarget().getParameter(i)))
4747
}
4848

49-
class UseAfterFreeReachability extends LocalScopeVariableReachability {
49+
class UseAfterFreeReachability extends StackVariableReachability {
5050
UseAfterFreeReachability() { this = "UseAfterFree" }
5151

52-
override predicate isSource(ControlFlowNode node, LocalScopeVariable v) { isFreeExpr(node, v) }
52+
override predicate isSource(ControlFlowNode node, StackVariable v) { isFreeExpr(node, v) }
5353

54-
override predicate isSink(ControlFlowNode node, LocalScopeVariable v) { isDerefExpr(node, v) }
54+
override predicate isSink(ControlFlowNode node, StackVariable v) { isDerefExpr(node, v) }
5555

56-
override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) {
56+
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
5757
definitionBarrier(v, node) or
5858
isFreeExpr(node, v)
5959
}
6060
}
6161

62-
from UseAfterFreeReachability r, LocalScopeVariable v, Expr free, Expr e
62+
from UseAfterFreeReachability r, StackVariable v, Expr free, Expr e
6363
where r.reaches(free, v, e)
6464
select e, "Memory pointed to by '" + v.getName().toString() + "' may have been previously freed $@",
6565
free, "here"

cpp/ql/src/Likely Bugs/Likely Typos/AssignWhereCompareMeant.ql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,24 @@
1212
*/
1313

1414
import cpp
15-
import semmle.code.cpp.controlflow.LocalScopeVariableReachability
15+
import semmle.code.cpp.controlflow.StackVariableReachability
1616

17-
class UndefReachability extends LocalScopeVariableReachability {
17+
class UndefReachability extends StackVariableReachability {
1818
UndefReachability() { this = "UndefReachability" }
1919

20-
override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
20+
override predicate isSource(ControlFlowNode node, StackVariable v) {
2121
candidateVariable(v) and
2222
node = v.getParentScope() and
2323
not v instanceof Parameter and
2424
not v.hasInitializer()
2525
}
2626

27-
override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
27+
override predicate isSink(ControlFlowNode node, StackVariable v) {
2828
candidateVariable(v) and
2929
node = v.getAnAccess()
3030
}
3131

32-
override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) {
32+
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
3333
node.(AssignExpr).getLValue() = v.getAnAccess()
3434
}
3535
}

cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

1313
import cpp
14-
import semmle.code.cpp.controlflow.LocalScopeVariableReachability
14+
import semmle.code.cpp.controlflow.StackVariableReachability
1515
import semmle.code.cpp.commons.NullTermination
1616

1717
/**
@@ -22,10 +22,10 @@ DeclStmt declWithNoInit(LocalVariable v) {
2222
not exists(v.getInitializer())
2323
}
2424

25-
class ImproperNullTerminationReachability extends LocalScopeVariableReachabilityWithReassignment {
25+
class ImproperNullTerminationReachability extends StackVariableReachabilityWithReassignment {
2626
ImproperNullTerminationReachability() { this = "ImproperNullTerminationReachability" }
2727

28-
override predicate isSourceActual(ControlFlowNode node, LocalScopeVariable v) {
28+
override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
2929
node = declWithNoInit(v)
3030
or
3131
exists(Call c, VariableAccess va |
@@ -36,12 +36,12 @@ class ImproperNullTerminationReachability extends LocalScopeVariableReachability
3636
)
3737
}
3838

39-
override predicate isSinkActual(ControlFlowNode node, LocalScopeVariable v) {
39+
override predicate isSinkActual(ControlFlowNode node, StackVariable v) {
4040
node.(VariableAccess).getTarget() = v and
4141
variableMustBeNullTerminated(node)
4242
}
4343

44-
override predicate isBarrier(ControlFlowNode node, LocalScopeVariable v) {
44+
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
4545
exprDefinition(v, node, _) or
4646
mayAddNullTerminator(node, v.getAnAccess()) or
4747
isSinkActual(node, v) // only report first use

cpp/ql/src/semmle/code/cpp/controlflow/internal/ConstantExprs.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,7 +924,7 @@ library class LoopEntryConditionEvaluator extends ExprEvaluator {
924924
/*
925925
* Use primitive basic blocks in reachability analysis for better performance.
926926
* This is similar to the pattern used in e.g. `DefinitionsAndUses` and
927-
* `LocalScopeVariableReachability`.
927+
* `StackVariableReachability`.
928928
*/
929929

930930
exists(PrimitiveBasicBlock bb1, int pos1 | bb1.getNode(pos1) = valueOrDef |

0 commit comments

Comments
 (0)