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

Skip to content

Commit faae2e7

Browse files
committed
C++: Implement field flow for operator[] writes and pointer deref writes.
1 parent 3a7bf2a commit faae2e7

3 files changed

Lines changed: 75 additions & 16 deletions

File tree

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,6 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
264264
t instanceof Union
265265
or
266266
t instanceof ArrayType
267-
or
268-
// Buffers of unknown size
269-
t instanceof UnknownType
270267
)
271268
or
272269
exists(BinaryInstruction bin |

cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,24 +181,41 @@ private class CollectionContent extends Content, TCollectionContent {
181181
}
182182

183183
private class ArrayContent extends Content, TArrayContent {
184-
override string toString() { result = "array" }
184+
ArrayContent() { this = TArrayContent() }
185+
186+
override string toString() { result = "array content" }
185187
}
186188

187-
private predicate storeStepNoChi(Node node1, Content f, PostUpdateNode node2) {
189+
private predicate fieldStoreStepNoChi(Node node1, FieldContent f, PostUpdateNode node2) {
188190
exists(FieldAddressInstruction fa, StoreInstruction store |
189191
store = node2.asInstruction() and
190192
store.getDestinationAddress() = fa and
191193
store.getSourceValue() = node1.asInstruction() and
192-
f.(FieldContent).getField() = fa.getField()
194+
f.getField() = fa.getField()
193195
)
194196
}
195197

196-
private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
198+
private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode node2) {
197199
exists(FieldAddressInstruction fa, StoreInstruction store |
198200
node1.asInstruction() = store and
199201
store.getDestinationAddress() = fa and
200202
node2.asInstruction().(ChiInstruction).getPartial() = store and
201-
f.(FieldContent).getField() = fa.getField()
203+
f.getField() = fa.getField()
204+
)
205+
}
206+
207+
private predicate arrayStoreStepChi(Node node1, Content a, PostUpdateNode node2) {
208+
a instanceof ArrayContent and
209+
exists(StoreInstruction store |
210+
node1.asInstruction() = store and
211+
(
212+
// `x[i] = taint()`
213+
store.getDestinationAddress() instanceof PointerAddInstruction
214+
or
215+
// `*p = taint()`
216+
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
217+
) and
218+
node2.asInstruction().(ChiInstruction).getPartial() = store
202219
)
203220
}
204221

@@ -208,16 +225,12 @@ private predicate storeStepChi(Node node1, Content f, PostUpdateNode node2) {
208225
* value of `node1`.
209226
*/
210227
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
211-
storeStepNoChi(node1, f, node2) or
212-
storeStepChi(node1, f, node2)
228+
fieldStoreStepNoChi(node1, f, node2) or
229+
fieldStoreStepChi(node1, f, node2) or
230+
arrayStoreStepChi(node1, f, node2)
213231
}
214232

215-
/**
216-
* Holds if data can flow from `node1` to `node2` via a read of `f`.
217-
* Thus, `node1` references an object with a field `f` whose value ends up in
218-
* `node2`.
219-
*/
220-
predicate readStep(Node node1, Content f, Node node2) {
233+
private predicate fieldReadStep(Node node1, FieldContent f, Node node2) {
221234
exists(FieldAddressInstruction fa, LoadInstruction load |
222235
load.getSourceAddress() = fa and
223236
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
@@ -226,6 +239,24 @@ predicate readStep(Node node1, Content f, Node node2) {
226239
)
227240
}
228241

242+
private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
243+
a = TArrayContent() and
244+
exists(LoadInstruction load |
245+
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
246+
load = node2.asInstruction()
247+
)
248+
}
249+
250+
/**
251+
* Holds if data can flow from `node1` to `node2` via a read of `f`.
252+
* Thus, `node1` references an object with a field `f` whose value ends up in
253+
* `node2`.
254+
*/
255+
predicate readStep(Node node1, Content f, Node node2) {
256+
fieldReadStep(node1, f, node2) or
257+
arrayReadStep(node1, f, node2)
258+
}
259+
229260
/**
230261
* Holds if values stored inside content `c` are cleared at node `n`.
231262
*/

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,37 @@ private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNod
377377
}
378378
}
379379

380+
private class ArrayStoreNode extends PartialDefinitionNode {
381+
override ChiInstruction instr;
382+
PointerAddInstruction add;
383+
384+
ArrayStoreNode() {
385+
not instr.isResultConflated() and
386+
exists(StoreInstruction store |
387+
instr.getPartial() = store and
388+
add = store.getDestinationAddress()
389+
)
390+
}
391+
392+
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
393+
394+
override Expr getDefinedExpr() { result = add.getLeft().getUnconvertedResultExpression() }
395+
}
396+
397+
private class PointerStoreNode extends PostUpdateNode {
398+
override ChiInstruction instr;
399+
400+
PointerStoreNode() {
401+
not instr.isResultConflated() and
402+
exists(StoreInstruction store |
403+
instr.getPartial() = store and
404+
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
405+
)
406+
}
407+
408+
override Node getPreUpdateNode() { result.asOperand() = instr.getTotalOperand() }
409+
}
410+
380411
/**
381412
* A node that represents the value of a variable after a function call that
382413
* may have changed the variable because it's passed by reference.

0 commit comments

Comments
 (0)