C++: noisy output iterators in AST taint tracking

This commit is contained in:
Robert Marsh
2020-08-25 15:26:18 -07:00
parent 983f54f11a
commit 703db0b9a6
6 changed files with 65 additions and 5 deletions

View File

@@ -10,6 +10,7 @@
private import semmle.code.cpp.models.interfaces.DataFlow
private import semmle.code.cpp.models.interfaces.Taint
private import semmle.code.cpp.models.implementations.Iterator
private module DataFlow {
import semmle.code.cpp.dataflow.internal.DataFlowUtil
@@ -186,6 +187,12 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) {
exprIn = call.getQualifier()
)
)
or
exists(Variable iterator, Variable collection |
assignmentViaIterator(iterator, exprIn) and
isIteratorForCollection(iterator, collection) and
collection.getAnAccess() = exprOut
)
}
private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
@@ -249,3 +256,27 @@ private predicate exprToPartialDefinitionStep(Expr exprIn, Expr exprOut) {
)
)
}
private predicate isIteratorForCollection(Variable iterator, Variable collection) {
exists(Call beginOrEnd |
beginOrEnd.getTarget() instanceof BeginOrEndFunction and
beginOrEnd.getQualifier() = collection.getAnAccess() and
iterator.getAnAssignedValue() = beginOrEnd
)
}
private predicate assignmentViaIterator(Variable iterator, Expr rvalue) {
exists(Assignment a, Call c |
c.getTarget() instanceof IteratorArrayMemberOperator and
c.getQualifier() = iterator.getAnAccess()
or
c.getTarget() instanceof IteratorPointerDereferenceMemberOperator and
c.getQualifier() = iterator.getAnAccess()
or
c.getTarget() instanceof IteratorPointerDereferenceOperator and
c.getArgument(0) = iterator.getAnAccess()
|
c = a.getLValue() and
rvalue = a.getRValue()
)
}

View File

@@ -271,3 +271,15 @@ class IteratorArrayMemberOperator extends MemberFunction, TaintFunction {
output.isReturnValue()
}
}
class BeginOrEndFunction extends MemberFunction, TaintFunction {
BeginOrEndFunction() {
this.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) and
this.getType().getUnspecifiedType() instanceof Iterator
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierObject() and
output.isReturnValue()
}
}

View File

@@ -3197,7 +3197,10 @@
| vector.cpp:336:37:336:41 | call to begin | vector.cpp:337:3:337:4 | i1 | |
| vector.cpp:337:2:337:15 | ... = ... | vector.cpp:337:2:337:2 | call to operator* [post update] | |
| vector.cpp:337:3:337:4 | i1 | vector.cpp:337:2:337:2 | call to operator* | TAINT |
| vector.cpp:337:8:337:13 | call to source | vector.cpp:336:34:336:35 | v1 | TAINT |
| vector.cpp:337:8:337:13 | call to source | vector.cpp:337:2:337:15 | ... = ... | |
| vector.cpp:337:8:337:13 | call to source | vector.cpp:338:7:338:8 | v1 | TAINT |
| vector.cpp:337:8:337:13 | call to source | vector.cpp:354:1:354:1 | v1 | TAINT |
| vector.cpp:338:7:338:8 | ref arg v1 | vector.cpp:354:1:354:1 | v1 | |
| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:340:56:340:57 | v2 | |
| vector.cpp:340:38:340:39 | ref arg v2 | vector.cpp:343:7:343:8 | v2 | |
@@ -3216,7 +3219,11 @@
| vector.cpp:340:68:340:69 | ref arg it | vector.cpp:341:4:341:5 | it | |
| vector.cpp:341:3:341:16 | ... = ... | vector.cpp:341:3:341:3 | call to operator* [post update] | |
| vector.cpp:341:4:341:5 | it | vector.cpp:341:3:341:3 | call to operator* | TAINT |
| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:38:340:39 | v2 | TAINT |
| vector.cpp:341:9:341:14 | call to source | vector.cpp:340:56:340:57 | v2 | TAINT |
| vector.cpp:341:9:341:14 | call to source | vector.cpp:341:3:341:16 | ... = ... | |
| vector.cpp:341:9:341:14 | call to source | vector.cpp:343:7:343:8 | v2 | TAINT |
| vector.cpp:341:9:341:14 | call to source | vector.cpp:354:1:354:1 | v2 | TAINT |
| vector.cpp:343:7:343:8 | ref arg v2 | vector.cpp:354:1:354:1 | v2 | |
| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator* | TAINT |
| vector.cpp:345:15:345:15 | (__begin) | vector.cpp:345:15:345:15 | call to operator++ | TAINT |
@@ -3253,5 +3260,9 @@
| vector.cpp:350:68:350:69 | ref arg it | vector.cpp:351:4:351:5 | it | |
| vector.cpp:351:3:351:16 | ... = ... | vector.cpp:351:3:351:3 | call to operator* [post update] | |
| vector.cpp:351:4:351:5 | it | vector.cpp:351:3:351:3 | call to operator* | TAINT |
| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:38:350:39 | v4 | TAINT |
| vector.cpp:351:9:351:14 | call to source | vector.cpp:350:56:350:57 | v4 | TAINT |
| vector.cpp:351:9:351:14 | call to source | vector.cpp:351:3:351:16 | ... = ... | |
| vector.cpp:351:9:351:14 | call to source | vector.cpp:353:7:353:8 | v4 | TAINT |
| vector.cpp:351:9:351:14 | call to source | vector.cpp:354:1:354:1 | v4 | TAINT |
| vector.cpp:353:7:353:8 | ref arg v4 | vector.cpp:354:1:354:1 | v4 | |

View File

@@ -326,3 +326,6 @@
| vector.cpp:312:7:312:7 | d | vector.cpp:303:14:303:19 | call to source |
| vector.cpp:324:7:324:8 | v2 | vector.cpp:318:15:318:20 | call to source |
| vector.cpp:326:7:326:8 | v4 | vector.cpp:318:15:318:20 | call to source |
| vector.cpp:338:7:338:8 | v1 | vector.cpp:337:8:337:13 | call to source |
| vector.cpp:343:7:343:8 | v2 | vector.cpp:341:9:341:14 | call to source |
| vector.cpp:353:7:353:8 | v4 | vector.cpp:351:9:351:14 | call to source |

View File

@@ -275,3 +275,6 @@
| vector.cpp:312:7:312:7 | vector.cpp:303:14:303:19 | AST only |
| vector.cpp:324:7:324:8 | vector.cpp:318:15:318:20 | AST only |
| vector.cpp:326:7:326:8 | vector.cpp:318:15:318:20 | AST only |
| vector.cpp:338:7:338:8 | vector.cpp:337:8:337:13 | AST only |
| vector.cpp:343:7:343:8 | vector.cpp:341:9:341:14 | AST only |
| vector.cpp:353:7:353:8 | vector.cpp:351:9:351:14 | AST only |

View File

@@ -21,7 +21,7 @@ void test_range_based_for_loop_vector(int source1) {
}
for(std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
sink(*it); // tainted
sink(*it); // tainted [NOT DETECTED by IR]
}
for(int& x : v) {
@@ -335,12 +335,12 @@ void test_vector_output_iterator() {
std::vector<int>::iterator i1 = v1.begin();
*i1 = source();
sink(v1); // tainted [NOT DETECTED]
sink(v1); // tainted [NOT DETECTED by IR]
for(std::vector<int>::iterator it = v2.begin(); it != v2.end(); ++it) {
*it = source(); // tainted [NOT DETECTED]
*it = source();
}
sink(v2);
sink(v2); // tainted [NOT DETECTED by IR]
for(int& x : v3) {
x = source();
@@ -350,5 +350,5 @@ void test_vector_output_iterator() {
for(std::vector<int>::iterator it = v4.begin(); it != v4.end(); ++it) {
*it = source();
}
sink(v4); // tainted [NOT DETECTED]
sink(v4); // tainted [NOT DETECTED by IR]
}