Skip to content

Commit 2653458

Browse files
authored
Merge pull request github#11537 from MathiasVP/iterator-model-changes
C++: Change iterator models
2 parents f8386e7 + cef7224 commit 2653458

File tree

4 files changed

+62
-19
lines changed

4 files changed

+62
-19
lines changed

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

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,17 @@ private class IteratorTraits extends Class {
3131
* `std::iterator_traits` instantiation for it.
3232
*/
3333
private class IteratorByTraits extends Iterator {
34-
IteratorByTraits() { exists(IteratorTraits it | it.getIteratorType() = this) }
34+
IteratorTraits trait;
35+
36+
IteratorByTraits() { trait.getIteratorType() = this }
37+
38+
override Type getValueType() {
39+
exists(TypedefType t |
40+
trait.getAMember() = t and
41+
t.getName() = "value_type" and
42+
result = t.getUnderlyingType()
43+
)
44+
}
3545
}
3646

3747
/**
@@ -42,27 +52,36 @@ private class IteratorByTraits extends Iterator {
4252
*/
4353
private class IteratorByPointer extends Iterator instanceof PointerType {
4454
IteratorByPointer() { not this instanceof IteratorByTraits }
55+
56+
override Type getValueType() { result = super.getBaseType() }
4557
}
4658

4759
/**
4860
* A type which has the typedefs expected for an iterator.
4961
*/
5062
private class IteratorByTypedefs extends Iterator, Class {
63+
TypedefType valueType;
64+
5165
IteratorByTypedefs() {
5266
this.getAMember().(TypedefType).hasName("difference_type") and
53-
this.getAMember().(TypedefType).hasName("value_type") and
67+
valueType = this.getAMember() and
68+
valueType.hasName("value_type") and
5469
this.getAMember().(TypedefType).hasName("pointer") and
5570
this.getAMember().(TypedefType).hasName("reference") and
5671
this.getAMember().(TypedefType).hasName("iterator_category") and
5772
not this.hasQualifiedName(["std", "bsl"], "iterator_traits")
5873
}
74+
75+
override Type getValueType() { result = valueType.getUnderlyingType() }
5976
}
6077

6178
/**
6279
* The `std::iterator` class.
6380
*/
6481
private class StdIterator extends Iterator, Class {
6582
StdIterator() { this.hasQualifiedName(["std", "bsl"], "iterator") }
83+
84+
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
6685
}
6786

6887
/**
@@ -166,12 +185,15 @@ private class IteratorSubOperator extends Operator, TaintFunction {
166185
/**
167186
* A non-member `operator+=` or `operator-=` function for an iterator type.
168187
*/
169-
private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunction, TaintFunction {
188+
class IteratorAssignArithmeticOperator extends Operator {
170189
IteratorAssignArithmeticOperator() {
171190
this.hasName(["operator+=", "operator-="]) and
172191
exists(getIteratorArgumentInput(this, 0))
173192
}
193+
}
174194

195+
private class IteratorAssignArithmeticOperatorModel extends IteratorAssignArithmeticOperator,
196+
DataFlowFunction, TaintFunction {
175197
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
176198
input.isParameter(0) and
177199
output.isReturnValue()
@@ -210,11 +232,14 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc
210232
/**
211233
* An `operator++` or `operator--` member function for an iterator type.
212234
*/
213-
private class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunction, TaintFunction {
235+
class IteratorCrementMemberOperator extends MemberFunction {
214236
IteratorCrementMemberOperator() {
215237
this.getClassAndName(["operator++", "operator--"]) instanceof Iterator
216238
}
239+
}
217240

241+
private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOperator,
242+
DataFlowFunction, TaintFunction {
218243
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
219244
input.isQualifierAddress() and
220245
output.isReturnValue()

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

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,53 @@
55
import semmle.code.cpp.models.interfaces.Taint
66
import semmle.code.cpp.models.interfaces.Iterator
77

8+
/**
9+
* A sequence container template class (for example, `std::vector`) from the
10+
* standard library.
11+
*/
12+
abstract class StdSequenceContainer extends Class {
13+
Type getElementType() { result = this.getTemplateArgument(0) }
14+
}
15+
816
/**
917
* The `std::array` template class.
1018
*/
11-
private class Array extends Class {
19+
private class Array extends StdSequenceContainer {
1220
Array() { this.hasQualifiedName(["std", "bsl"], "array") }
1321
}
1422

23+
/**
24+
* The `std::string` template class.
25+
*/
26+
private class String extends StdSequenceContainer {
27+
String() { this.hasQualifiedName(["std", "bsl"], "basic_string") }
28+
}
29+
1530
/**
1631
* The `std::deque` template class.
1732
*/
18-
private class Deque extends Class {
33+
private class Deque extends StdSequenceContainer {
1934
Deque() { this.hasQualifiedName(["std", "bsl"], "deque") }
2035
}
2136

2237
/**
2338
* The `std::forward_list` template class.
2439
*/
25-
private class ForwardList extends Class {
40+
private class ForwardList extends StdSequenceContainer {
2641
ForwardList() { this.hasQualifiedName(["std", "bsl"], "forward_list") }
2742
}
2843

2944
/**
3045
* The `std::list` template class.
3146
*/
32-
private class List extends Class {
47+
private class List extends StdSequenceContainer {
3348
List() { this.hasQualifiedName(["std", "bsl"], "list") }
3449
}
3550

3651
/**
3752
* The `std::vector` template class.
3853
*/
39-
private class Vector extends Class {
54+
private class Vector extends StdSequenceContainer {
4055
Vector() { this.hasQualifiedName(["std", "bsl"], "vector") }
4156
}
4257

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,6 @@ private class StdBasicString extends ClassTemplateInstantiation {
1515
StdBasicString() { this.hasQualifiedName(["std", "bsl"], "basic_string") }
1616
}
1717

18-
/**
19-
* The `std::basic_string::iterator` declaration.
20-
*/
21-
private class StdBasicStringIterator extends Iterator, Type {
22-
StdBasicStringIterator() {
23-
this.getEnclosingElement() instanceof StdBasicString and this.hasName("iterator")
24-
}
25-
}
26-
2718
/**
2819
* A `std::string` function for which taint should be propagated.
2920
*/

cpp/ql/lib/semmle/code/cpp/models/interfaces/Iterator.qll

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,17 @@ abstract class GetIteratorFunction extends Function {
2929

3030
/**
3131
* A type which can be used as an iterator.
32+
*
33+
* Note: Do _not_ `extend` when inheriting from this class in queries. Always use `instanceof`:
34+
* ```
35+
* class MyIterator instanceof Iterator { ... }
36+
* ```
3237
*/
33-
abstract class Iterator extends Type { }
38+
abstract class Iterator extends Type {
39+
/**
40+
* Gets the value type of this iterator, if any.
41+
*
42+
* For example, the value type of a `std::vector<int>::iterator` is `int`.
43+
*/
44+
Type getValueType() { none() }
45+
}

0 commit comments

Comments
 (0)