C++: Change iterator models.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-12-02 08:20:31 +00:00
parent 8af2138ade
commit a245977075
4 changed files with 67 additions and 12 deletions

View File

@@ -31,7 +31,17 @@ private class IteratorTraits extends Class {
* `std::iterator_traits` instantiation for it. * `std::iterator_traits` instantiation for it.
*/ */
private class IteratorByTraits extends Iterator { private class IteratorByTraits extends Iterator {
IteratorByTraits() { exists(IteratorTraits it | it.getIteratorType() = this) } IteratorTraits trait;
IteratorByTraits() { trait.getIteratorType() = this }
override Type getValueType() {
exists(TypedefType t |
trait.getAMember() = t and
t.getName() = "value_type" and
result = t.getUnderlyingType()
)
}
} }
/** /**
@@ -42,20 +52,27 @@ private class IteratorByTraits extends Iterator {
*/ */
private class IteratorByPointer extends Iterator instanceof PointerType { private class IteratorByPointer extends Iterator instanceof PointerType {
IteratorByPointer() { not this instanceof IteratorByTraits } IteratorByPointer() { not this instanceof IteratorByTraits }
override Type getValueType() { result = super.getBaseType() }
} }
/** /**
* A type which has the typedefs expected for an iterator. * A type which has the typedefs expected for an iterator.
*/ */
private class IteratorByTypedefs extends Iterator, Class { private class IteratorByTypedefs extends Iterator, Class {
TypedefType valueType;
IteratorByTypedefs() { IteratorByTypedefs() {
this.getAMember().(TypedefType).hasName("difference_type") and this.getAMember().(TypedefType).hasName("difference_type") and
this.getAMember().(TypedefType).hasName("value_type") and valueType = this.getAMember() and
valueType.hasName("value_type") and
this.getAMember().(TypedefType).hasName("pointer") and this.getAMember().(TypedefType).hasName("pointer") and
this.getAMember().(TypedefType).hasName("reference") and this.getAMember().(TypedefType).hasName("reference") and
this.getAMember().(TypedefType).hasName("iterator_category") and this.getAMember().(TypedefType).hasName("iterator_category") and
not this.hasQualifiedName(["std", "bsl"], "iterator_traits") not this.hasQualifiedName(["std", "bsl"], "iterator_traits")
} }
override Type getValueType() { result = valueType.getUnderlyingType() }
} }
/** /**
@@ -63,6 +80,8 @@ private class IteratorByTypedefs extends Iterator, Class {
*/ */
private class StdIterator extends Iterator, Class { private class StdIterator extends Iterator, Class {
StdIterator() { this.hasQualifiedName(["std", "bsl"], "iterator") } StdIterator() { this.hasQualifiedName(["std", "bsl"], "iterator") }
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
} }
/** /**
@@ -166,12 +185,15 @@ private class IteratorSubOperator extends Operator, TaintFunction {
/** /**
* A non-member `operator+=` or `operator-=` function for an iterator type. * A non-member `operator+=` or `operator-=` function for an iterator type.
*/ */
private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunction, TaintFunction { class IteratorAssignArithmeticOperator extends Operator {
IteratorAssignArithmeticOperator() { IteratorAssignArithmeticOperator() {
this.hasName(["operator+=", "operator-="]) and this.hasName(["operator+=", "operator-="]) and
exists(getIteratorArgumentInput(this, 0)) exists(getIteratorArgumentInput(this, 0))
} }
}
private class IteratorAssignArithmeticOperatorModel extends IteratorAssignArithmeticOperator,
DataFlowFunction, TaintFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and input.isParameter(0) and
output.isReturnValue() output.isReturnValue()
@@ -210,11 +232,14 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc
/** /**
* An `operator++` or `operator--` member function for an iterator type. * An `operator++` or `operator--` member function for an iterator type.
*/ */
private class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunction, TaintFunction { class IteratorCrementMemberOperator extends MemberFunction {
IteratorCrementMemberOperator() { IteratorCrementMemberOperator() {
this.getClassAndName(["operator++", "operator--"]) instanceof Iterator this.getClassAndName(["operator++", "operator--"]) instanceof Iterator
} }
}
private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOperator,
DataFlowFunction, TaintFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and input.isQualifierAddress() and
output.isReturnValue() output.isReturnValue()

View File

@@ -5,38 +5,53 @@
import semmle.code.cpp.models.interfaces.Taint import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Iterator import semmle.code.cpp.models.interfaces.Iterator
/**
* A sequence container template class (for example, `std::vector`) from the
* standard library.
*/
abstract class StdSequenceContainer extends Class {
Type getElementType() { result = this.getTemplateArgument(0) }
}
/** /**
* The `std::array` template class. * The `std::array` template class.
*/ */
private class Array extends Class { private class Array extends StdSequenceContainer {
Array() { this.hasQualifiedName(["std", "bsl"], "array") } Array() { this.hasQualifiedName(["std", "bsl"], "array") }
} }
/**
* The `std::string` template class.
*/
private class String extends StdSequenceContainer {
String() { this.hasQualifiedName(["std", "bsl"], "basic_string") }
}
/** /**
* The `std::deque` template class. * The `std::deque` template class.
*/ */
private class Deque extends Class { private class Deque extends StdSequenceContainer {
Deque() { this.hasQualifiedName(["std", "bsl"], "deque") } Deque() { this.hasQualifiedName(["std", "bsl"], "deque") }
} }
/** /**
* The `std::forward_list` template class. * The `std::forward_list` template class.
*/ */
private class ForwardList extends Class { private class ForwardList extends StdSequenceContainer {
ForwardList() { this.hasQualifiedName(["std", "bsl"], "forward_list") } ForwardList() { this.hasQualifiedName(["std", "bsl"], "forward_list") }
} }
/** /**
* The `std::list` template class. * The `std::list` template class.
*/ */
private class List extends Class { private class List extends StdSequenceContainer {
List() { this.hasQualifiedName(["std", "bsl"], "list") } List() { this.hasQualifiedName(["std", "bsl"], "list") }
} }
/** /**
* The `std::vector` template class. * The `std::vector` template class.
*/ */
private class Vector extends Class { private class Vector extends StdSequenceContainer {
Vector() { this.hasQualifiedName(["std", "bsl"], "vector") } Vector() { this.hasQualifiedName(["std", "bsl"], "vector") }
} }

View File

@@ -18,9 +18,12 @@ private class StdBasicString extends ClassTemplateInstantiation {
/** /**
* The `std::basic_string::iterator` declaration. * The `std::basic_string::iterator` declaration.
*/ */
private class StdBasicStringIterator extends Iterator, Type { private class StdBasicStringIterator extends Type instanceof Iterator {
StdBasicStringIterator() { StdBasicStringIterator() {
this.getEnclosingElement() instanceof StdBasicString and this.hasName("iterator") exists(Type unspecified |
unspecified.getEnclosingElement() = any(StdBasicString s).getTemplate() and
unspecified.getUnspecifiedType() = this
)
} }
} }

View File

@@ -29,5 +29,17 @@ abstract class GetIteratorFunction extends Function {
/** /**
* A type which can be used as an iterator. * A type which can be used as an iterator.
*
* Note: Do _not_ `extend` when inheriting from this class in queries. Always use `instanceof`:
* ```
* class MyIterator instanceof Iterator { ... }
* ```
*/ */
abstract class Iterator extends Type { } abstract class Iterator extends Type {
/**
* Gets the value type of this iterator, if any.
*
* For example, the value type of a `std::vector<int>::iterator` is `int`.
*/
Type getValueType() { none() }
}