Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eab1557

Browse files
author
Robert Marsh
committed
C++: output iterator flow via FlowVar
1 parent 13c45b6 commit eab1557

7 files changed

Lines changed: 287 additions & 73 deletions

File tree

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,12 @@ abstract class PostUpdateNode extends Node {
283283
override Location getLocation() { result = getPreUpdateNode().getLocation() }
284284
}
285285

286-
private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
286+
private abstract class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
287287
PartialDefinition pd;
288288

289-
PartialDefinitionNode() { this = TPartialDefinitionNode(pd) }
290-
291-
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
289+
PartialDefinitionNode() {
290+
this = TPartialDefinitionNode(pd)
291+
}
292292

293293
override Location getLocation() { result = pd.getActualLocation() }
294294

@@ -297,6 +297,18 @@ private class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNo
297297
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
298298
}
299299

300+
private class VariablePartialDefinitionNode extends PartialDefinitionNode {
301+
override VariablePartialDefinition pd;
302+
303+
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
304+
}
305+
306+
private class IteratorPartialDefinitionNode extends PartialDefinitionNode {
307+
override IteratorPartialDefinition pd;
308+
309+
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
310+
}
311+
300312
/**
301313
* A post-update node on the `e->f` in `f(&e->f)` (and other forms).
302314
*/

cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll

Lines changed: 80 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import cpp
66
private import semmle.code.cpp.controlflow.SSA
77
private import semmle.code.cpp.dataflow.internal.SubBasicBlocks
88
private import semmle.code.cpp.dataflow.internal.AddressFlow
9+
private import semmle.code.cpp.models.implementations.Iterator
910

1011
/**
1112
* A conceptual variable that is assigned only once, like an SSA variable. This
@@ -109,20 +110,16 @@ class FlowVar extends TFlowVar {
109110
*/
110111
private module PartialDefinitions {
111112
class PartialDefinition extends Expr {
112-
Expr innerDefinedExpr;
113113
ControlFlowNode node;
114114

115115
PartialDefinition() {
116-
exists(Expr convertedInner |
117-
valueToUpdate(convertedInner, this.getFullyConverted(), node) and
118-
innerDefinedExpr = convertedInner.getUnconverted() and
119-
not this instanceof Conversion
120-
)
116+
valueToUpdate(_, this.getFullyConverted(), node) and
117+
not this instanceof Conversion
121118
}
122119

123-
deprecated predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
120+
deprecated predicate partiallyDefines(Variable v) { none() }
124121

125-
deprecated predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
122+
deprecated predicate partiallyDefinesThis(ThisExpr e) { none() }
126123

127124
/**
128125
* Gets the subBasicBlock where this `PartialDefinition` is defined.
@@ -133,10 +130,9 @@ private module PartialDefinitions {
133130
* Holds if this `PartialDefinition` defines variable `v` at control-flow
134131
* node `cfn`.
135132
*/
136-
pragma[noinline]
133+
pragma[noinline] // does this work with a dispred?
137134
predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
138-
innerDefinedExpr = v.getAnAccess() and
139-
cfn = node
135+
none()
140136
}
141137

142138
/**
@@ -147,10 +143,7 @@ private module PartialDefinitions {
147143
* - `inner` = `... .x`, `outer` = `&...`
148144
* - `inner` = `a`, `outer` = `*`
149145
*/
150-
predicate definesExpressions(Expr inner, Expr outer) {
151-
inner = innerDefinedExpr and
152-
outer = this
153-
}
146+
predicate definesExpressions(Expr inner, Expr outer) { none() }
154147

155148
/**
156149
* Gets the location of this element, adjusted to avoid unknown locations
@@ -166,6 +159,68 @@ private module PartialDefinitions {
166159
}
167160
}
168161

162+
class IteratorPartialDefinition extends PartialDefinition {
163+
Variable collection;
164+
Call innerDefinedExpr;
165+
166+
IteratorPartialDefinition() {
167+
exists(Expr convertedInner |
168+
valueToUpdate(convertedInner, this.getFullyConverted(), node) and
169+
innerDefinedExpr = convertedInner.getUnconverted() and
170+
innerDefinedExpr.getQualifier() = getAnIteratorAccess(collection) and
171+
innerDefinedExpr.getTarget() instanceof IteratorPointerDereferenceMemberOperator
172+
)
173+
}
174+
175+
deprecated override predicate partiallyDefines(Variable v) { v = collection }
176+
177+
deprecated override predicate partiallyDefinesThis(ThisExpr e) { none() }
178+
179+
override predicate definesExpressions(Expr inner, Expr outer) {
180+
inner = innerDefinedExpr and
181+
outer = this
182+
}
183+
184+
override predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
185+
v = collection and
186+
cfn = node
187+
}
188+
}
189+
190+
class VariablePartialDefinition extends PartialDefinition {
191+
Expr innerDefinedExpr;
192+
193+
VariablePartialDefinition() {
194+
exists(Expr convertedInner |
195+
valueToUpdate(convertedInner, this.getFullyConverted(), node) and
196+
innerDefinedExpr = convertedInner.getUnconverted() and
197+
not this instanceof Conversion
198+
)
199+
}
200+
201+
deprecated override predicate partiallyDefines(Variable v) { innerDefinedExpr = v.getAnAccess() }
202+
203+
deprecated override predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
204+
205+
/**
206+
* Holds if this partial definition may modify `inner` (or what it points
207+
* to) through `outer`. These expressions will never be `Conversion`s.
208+
*
209+
* For example, in `f(& (*a).x)`, there are two results:
210+
* - `inner` = `... .x`, `outer` = `&...`
211+
* - `inner` = `a`, `outer` = `*`
212+
*/
213+
override predicate definesExpressions(Expr inner, Expr outer) {
214+
inner = innerDefinedExpr and
215+
outer = this
216+
}
217+
218+
override predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
219+
innerDefinedExpr = v.getAnAccess() and
220+
cfn = node
221+
}
222+
}
223+
169224
/**
170225
* A partial definition that's a definition by reference.
171226
*/
@@ -686,9 +741,7 @@ module FlowVar_internal {
686741
* `node instanceof Initializer` is covered by `initializer` instead of this
687742
* predicate.
688743
*/
689-
predicate assignmentLikeOperation(
690-
ControlFlowNode node, Variable v, Expr assignedExpr
691-
) {
744+
predicate assignmentLikeOperation(ControlFlowNode node, Variable v, Expr assignedExpr) {
692745
// Together, the two following cases cover `Assignment`
693746
node =
694747
any(AssignExpr ae |
@@ -715,6 +768,15 @@ module FlowVar_internal {
715768
)
716769
}
717770

771+
Expr getAnIteratorAccess(Variable collection) {
772+
exists(Call c, SsaDefinition def, Variable iterator |
773+
c.getQualifier() = collection.getAnAccess() and
774+
c.getTarget() instanceof BeginOrEndFunction and
775+
def.getAnUltimateDefiningValue(iterator) = c and
776+
result = def.getAUse(iterator)
777+
)
778+
}
779+
718780
/**
719781
* Holds if `v` is initialized to have value `assignedExpr`.
720782
*/

cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,6 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) {
187187
exprIn = call.getQualifier()
188188
)
189189
)
190-
or
191-
exists(Variable iterator, Variable collection |
192-
assignmentViaIterator(iterator, exprIn) and
193-
isIteratorForCollection(iterator, collection) and
194-
collection.getAnAccess() = exprOut
195-
)
196190
}
197191

198192
private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
@@ -255,28 +249,18 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) {
255249
exprIn = call.getArgument(argInIndex)
256250
)
257251
)
258-
}
259-
260-
private predicate isIteratorForCollection(Variable iterator, Variable collection) {
261-
exists(Call beginOrEnd |
262-
beginOrEnd.getTarget() instanceof BeginOrEndFunction and
263-
beginOrEnd.getQualifier() = collection.getAnAccess() and
264-
iterator.getAnAssignedValue() = beginOrEnd
252+
or
253+
exists(Assignment a |
254+
iteratorDereference(exprOut) and
255+
a.getLValue() = exprOut and
256+
a.getRValue() = exprIn
265257
)
266258
}
267259

268-
private predicate assignmentViaIterator(Variable iterator, Expr rvalue) {
269-
exists(Assignment a, Call c |
270-
c.getTarget() instanceof IteratorArrayMemberOperator and
271-
c.getQualifier() = iterator.getAnAccess()
260+
private predicate iteratorDereference(Call c) {
261+
c.getTarget() instanceof IteratorArrayMemberOperator
272262
or
273-
c.getTarget() instanceof IteratorPointerDereferenceMemberOperator and
274-
c.getQualifier() = iterator.getAnAccess()
263+
c.getTarget() instanceof IteratorPointerDereferenceMemberOperator
275264
or
276-
c.getTarget() instanceof IteratorPointerDereferenceOperator and
277-
c.getArgument(0) = iterator.getAnAccess()
278-
|
279-
c = a.getLValue() and
280-
rvalue = a.getRValue()
281-
)
265+
c.getTarget() instanceof IteratorPointerDereferenceOperator
282266
}

0 commit comments

Comments
 (0)