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

Skip to content

Commit 20188b7

Browse files
author
Robert Marsh
committed
C++: input iterator models
1 parent d32d6c9 commit 20188b7

7 files changed

Lines changed: 142 additions & 67 deletions

File tree

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

Lines changed: 82 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import cpp
22
import semmle.code.cpp.models.interfaces.Taint
3+
import semmle.code.cpp.models.interfaces.DataFlow
34

45
class IteratorTraits extends Class {
56
IteratorTraits() {
@@ -25,12 +26,17 @@ class IteratorByTypedefs extends Class {
2526
}
2627
}
2728

28-
class IteratorByStdIteratorTraits extends Type { }
29+
class StdIterator extends Class {
30+
StdIterator() {
31+
this.hasQualifiedName("std", "iterator")
32+
}
33+
}
2934

3035
class LegacyIterator extends Type {
3136
LegacyIterator() {
3237
this instanceof IteratorByTypedefs or
33-
exists(IteratorTraits it | it.getIteratorType() = this)
38+
exists(IteratorTraits it | it.getIteratorType() = this) or
39+
this instanceof StdIterator
3440
}
3541
}
3642

@@ -47,7 +53,7 @@ class IteratorPointerDereferenceOperator extends Operator, TaintFunction {
4753
}
4854
}
4955

50-
class IteratorCrementOperator extends Operator, TaintFunction {
56+
class IteratorCrementOperator extends Operator, DataFlowFunction, TaintFunction {
5157
IteratorCrementOperator() {
5258
(
5359
this.hasName("operator++") or
@@ -62,6 +68,11 @@ class IteratorCrementOperator extends Operator, TaintFunction {
6268
.getBaseType() instanceof LegacyIterator
6369
}
6470

71+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
72+
input.isParameter(0) and
73+
output.isReturnValue()
74+
}
75+
6576
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
6677
input.isParameterDeref(0) and
6778
output.isParameterDeref(0)
@@ -75,7 +86,7 @@ class IteratorFieldOperator extends Operator, TaintFunction {
7586
.getACallToThisFunction()
7687
.getArgument(0)
7788
.getFullyConverted()
78-
.getUnderlyingType()
89+
.getUnspecifiedType()
7990
.(PointerType)
8091
.getBaseType() instanceof LegacyIterator
8192
}
@@ -88,24 +99,22 @@ class IteratorFieldOperator extends Operator, TaintFunction {
8899

89100
class IteratorAddOperator extends Operator, TaintFunction {
90101
IteratorAddOperator() {
102+
this.hasName("operator+") and
91103
(
92-
this.hasName("operator+")
93-
) and
94-
(
95-
this
96-
.getACallToThisFunction()
97-
.getArgument(0)
98-
.getFullyConverted()
99-
.getUnderlyingType()
100-
.(PointerType)
101-
.getBaseType() instanceof LegacyIterator or
102-
this
103-
.getACallToThisFunction()
104-
.getArgument(0)
105-
.getFullyConverted()
106-
.getUnderlyingType()
107-
.(PointerType)
108-
.getBaseType() instanceof LegacyIterator
104+
this
105+
.getACallToThisFunction()
106+
.getArgument(0)
107+
.getFullyConverted()
108+
.getUnspecifiedType()
109+
.(PointerType)
110+
.getBaseType() instanceof LegacyIterator or
111+
this
112+
.getACallToThisFunction()
113+
.getArgument(0)
114+
.getFullyConverted()
115+
.getUnspecifiedType()
116+
.(PointerType)
117+
.getBaseType() instanceof LegacyIterator
109118
)
110119
}
111120

@@ -118,23 +127,17 @@ class IteratorAddOperator extends Operator, TaintFunction {
118127
}
119128
}
120129

130+
/**
131+
* A non-member `operator-` function that takes an iterator as its first argument.
132+
*/
121133
class IteratorSubOperator extends Operator, TaintFunction {
122134
IteratorSubOperator() {
123-
(
124-
this.hasName("operator-")
125-
) and
135+
this.hasName("operator-") and
126136
this
127137
.getACallToThisFunction()
128138
.getArgument(0)
129139
.getFullyConverted()
130-
.getUnderlyingType()
131-
.(PointerType)
132-
.getBaseType() instanceof LegacyIterator and
133-
not this
134-
.getACallToThisFunction()
135-
.getArgument(1)
136-
.getFullyConverted()
137-
.getUnderlyingType()
140+
.getUnspecifiedType()
138141
.(PointerType)
139142
.getBaseType() instanceof LegacyIterator
140143
}
@@ -148,35 +151,26 @@ class IteratorSubOperator extends Operator, TaintFunction {
148151
}
149152
}
150153

151-
class IteratorDiffOperator extends Operator, TaintFunction {
152-
IteratorDiffOperator() {
154+
class IteratorAssignArithmeticOperator extends MemberFunction, DataFlowFunction, TaintFunction {
155+
IteratorAssignArithmeticOperator() {
153156
(
154-
this.hasName("operator-")
157+
this.hasName("operator+=") or
158+
this.hasName("operator-=")
155159
) and
156-
this
157-
.getACallToThisFunction()
158-
.getArgument(0)
159-
.getFullyConverted()
160-
.getUnderlyingType()
161-
.(PointerType)
162-
.getBaseType() instanceof LegacyIterator and
163-
not this
164-
.getACallToThisFunction()
165-
.getArgument(1)
166-
.getFullyConverted()
167-
.getUnderlyingType()
168-
.(PointerType)
169-
.getBaseType() instanceof LegacyIterator
160+
this.getDeclaringType() instanceof LegacyIterator
170161
}
171162

172-
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
173-
(
174-
input.isParameter(0) or
175-
input.isParameter(1)
176-
) and
163+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
164+
input.isParameter(0) and
177165
output.isReturnValue()
178166
}
167+
168+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
169+
input.isParameterDeref(1) and
170+
output.isParameterDeref(0)
171+
}
179172
}
173+
180174
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction {
181175
IteratorPointerDereferenceMemberOperator() {
182176
this.hasName("operator*") and
@@ -189,7 +183,7 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc
189183
}
190184
}
191185

192-
class IteratorCrementMemberOperator extends MemberFunction, TaintFunction {
186+
class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunction, TaintFunction {
193187
IteratorCrementMemberOperator() {
194188
(
195189
this.hasName("operator++") or
@@ -198,6 +192,11 @@ class IteratorCrementMemberOperator extends MemberFunction, TaintFunction {
198192
this.getDeclaringType() instanceof LegacyIterator
199193
}
200194

195+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
196+
input.isQualifierAddress() and
197+
output.isReturnValue()
198+
}
199+
201200
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
202201
input.isQualifierObject() and
203202
output.isQualifierObject()
@@ -216,13 +215,14 @@ class IteratorFieldMemberOperator extends Operator, TaintFunction {
216215
}
217216
}
218217

219-
class IteratorMemberBinaryOperator extends MemberFunction, TaintFunction {
220-
IteratorMemberBinaryOperator() {
221-
(
222-
this.hasName("operator+") or
223-
this.hasName("operator-")
224-
) and
225-
this.getDeclaringType() instanceof LegacyIterator
218+
/**
219+
* An `operator+` or `operator-` member function of an iterator class.
220+
*/
221+
class IteratorBinaryArithmeticMemberOperator extends MemberFunction, TaintFunction {
222+
IteratorBinaryArithmeticMemberOperator() {
223+
this.hasName("operator-") and
224+
this.getDeclaringType() instanceof LegacyIterator and
225+
this.getParameter(0).getUnspecifiedType() instanceof LegacyIterator
226226
}
227227

228228
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -234,22 +234,37 @@ class IteratorMemberBinaryOperator extends MemberFunction, TaintFunction {
234234
}
235235
}
236236

237-
class IteratorMemberAssignOperator extends MemberFunction, TaintFunction {
238-
IteratorMemberAssignOperator() {
237+
class IteratorAssignArithmeticMemberOperator extends MemberFunction, DataFlowFunction, TaintFunction {
238+
IteratorAssignArithmeticMemberOperator() {
239239
(
240240
this.hasName("operator+=") or
241241
this.hasName("operator-=")
242242
) and
243243
this.getDeclaringType() instanceof LegacyIterator
244244
}
245245

246+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
247+
input.isQualifierAddress() and
248+
output.isReturnValue()
249+
}
250+
251+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
252+
input.isParameter(0) and
253+
output.isQualifierObject()
254+
}
255+
}
256+
257+
class IteratorArrayMemberOperator extends MemberFunction, TaintFunction {
258+
IteratorArrayMemberOperator() {
259+
this.hasName("operator[]") and
260+
this.getDeclaringType() instanceof LegacyIterator
261+
}
262+
246263
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
247264
(
248265
input.isQualifierObject() or
249266
input.isParameter(0)
250267
) and
251-
output.isQualifierObject()
252-
or
253268
output.isReturnValue()
254269
}
255-
}
270+
}

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import semmle.code.cpp.models.interfaces.Taint
2+
import semmle.code.cpp.models.implementations.Iterator
23

34
/**
45
* The `std::basic_string` template class.
@@ -65,11 +66,17 @@ class StdStringAppend extends TaintFunction {
6566
getParameter(result).getType() = getDeclaringType().getTemplateArgument(0) // i.e. `std::basic_string::CharT`
6667
}
6768

69+
int getAnIteratorParameter() {
70+
getParameter(result).getType() instanceof LegacyIterator
71+
}
72+
6873
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
6974
// flow from string and parameter to string (qualifier) and return value
7075
(
7176
input.isQualifierObject() or
7277
input.isParameterDeref(getAStringParameter())
78+
or
79+
input.isParameter(getAnIteratorParameter())
7380
) and
7481
(
7582
output.isQualifierObject() or
@@ -104,6 +111,20 @@ class StdStringAssign extends TaintFunction {
104111
}
105112
}
106113

114+
class StdStringBegin extends TaintFunction {
115+
StdStringBegin() {
116+
this.hasQualifiedName("std", "basic_string", "begin") or
117+
this.hasQualifiedName("std", "basic_string", "cbegin") or
118+
this.hasQualifiedName("std", "basic_string", "rbegin") or
119+
this.hasQualifiedName("std", "basic_string", "crbegin")
120+
}
121+
122+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
123+
input.isQualifierObject() and
124+
output.isReturnValue()
125+
}
126+
}
127+
107128
/**
108129
* The standard function `std::string.copy`.
109130
*/

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@
368368
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:33:124:33 | s | |
369369
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:124:50:124:50 | s | |
370370
| string.cpp:119:16:119:24 | call to basic_string | string.cpp:128:16:128:16 | s | |
371+
| string.cpp:120:15:120:15 | (__begin) | string.cpp:120:15:120:15 | call to operator* | TAINT |
372+
| string.cpp:120:15:120:15 | (__range) | string.cpp:120:15:120:15 | call to begin | TAINT |
371373
| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | |
372374
| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | |
373375
| string.cpp:120:15:120:15 | call to begin | string.cpp:120:15:120:15 | (__begin) | |
@@ -382,6 +384,7 @@
382384
| string.cpp:120:15:120:15 | s | string.cpp:120:15:120:15 | call to operator* | TAINT |
383385
| string.cpp:124:33:124:33 | ref arg s | string.cpp:124:50:124:50 | s | |
384386
| string.cpp:124:33:124:33 | ref arg s | string.cpp:128:16:128:16 | s | |
387+
| string.cpp:124:33:124:33 | s | string.cpp:124:35:124:39 | call to begin | TAINT |
385388
| string.cpp:124:35:124:39 | call to begin | string.cpp:124:44:124:45 | it | |
386389
| string.cpp:124:35:124:39 | call to begin | string.cpp:124:61:124:62 | it | |
387390
| string.cpp:124:35:124:39 | call to begin | string.cpp:125:9:125:10 | it | |
@@ -390,6 +393,9 @@
390393
| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:44:124:45 | it | |
391394
| string.cpp:124:61:124:62 | ref arg it | string.cpp:124:61:124:62 | it | |
392395
| string.cpp:124:61:124:62 | ref arg it | string.cpp:125:9:125:10 | it | |
396+
| string.cpp:125:9:125:10 | it | string.cpp:125:8:125:8 | call to operator* | TAINT |
397+
| string.cpp:128:16:128:16 | (__begin) | string.cpp:128:16:128:16 | call to operator* | TAINT |
398+
| string.cpp:128:16:128:16 | (__range) | string.cpp:128:16:128:16 | call to begin | TAINT |
393399
| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | |
394400
| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | |
395401
| string.cpp:128:16:128:16 | call to begin | string.cpp:128:16:128:16 | (__begin) | |
@@ -404,6 +410,8 @@
404410
| string.cpp:128:16:128:16 | s | string.cpp:128:16:128:16 | call to operator* | TAINT |
405411
| string.cpp:132:28:132:33 | call to source | string.cpp:132:28:132:36 | call to basic_string | TAINT |
406412
| string.cpp:132:28:132:36 | call to basic_string | string.cpp:133:22:133:28 | const_s | |
413+
| string.cpp:133:22:133:22 | (__begin) | string.cpp:133:22:133:22 | call to operator* | TAINT |
414+
| string.cpp:133:22:133:22 | (__range) | string.cpp:133:22:133:22 | call to begin | TAINT |
407415
| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | |
408416
| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | |
409417
| string.cpp:133:22:133:22 | call to begin | string.cpp:133:22:133:22 | (__begin) | |
@@ -677,6 +685,18 @@
677685
| string.cpp:319:16:319:24 | call to basic_string | string.cpp:322:19:322:19 | b | |
678686
| string.cpp:321:7:321:7 | a | string.cpp:321:9:321:14 | call to substr | TAINT |
679687
| string.cpp:322:7:322:7 | b | string.cpp:322:9:322:14 | call to substr | TAINT |
688+
| string.cpp:327:18:327:24 | hello | string.cpp:327:18:327:25 | call to basic_string | TAINT |
689+
| string.cpp:327:18:327:25 | call to basic_string | string.cpp:329:8:329:9 | s1 | |
690+
| string.cpp:327:18:327:25 | call to basic_string | string.cpp:330:8:330:9 | s1 | |
691+
| string.cpp:327:18:327:25 | call to basic_string | string.cpp:331:8:331:9 | s1 | |
692+
| string.cpp:328:18:328:23 | call to source | string.cpp:328:18:328:26 | call to basic_string | TAINT |
693+
| string.cpp:328:18:328:26 | call to basic_string | string.cpp:330:18:330:19 | s2 | |
694+
| string.cpp:328:18:328:26 | call to basic_string | string.cpp:330:30:330:31 | s2 | |
695+
| string.cpp:330:8:330:9 | s1 | string.cpp:330:11:330:16 | call to append | TAINT |
696+
| string.cpp:330:18:330:19 | ref arg s2 | string.cpp:330:30:330:31 | s2 | |
697+
| string.cpp:330:18:330:19 | s2 | string.cpp:330:21:330:25 | call to begin | TAINT |
698+
| string.cpp:330:21:330:25 | call to begin | string.cpp:330:11:330:16 | call to append | TAINT |
699+
| string.cpp:330:33:330:35 | call to end | string.cpp:330:11:330:16 | call to append | TAINT |
680700
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:16:2:16:4 | ss1 | |
681701
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:22:7:22:9 | ss1 | |
682702
| stringstream.cpp:13:20:13:22 | call to basic_stringstream | stringstream.cpp:27:7:27:9 | ss1 | |
@@ -1520,6 +1540,7 @@
15201540
| vector.cpp:12:21:12:28 | call to vector | vector.cpp:18:38:18:38 | v | |
15211541
| vector.cpp:12:21:12:28 | call to vector | vector.cpp:18:55:18:55 | v | |
15221542
| vector.cpp:12:21:12:28 | call to vector | vector.cpp:22:15:22:15 | v | |
1543+
| vector.cpp:14:14:14:14 | (__begin) | vector.cpp:14:14:14:14 | call to operator* | TAINT |
15231544
| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | |
15241545
| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | |
15251546
| vector.cpp:14:14:14:14 | call to begin | vector.cpp:14:14:14:14 | (__begin) | |
@@ -1542,6 +1563,8 @@
15421563
| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:18:49:18:50 | it | |
15431564
| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:18:66:18:67 | it | |
15441565
| vector.cpp:18:66:18:67 | ref arg it | vector.cpp:19:9:19:10 | it | |
1566+
| vector.cpp:19:9:19:10 | it | vector.cpp:19:8:19:8 | call to operator* | TAINT |
1567+
| vector.cpp:22:15:22:15 | (__begin) | vector.cpp:22:15:22:15 | call to operator* | TAINT |
15451568
| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | |
15461569
| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | |
15471570
| vector.cpp:22:15:22:15 | call to begin | vector.cpp:22:15:22:15 | (__begin) | |
@@ -1556,6 +1579,7 @@
15561579
| vector.cpp:22:15:22:15 | v | vector.cpp:22:15:22:15 | call to operator* | TAINT |
15571580
| vector.cpp:26:33:26:39 | source1 | vector.cpp:26:33:26:40 | call to vector | TAINT |
15581581
| vector.cpp:26:33:26:40 | call to vector | vector.cpp:27:21:27:27 | const_v | |
1582+
| vector.cpp:27:21:27:21 | (__begin) | vector.cpp:27:21:27:21 | call to operator* | TAINT |
15591583
| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | |
15601584
| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | |
15611585
| vector.cpp:27:21:27:21 | call to begin | vector.cpp:27:21:27:21 | (__begin) | |

cpp/ql/test/library-tests/dataflow/taint-tests/stl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ namespace std
6363
basic_string& append(const basic_string& str);
6464
basic_string& append(const charT* s);
6565
basic_string& append(size_type n, charT c);
66+
template<class InputIt> constexpr basic_string& append(InputIt first, InputIt last);
6667
basic_string& assign(const basic_string& str);
6768
basic_string& assign(size_type n, charT c);
6869
basic_string& insert(size_type pos, const basic_string& str);

0 commit comments

Comments
 (0)