Skip to content

Commit

Permalink
Merge pull request #16175 from MathiasVP/more-iterator-models
Browse files Browse the repository at this point in the history
C++: Add alias and side-effect models for more iterator functions
  • Loading branch information
MathiasVP authored Apr 10, 2024
2 parents b9b2aa3 + 0ed0731 commit 33f6b6a
Show file tree
Hide file tree
Showing 4 changed files with 785 additions and 789 deletions.
153 changes: 148 additions & 5 deletions cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,32 @@ class IteratorCrementNonMemberOperator extends Operator {
}

private class IteratorCrementNonMemberOperatorModel extends IteratorCrementNonMemberOperator,
DataFlowFunction
DataFlowFunction, SideEffectFunction, AliasFunction
{
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input = getIteratorArgumentInput(this, 0) and
output.isReturnValue()
or
input.isParameterDeref(0) and output.isReturnValueDeref()
}

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = false
}

override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
// See the comment on `IteratorCrementMemberOperatorModel::hasSpecificWriteSideEffect`
// for an explanation of these values.
i = 0 and buffer = false and mustWrite = false
}

override predicate parameterNeverEscapes(int index) { none() }

override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
}

/**
Expand All @@ -146,7 +164,7 @@ class IteratorCrementMemberOperator extends MemberFunction {
}

private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOperator,
DataFlowFunction, TaintFunction
DataFlowFunction, TaintFunction, SideEffectFunction, AliasFunction
{
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and
Expand All @@ -163,6 +181,28 @@ private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOp
input.isQualifierObject() and
output.isReturnValueDeref()
}

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}

override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
// We have two choices here: either `buffer` must be `true` or `mustWrite`
// must be `false` to ensure that the IR alias analysis doesn't think that
// `it++` completely override the value of the iterator.
// We choose `mustWrite` must be `false`. In that case, the value of
// `buffer` isn't super important (it just decides which kind of read side
// effect will be emitted).
i = -1 and buffer = false and mustWrite = false
}

override predicate parameterNeverEscapes(int index) { index = -1 }

override predicate parameterEscapesOnlyViaReturn(int index) { none() }
}

/**
Expand Down Expand Up @@ -332,7 +372,7 @@ class IteratorAssignArithmeticOperator extends Function {
* non-member and member versions, use `IteratorPointerDereferenceOperator`.
*/
class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction,
IteratorReferenceFunction
IteratorReferenceFunction, AliasFunction, SideEffectFunction
{
IteratorPointerDereferenceMemberOperator() {
this.getClassAndName("operator*") instanceof Iterator
Expand All @@ -345,6 +385,18 @@ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunc
input.isReturnValueDeref() and
output.isQualifierObject()
}

override predicate parameterNeverEscapes(int index) { index = -1 }

override predicate parameterEscapesOnlyViaReturn(int index) { none() }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}

/**
Expand All @@ -361,7 +413,7 @@ class IteratorPointerDereferenceNonMemberOperator extends Operator, IteratorRefe
}

private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorPointerDereferenceNonMemberOperator,
TaintFunction
TaintFunction, AliasFunction, SideEffectFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = getIteratorArgumentInput(this, 0) and
Expand All @@ -370,6 +422,18 @@ private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorP
input.isReturnValueDeref() and
output.isParameterDeref(0)
}

override predicate parameterNeverEscapes(int index) { index = 0 }

override predicate parameterEscapesOnlyViaReturn(int index) { none() }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = false
}
}

/**
Expand Down Expand Up @@ -420,6 +484,71 @@ class IteratorAssignmentMemberOperator extends MemberFunction {
}
}

/**
* A member `operator==` or `operator!=` function for an iterator type.
*
* Note that this class _only_ matches member functions. To find both
* non-member and member versions, use `IteratorLogicalOperator`.
*/
class IteratorLogicalMemberOperator extends MemberFunction {
IteratorLogicalMemberOperator() {
this.getClassAndName(["operator!=", "operator=="]) instanceof Iterator
}
}

private class IteratorLogicalMemberOperatorModel extends IteratorLogicalMemberOperator,
AliasFunction, SideEffectFunction
{
override predicate parameterNeverEscapes(int index) { index = [-1, 0] }

override predicate parameterEscapesOnlyViaReturn(int index) { none() }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = -1 and buffer = false
}
}

/**
* A member `operator==` or `operator!=` function for an iterator type.
*
* Note that this class _only_ matches non-member functions. To find both
* non-member and member versions, use `IteratorLogicalOperator`.
*/
class IteratorLogicalNonMemberOperator extends Function {
IteratorLogicalNonMemberOperator() {
this.hasName(["operator!=", "operator=="]) and
exists(getIteratorArgumentInput(this, 0)) and
exists(getIteratorArgumentInput(this, 1))
}
}

private class IteratorLogicalNonMemberOperatorModel extends IteratorLogicalNonMemberOperator,
AliasFunction, SideEffectFunction
{
override predicate parameterNeverEscapes(int index) { index = [0, 1] }

override predicate parameterEscapesOnlyViaReturn(int index) { none() }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }
}

/**
* A (member or non-member) `operator==` or `operator!=` function for an iterator type.
*/
class IteratorLogicalOperator extends Function {
IteratorLogicalOperator() {
this instanceof IteratorLogicalNonMemberOperator
or
this instanceof IteratorLogicalMemberOperator
}
}

/**
* An `operator=` member function of an iterator class that is not a copy or move assignment
* operator.
Expand All @@ -428,12 +557,26 @@ class IteratorAssignmentMemberOperator extends MemberFunction {
* `operator*` and use their own `operator=` to assign to the container.
*/
private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMemberOperator,
TaintFunction
TaintFunction, SideEffectFunction, AliasFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and
output.isQualifierObject()
}

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
// See the comment on `IteratorCrementMemberOperatorModel::hasSpecificWriteSideEffect`
// for an explanation of these values.
i = -1 and buffer = false and mustWrite = false
}

override predicate parameterNeverEscapes(int index) { index = 0 }

override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
}

/**
Expand Down
Loading

0 comments on commit 33f6b6a

Please sign in to comment.