Skip to content

Commit d56a033

Browse files
authored
Merge pull request #4107 from geoffw0/vecmethods
C++: Initial models for std::vector
2 parents 2a8ff87 + 3d171f3 commit d56a033

File tree

8 files changed

+727
-78
lines changed

8 files changed

+727
-78
lines changed

change-notes/1.26/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ The following changes in version 1.26 affect C/C++ analysis in all applications.
1919

2020
## Changes to libraries
2121

22+
* The models library now models some taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
2223
* The models library now models many more taint flows through `std::string`.
2324
* The `SimpleRangeAnalysis` library now supports multiplications of the form
2425
`e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant.

cpp/ql/src/semmle/code/cpp/models/Models.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ private import implementations.Strcat
1313
private import implementations.Strcpy
1414
private import implementations.Strdup
1515
private import implementations.Strftime
16+
private import implementations.StdContainer
1617
private import implementations.StdString
1718
private import implementations.Swap
1819
private import implementations.GetDelim
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/**
2+
* Provides models for C++ containers `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
3+
*/
4+
5+
import semmle.code.cpp.models.interfaces.Taint
6+
7+
/**
8+
* Additional model for standard container constructors that reference the
9+
* value type of the container (that is, the `T` in `std::vector<T>`). For
10+
* example the fill constructor:
11+
* ```
12+
* std::vector<std::string> v(100, potentially_tainted_string);
13+
* ```
14+
*/
15+
class StdSequenceContainerConstructor extends Constructor, TaintFunction {
16+
StdSequenceContainerConstructor() {
17+
this.getDeclaringType().hasQualifiedName("std", "vector") or
18+
this.getDeclaringType().hasQualifiedName("std", "deque") or
19+
this.getDeclaringType().hasQualifiedName("std", "list") or
20+
this.getDeclaringType().hasQualifiedName("std", "forward_list")
21+
}
22+
23+
/**
24+
* Gets the index of a parameter to this function that is a reference to the
25+
* value type of the container.
26+
*/
27+
int getAValueTypeParameterIndex() {
28+
getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
29+
getDeclaringType().getTemplateArgument(0) // i.e. the `T` of this `std::vector<T>`
30+
}
31+
32+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
33+
// taint flow from any parameter of the value type to the returned object
34+
input.isParameterDeref(getAValueTypeParameterIndex()) and
35+
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
36+
}
37+
}
38+
39+
/**
40+
* The standard container functions `push_back` and `push_front`.
41+
*/
42+
class StdSequenceContainerPush extends TaintFunction {
43+
StdSequenceContainerPush() {
44+
this.hasQualifiedName("std", "vector", "push_back") or
45+
this.hasQualifiedName("std", "deque", "push_back") or
46+
this.hasQualifiedName("std", "deque", "push_front") or
47+
this.hasQualifiedName("std", "list", "push_back") or
48+
this.hasQualifiedName("std", "list", "push_front") or
49+
this.hasQualifiedName("std", "forward_list", "push_front")
50+
}
51+
52+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
53+
// flow from parameter to qualifier
54+
input.isParameterDeref(0) and
55+
output.isQualifierObject()
56+
}
57+
}
58+
59+
/**
60+
* The standard container functions `front` and `back`.
61+
*/
62+
class StdSequenceContainerFrontBack extends TaintFunction {
63+
StdSequenceContainerFrontBack() {
64+
this.hasQualifiedName("std", "array", "front") or
65+
this.hasQualifiedName("std", "array", "back") or
66+
this.hasQualifiedName("std", "vector", "front") or
67+
this.hasQualifiedName("std", "vector", "back") or
68+
this.hasQualifiedName("std", "deque", "front") or
69+
this.hasQualifiedName("std", "deque", "back") or
70+
this.hasQualifiedName("std", "list", "front") or
71+
this.hasQualifiedName("std", "list", "back") or
72+
this.hasQualifiedName("std", "forward_list", "front")
73+
}
74+
75+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
76+
// flow from object to returned reference
77+
input.isQualifierObject() and
78+
output.isReturnValueDeref()
79+
}
80+
}
81+
82+
/**
83+
* The standard container `swap` functions.
84+
*/
85+
class StdSequenceContainerSwap extends TaintFunction {
86+
StdSequenceContainerSwap() {
87+
this.hasQualifiedName("std", "array", "swap") or
88+
this.hasQualifiedName("std", "vector", "swap") or
89+
this.hasQualifiedName("std", "deque", "swap") or
90+
this.hasQualifiedName("std", "list", "swap") or
91+
this.hasQualifiedName("std", "forward_list", "swap")
92+
}
93+
94+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
95+
// container1.swap(container2)
96+
input.isQualifierObject() and
97+
output.isParameterDeref(0)
98+
or
99+
input.isParameterDeref(0) and
100+
output.isQualifierObject()
101+
}
102+
}

0 commit comments

Comments
 (0)