C++: Model std::string constructors and container constructors that use iterators.

This commit is contained in:
Geoffrey White
2020-09-02 17:29:23 +01:00
parent 1ac0aa169d
commit d4cbb25e09
7 changed files with 60 additions and 3 deletions

View File

@@ -27,9 +27,17 @@ class StdSequenceContainerConstructor extends Constructor, TaintFunction {
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
}
/**
* Gets the index of a parameter to this function that is an iterator.
*/
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// taint flow from any parameter of the value type to the returned object
input.isParameterDeref(getAValueTypeParameterIndex()) and
(
input.isParameterDeref(getAValueTypeParameterIndex()) or
input.isParameter(getAnIteratorParameterIndex())
) and
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
}
}

View File

@@ -14,6 +14,43 @@ class StdBasicString extends TemplateClass {
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
}
/**
* Additional model for `std::string` constructors that reference the character
* type of the container, or an iterator. For example construction from
* iterators:
* ```
* std::string b(a.begin(), a.end());
* ```
*/
class StdStringConstructor extends Constructor, TaintFunction {
StdStringConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_string") }
/**
* Gets the index of a parameter to this function that is a string (or
* character).
*/
int getAStringParameterIndex() {
getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *`
getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &`
getParameter(result).getUnspecifiedType() =
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT`
}
/**
* Gets the index of a parameter to this function that is an iterator.
*/
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// taint flow from any parameter of the value type to the returned object
(
input.isParameterDeref(getAStringParameterIndex()) or
input.isParameter(getAnIteratorParameterIndex())
) and
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
}
}
/**
* The `std::string` function `c_str`.
*/

View File

@@ -1225,14 +1225,18 @@
| string.cpp:500:17:500:18 | ref arg s1 | string.cpp:503:7:503:8 | s1 | |
| string.cpp:500:17:500:18 | s1 | string.cpp:500:20:500:24 | call to begin | TAINT |
| string.cpp:500:17:500:37 | call to basic_string | string.cpp:505:7:505:8 | s3 | |
| string.cpp:500:20:500:24 | call to begin | string.cpp:500:17:500:37 | call to basic_string | TAINT |
| string.cpp:500:29:500:30 | ref arg s1 | string.cpp:503:7:503:8 | s1 | |
| string.cpp:500:29:500:30 | s1 | string.cpp:500:32:500:34 | call to end | TAINT |
| string.cpp:500:32:500:34 | call to end | string.cpp:500:17:500:37 | call to basic_string | TAINT |
| string.cpp:501:17:501:18 | ref arg s2 | string.cpp:501:29:501:30 | s2 | |
| string.cpp:501:17:501:18 | ref arg s2 | string.cpp:504:7:504:8 | s2 | |
| string.cpp:501:17:501:18 | s2 | string.cpp:501:20:501:24 | call to begin | TAINT |
| string.cpp:501:17:501:37 | call to basic_string | string.cpp:506:7:506:8 | s4 | |
| string.cpp:501:20:501:24 | call to begin | string.cpp:501:17:501:37 | call to basic_string | TAINT |
| string.cpp:501:29:501:30 | ref arg s2 | string.cpp:504:7:504:8 | s2 | |
| string.cpp:501:29:501:30 | s2 | string.cpp:501:32:501:34 | call to end | TAINT |
| string.cpp:501:32:501:34 | call to end | string.cpp:501:17:501:37 | call to basic_string | TAINT |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | |
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | |
@@ -3030,18 +3034,22 @@
| vector.cpp:320:22:320:23 | v1 | vector.cpp:320:25:320:29 | call to begin | TAINT |
| vector.cpp:320:22:320:42 | call to vector | vector.cpp:325:7:325:8 | v3 | |
| vector.cpp:320:22:320:42 | call to vector | vector.cpp:327:1:327:1 | v3 | |
| vector.cpp:320:25:320:29 | call to begin | vector.cpp:320:22:320:42 | call to vector | TAINT |
| vector.cpp:320:34:320:35 | ref arg v1 | vector.cpp:323:7:323:8 | v1 | |
| vector.cpp:320:34:320:35 | ref arg v1 | vector.cpp:327:1:327:1 | v1 | |
| vector.cpp:320:34:320:35 | v1 | vector.cpp:320:37:320:39 | call to end | TAINT |
| vector.cpp:320:37:320:39 | call to end | vector.cpp:320:22:320:42 | call to vector | TAINT |
| vector.cpp:321:22:321:23 | ref arg v2 | vector.cpp:321:34:321:35 | v2 | |
| vector.cpp:321:22:321:23 | ref arg v2 | vector.cpp:324:7:324:8 | v2 | |
| vector.cpp:321:22:321:23 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | |
| vector.cpp:321:22:321:23 | v2 | vector.cpp:321:25:321:29 | call to begin | TAINT |
| vector.cpp:321:22:321:42 | call to vector | vector.cpp:326:7:326:8 | v4 | |
| vector.cpp:321:22:321:42 | call to vector | vector.cpp:327:1:327:1 | v4 | |
| vector.cpp:321:25:321:29 | call to begin | vector.cpp:321:22:321:42 | call to vector | TAINT |
| vector.cpp:321:34:321:35 | ref arg v2 | vector.cpp:324:7:324:8 | v2 | |
| vector.cpp:321:34:321:35 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | |
| vector.cpp:321:34:321:35 | v2 | vector.cpp:321:37:321:39 | call to end | TAINT |
| vector.cpp:321:37:321:39 | call to end | vector.cpp:321:22:321:42 | call to vector | TAINT |
| vector.cpp:323:7:323:8 | ref arg v1 | vector.cpp:327:1:327:1 | v1 | |
| vector.cpp:324:7:324:8 | ref arg v2 | vector.cpp:327:1:327:1 | v2 | |
| vector.cpp:325:7:325:8 | ref arg v3 | vector.cpp:327:1:327:1 | v3 | |

View File

@@ -503,5 +503,5 @@ void test_constructors_more() {
sink(s1);
sink(s2); // tainted
sink(s3);
sink(s4); // tainted [NOT DETECTED]
sink(s4); // tainted
}

View File

@@ -137,6 +137,7 @@
| string.cpp:488:8:488:8 | h | string.cpp:482:18:482:23 | call to source |
| string.cpp:491:8:491:9 | s6 | string.cpp:482:18:482:23 | call to source |
| string.cpp:504:7:504:8 | s2 | string.cpp:497:14:497:19 | call to source |
| string.cpp:506:7:506:8 | s4 | string.cpp:497:14:497:19 | call to source |
| structlikeclass.cpp:35:8:35:9 | s1 | structlikeclass.cpp:29:22:29:27 | call to source |
| structlikeclass.cpp:36:8:36:9 | s2 | structlikeclass.cpp:30:24:30:29 | call to source |
| structlikeclass.cpp:37:8:37:9 | s3 | structlikeclass.cpp:29:22:29:27 | call to source |
@@ -306,3 +307,4 @@
| vector.cpp:311:9:311:14 | call to insert | vector.cpp:303:14:303:19 | call to source |
| 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 |

View File

@@ -147,6 +147,7 @@
| string.cpp:488:8:488:8 | string.cpp:482:18:482:23 | AST only |
| string.cpp:491:8:491:9 | string.cpp:482:18:482:23 | AST only |
| string.cpp:504:7:504:8 | string.cpp:497:14:497:19 | AST only |
| string.cpp:506:7:506:8 | string.cpp:497:14:497:19 | AST only |
| structlikeclass.cpp:35:8:35:9 | structlikeclass.cpp:29:22:29:27 | AST only |
| structlikeclass.cpp:36:8:36:9 | structlikeclass.cpp:30:24:30:29 | AST only |
| structlikeclass.cpp:37:8:37:9 | structlikeclass.cpp:29:22:29:27 | AST only |
@@ -255,3 +256,4 @@
| vector.cpp:311:9:311:14 | vector.cpp:303:14:303:19 | AST only |
| 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 |

View File

@@ -323,5 +323,5 @@ void test_constructors_more() {
sink(v1);
sink(v2); // tainted
sink(v3);
sink(v4); // tainted [NOT DETECTED]
sink(v4); // tainted
}