Skip to content

Commit b7774b2

Browse files
authored
Merge pull request #4201 from geoffw0/insert
C++: Model iterator versions of string and vector methods
2 parents f180497 + 50d9a85 commit b7774b2

File tree

9 files changed

+756
-41
lines changed

9 files changed

+756
-41
lines changed

change-notes/1.26/analysis-cpp.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +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`.
22+
* The models library now models many taint flows through `std::array`, `std::vector`, `std::deque`, `std::list` and `std::forward_list`.
2323
* The models library now models many more taint flows through `std::string`.
2424
* The `SimpleRangeAnalysis` library now supports multiplications of the form
2525
`e1 * e2` and `x *= e2` when `e1` and `e2` are unsigned or constant.

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

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44

55
import semmle.code.cpp.models.interfaces.Taint
6+
import semmle.code.cpp.models.implementations.Iterator
67

78
/**
89
* Additional model for standard container constructors that reference the
@@ -26,9 +27,17 @@ class StdSequenceContainerConstructor extends Constructor, TaintFunction {
2627
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
2728
}
2829

30+
/**
31+
* Gets the index of a parameter to this function that is an iterator.
32+
*/
33+
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
34+
2935
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
3036
// taint flow from any parameter of the value type to the returned object
31-
input.isParameterDeref(getAValueTypeParameterIndex()) and
37+
(
38+
input.isParameterDeref(getAValueTypeParameterIndex()) or
39+
input.isParameter(getAnIteratorParameterIndex())
40+
) and
3241
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
3342
}
3443
}
@@ -88,6 +97,43 @@ class StdSequenceContainerFrontBack extends TaintFunction {
8897
}
8998
}
9099

100+
/**
101+
* The standard container functions `insert` and `insert_after`.
102+
*/
103+
class StdSequenceContainerInsert extends TaintFunction {
104+
StdSequenceContainerInsert() {
105+
this.hasQualifiedName("std", ["vector", "deque", "list"], "insert") or
106+
this.hasQualifiedName("std", ["forward_list"], "insert_after")
107+
}
108+
109+
/**
110+
* Gets the index of a parameter to this function that is a reference to the
111+
* value type of the container.
112+
*/
113+
int getAValueTypeParameterIndex() {
114+
getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
115+
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
116+
}
117+
118+
/**
119+
* Gets the index of a parameter to this function that is an iterator.
120+
*/
121+
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
122+
123+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
124+
// flow from parameter to container itself (qualifier) and return value
125+
(
126+
input.isQualifierObject() or
127+
input.isParameterDeref(getAValueTypeParameterIndex()) or
128+
input.isParameter(getAnIteratorParameterIndex())
129+
) and
130+
(
131+
output.isQualifierObject() or
132+
output.isReturnValueDeref()
133+
)
134+
}
135+
}
136+
91137
/**
92138
* The standard container function `assign`.
93139
*/
@@ -105,13 +151,41 @@ class StdSequenceContainerAssign extends TaintFunction {
105151
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
106152
}
107153

154+
/**
155+
* Gets the index of a parameter to this function that is an iterator.
156+
*/
157+
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
158+
108159
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
109-
// flow from parameter to string itself (qualifier) and return value
110-
input.isParameterDeref(getAValueTypeParameterIndex()) and
160+
// flow from parameter to container itself (qualifier)
161+
(
162+
input.isParameterDeref(getAValueTypeParameterIndex()) or
163+
input.isParameter(getAnIteratorParameterIndex())
164+
) and
111165
output.isQualifierObject()
112166
}
113167
}
114168

169+
/**
170+
* The standard container `begin` and `end` functions and their
171+
* variants.
172+
*/
173+
class StdSequenceContainerBeginEnd extends TaintFunction {
174+
StdSequenceContainerBeginEnd() {
175+
this
176+
.hasQualifiedName("std", ["array", "vector", "deque", "list"],
177+
["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"]) or
178+
this
179+
.hasQualifiedName("std", "forward_list",
180+
["before_begin", "begin", "end", "cbefore_begin", "cbegin", "cend"])
181+
}
182+
183+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
184+
input.isQualifierObject() and
185+
output.isReturnValue()
186+
}
187+
}
188+
115189
/**
116190
* The standard container `swap` functions.
117191
*/

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

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,43 @@ class StdBasicString extends TemplateClass {
1414
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
1515
}
1616

17+
/**
18+
* Additional model for `std::string` constructors that reference the character
19+
* type of the container, or an iterator. For example construction from
20+
* iterators:
21+
* ```
22+
* std::string b(a.begin(), a.end());
23+
* ```
24+
*/
25+
class StdStringConstructor extends Constructor, TaintFunction {
26+
StdStringConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_string") }
27+
28+
/**
29+
* Gets the index of a parameter to this function that is a string (or
30+
* character).
31+
*/
32+
int getAStringParameterIndex() {
33+
getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *`
34+
getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &`
35+
getParameter(result).getUnspecifiedType() =
36+
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT`
37+
}
38+
39+
/**
40+
* Gets the index of a parameter to this function that is an iterator.
41+
*/
42+
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
43+
44+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
45+
// taint flow from any parameter of the value type to the returned object
46+
(
47+
input.isParameterDeref(getAStringParameterIndex()) or
48+
input.isParameter(getAnIteratorParameterIndex())
49+
) and
50+
output.isReturnValue() // TODO: this should be `isQualifierObject` by our current definitions, but that flow is not yet supported.
51+
}
52+
}
53+
1754
/**
1855
* The `std::string` function `c_str`.
1956
*/
@@ -79,8 +116,8 @@ class StdStringAppend extends TaintFunction {
79116
* character).
80117
*/
81118
int getAStringParameterIndex() {
82-
getParameter(result).getType() instanceof PointerType or
83-
getParameter(result).getType() instanceof ReferenceType or
119+
getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *`
120+
getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &`
84121
getParameter(result).getUnspecifiedType() =
85122
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT`
86123
}
@@ -115,15 +152,23 @@ class StdStringAssign extends TaintFunction {
115152
* character).
116153
*/
117154
int getAStringParameterIndex() {
118-
getParameter(result).getType() instanceof PointerType or
119-
getParameter(result).getType() instanceof ReferenceType or
155+
getParameter(result).getType() instanceof PointerType or // e.g. `std::basic_string::CharT *`
156+
getParameter(result).getType() instanceof ReferenceType or // e.g. `std::basic_string &`
120157
getParameter(result).getUnspecifiedType() =
121158
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. `std::basic_string::CharT`
122159
}
123160

161+
/**
162+
* Gets the index of a parameter to this function that is an iterator.
163+
*/
164+
int getAnIteratorParameterIndex() { getParameter(result).getType() instanceof Iterator }
165+
124166
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
125167
// flow from parameter to string itself (qualifier) and return value
126-
input.isParameterDeref(getAStringParameterIndex()) and
168+
(
169+
input.isParameterDeref(getAStringParameterIndex()) or
170+
input.isParameter(getAnIteratorParameterIndex())
171+
) and
127172
(
128173
output.isQualifierObject() or
129174
output.isReturnValueDeref()
@@ -137,14 +182,9 @@ class StdStringAssign extends TaintFunction {
137182
*/
138183
class StdStringBeginEnd extends TaintFunction {
139184
StdStringBeginEnd() {
140-
this.hasQualifiedName("std", "basic_string", "begin") or
141-
this.hasQualifiedName("std", "basic_string", "cbegin") or
142-
this.hasQualifiedName("std", "basic_string", "rbegin") or
143-
this.hasQualifiedName("std", "basic_string", "crbegin") or
144-
this.hasQualifiedName("std", "basic_string", "end") or
145-
this.hasQualifiedName("std", "basic_string", "cend") or
146-
this.hasQualifiedName("std", "basic_string", "rend") or
147-
this.hasQualifiedName("std", "basic_string", "crend")
185+
this
186+
.hasQualifiedName("std", "basic_string",
187+
["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend"])
148188
}
149189

150190
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {

0 commit comments

Comments
 (0)