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

Skip to content

Commit 703db0b

Browse files
author
Robert Marsh
committed
C++: noisy output iterators in AST taint tracking
1 parent 983f54f commit 703db0b

6 files changed

Lines changed: 65 additions & 5 deletions

File tree

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
private import semmle.code.cpp.models.interfaces.DataFlow
1212
private import semmle.code.cpp.models.interfaces.Taint
13+
private import semmle.code.cpp.models.implementations.Iterator
1314

1415
private module DataFlow {
1516
import semmle.code.cpp.dataflow.internal.DataFlowUtil
@@ -186,6 +187,12 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) {
186187
exprIn = call.getQualifier()
187188
)
188189
)
190+
or
191+
exists(Variable iterator, Variable collection |
192+
assignmentViaIterator(iterator, exprIn) and
193+
isIteratorForCollection(iterator, collection) and
194+
collection.getAnAccess() = exprOut
195+
)
189196
}
190197

191198
private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
@@ -249,3 +256,27 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) {
249256
)
250257
)
251258
}
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
265+
)
266+
}
267+
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()
272+
or
273+
c.getTarget() instanceof IteratorPointerDereferenceMemberOperator and
274+
c.getQualifier() = iterator.getAnAccess()
275+
or
276+
c.getTarget() instanceof IteratorPointerDereferenceOperator and
277+
c.getArgument(0) = iterator.getAnAccess()
278+
|
279+
c = a.getLValue() and
280+
rvalue = a.getRValue()
281+
)
282+
}

cpp/ql/src/semmle/code/cpp/models/implementations/Iterator.qll

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,3 +271,15 @@ class IteratorArrayMemberOperator extends MemberFunction, TaintFunction {
271271
output.isReturnValue()
272272
}
273273
}
274+
275+
class BeginOrEndFunction extends MemberFunction, TaintFunction {
276+
BeginOrEndFunction() {
277+
this.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) and
278+
this.getType().getUnspecifiedType() instanceof Iterator
279+
}
280+
281+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
282+
input.isQualifierObject() and
283+
output.isReturnValue()
284+
}
285+
}

cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3197,7 +3197,10 @@
31973197
| vector.cpp:336:37:336:41 | call to begin | vector.cpp:337:3:337:4 | i1 | |
31983198
| vector.cpp:337:2:337:15 | ... = ... | vector.cpp:337:2:337:2 | call to operator* [post update] | |
31993199
| vector.cpp:337:3:337:4 | i1 | vector.cpp:337:2:337:2 | call to operator* | TAINT |
3200+
| vector.cpp:337:8:337:13 | call to source | vector.cpp:336:34:336:35 | v1 | TAINT |
32003201
| vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:15 | ... = ... | |
3202+
| vector.cpp:337:8:337:13 | call to source | vector.cpp:338:7:338:8 | v1 | TAINT |
3203+
| vector.cpp:337:8:337:13 | call to source | vector.cpp:354:1:354:1 | v1 | TAINT |
32013204
| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:354:1:354:1 | v1 | |
32023205
| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | |
32033206
| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | |
@@ -3216,7 +3219,11 @@
32163219
| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:341:4:341:5 | it | |
32173220
| vector.cpp:341:3:341:16 | ... = ... | vector.cpp:341:3:341:3 | call to operator* [post update] | |
32183221
| vector.cpp:341:4:341:5 | it | vector.cpp:341:3:341:3 | call to operator* | TAINT |
3222+
| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:38:340:39 | v2 | TAINT |
3223+
| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:56:340:57 | v2 | TAINT |
32193224
| vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:16 | ... = ... | |
3225+
| vector.cpp:341:9:341:14 | call to source | vector.cpp:343:7:343:8 | v2 | TAINT |
3226+
| vector.cpp:341:9:341:14 | call to source | vector.cpp:354:1:354:1 | v2 | TAINT |
32203227
| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | |
32213228
| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator* | TAINT |
32223229
| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator++ | TAINT |
@@ -3253,5 +3260,9 @@
32533260
| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:4:351:5 | it | |
32543261
| vector.cpp:351:3:351:16 | ... = ... | vector.cpp:351:3:351:3 | call to operator* [post update] | |
32553262
| vector.cpp:351:4:351:5 | it | vector.cpp:351:3:351:3 | call to operator* | TAINT |
3263+
| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:38:350:39 | v4 | TAINT |
3264+
| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:56:350:57 | v4 | TAINT |
32563265
| vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:16 | ... = ... | |
3266+
| vector.cpp:351:9:351:14 | call to source | vector.cpp:353:7:353:8 | v4 | TAINT |
3267+
| vector.cpp:351:9:351:14 | call to source | vector.cpp:354:1:354:1 | v4 | TAINT |
32573268
| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | |

cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,6 @@
326326
| vector.cpp:312:7:312:7 | d | vector.cpp:303:14:303:19 | call to source |
327327
| vector.cpp:324:7:324:8 | v2 | vector.cpp:318:15:318:20 | call to source |
328328
| vector.cpp:326:7:326:8 | v4 | vector.cpp:318:15:318:20 | call to source |
329+
| vector.cpp:338:7:338:8 | v1 | vector.cpp:337:8:337:13 | call to source |
330+
| vector.cpp:343:7:343:8 | v2 | vector.cpp:341:9:341:14 | call to source |
331+
| vector.cpp:353:7:353:8 | v4 | vector.cpp:351:9:351:14 | call to source |

cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,6 @@
275275
| vector.cpp:312:7:312:7 | vector.cpp:303:14:303:19 | AST only |
276276
| vector.cpp:324:7:324:8 | vector.cpp:318:15:318:20 | AST only |
277277
| vector.cpp:326:7:326:8 | vector.cpp:318:15:318:20 | AST only |
278+
| vector.cpp:338:7:338:8 | vector.cpp:337:8:337:13 | AST only |
279+
| vector.cpp:343:7:343:8 | vector.cpp:341:9:341:14 | AST only |
280+
| vector.cpp:353:7:353:8 | vector.cpp:351:9:351:14 | AST only |

cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ void test_range_based_for_loop_vector(int source1) {
2121
}
2222

2323
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
24-
sink(*it); // tainted
24+
sink(*it); // tainted [NOT DETECTED by IR]
2525
}
2626

2727
for(int& x : v) {
@@ -335,12 +335,12 @@ void test_vector_output_iterator() {
335335

336336
std::vector<int>::iterator i1 = v1.begin();
337337
*i1 = source();
338-
sink(v1); // tainted [NOT DETECTED]
338+
sink(v1); // tainted [NOT DETECTED by IR]
339339

340340
for(std::vector<int>::iterator it = v2.begin(); it != v2.end(); ++it) {
341-
*it = source(); // tainted [NOT DETECTED]
341+
*it = source();
342342
}
343-
sink(v2);
343+
sink(v2); // tainted [NOT DETECTED by IR]
344344

345345
for(int& x : v3) {
346346
x = source();
@@ -350,5 +350,5 @@ void test_vector_output_iterator() {
350350
for(std::vector<int>::iterator it = v4.begin(); it != v4.end(); ++it) {
351351
*it = source();
352352
}
353-
sink(v4); // tainted [NOT DETECTED]
353+
sink(v4); // tainted [NOT DETECTED by IR]
354354
}

0 commit comments

Comments
 (0)