Skip to content

Commit

Permalink
Merge pull request #17034 from MathiasVP/more-alias-and-side-effect-m…
Browse files Browse the repository at this point in the history
…odels

C++: Add more alias and side effect models
  • Loading branch information
MathiasVP committed Jul 25, 2024
2 parents 5a39610 + 3f5b4a8 commit 032ae9e
Show file tree
Hide file tree
Showing 14 changed files with 2,299 additions and 1,052 deletions.
5 changes: 5 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/models/Models.qll
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ private import implementations.StdPair
private import implementations.StdMap
private import implementations.StdSet
private import implementations.StdString
private import implementations.StdFunction
private import implementations.StdException
private import implementations.StdAllocator
private import implementations.StdAlgorithm
private import implementations.StdMath
private import implementations.Swap
private import implementations.GetDelim
private import implementations.SmartPointer
Expand Down
69 changes: 62 additions & 7 deletions cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,41 @@ private class StdIterator extends Iterator, Class {
override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
}

private class StdReverseIterator extends Iterator, Class {
StdReverseIterator() { this.hasQualifiedName(["std", "bsl"], "reverse_iterator") }

override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
}

private class StdIstreamBufIterator extends Iterator, Class {
StdIstreamBufIterator() { this.hasQualifiedName(["std", "bsl"], "istreambuf_iterator") }

override Type getValueType() { result = this.getTemplateArgument(1).(Type).getUnderlyingType() }
}

private class StdIstreambufIteratorConstructor extends Constructor, SideEffectFunction,
AliasFunction
{
StdIstreambufIteratorConstructor() { this.getDeclaringType() instanceof StdIstreamBufIterator }

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

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

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

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

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}
}

/**
* Gets the `FunctionInput` corresponding to an iterator parameter to
* user-defined operator `op`, at `index`.
Expand Down Expand Up @@ -579,31 +614,51 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
}

private string beginName() {
result = ["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]
}

/**
* A `begin` member function, or a related function, that returns an iterator.
*/
class BeginFunction extends MemberFunction {
class BeginFunction extends Function {
BeginFunction() {
this.hasName(["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]) and
this.getType().getUnspecifiedType() instanceof Iterator
this.getUnspecifiedType() instanceof Iterator and
(
this.hasName(beginName()) and
this instanceof MemberFunction
or
this.hasGlobalOrStdOrBslName(beginName()) and
not this instanceof MemberFunction and
this.getNumberOfParameters() = 1
)
}
}

private string endName() { result = ["end", "cend", "rend", "crend"] }

/**
* An `end` member function, or a related function, that returns an iterator.
*/
class EndFunction extends MemberFunction {
class EndFunction extends Function {
EndFunction() {
this.hasName(["end", "cend", "rend", "crend"]) and
this.getType().getUnspecifiedType() instanceof Iterator
this.getUnspecifiedType() instanceof Iterator and
(
this.hasName(endName()) and
this instanceof MemberFunction
or
this.hasGlobalOrStdOrBslName(endName()) and
this instanceof MemberFunction and
this.getNumberOfParameters() = 1
)
}
}

/**
* A `begin` or `end` member function, or a related member function, that
* returns an iterator.
*/
class BeginOrEndFunction extends MemberFunction {
class BeginOrEndFunction extends Function {
BeginOrEndFunction() {
this instanceof BeginFunction or
this instanceof EndFunction
Expand Down
23 changes: 22 additions & 1 deletion cpp/ql/lib/semmle/code/cpp/models/implementations/Printf.qll
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect

/**
* The standard functions `printf`, `wprintf` and their glib variants.
Expand Down Expand Up @@ -96,7 +97,7 @@ private class Sprintf extends FormattingFunction {
/**
* Implements `Snprintf`.
*/
private class SnprintfImpl extends Snprintf {
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
SnprintfImpl() {
this instanceof TopLevelFunction and
(
Expand Down Expand Up @@ -143,6 +144,26 @@ private class SnprintfImpl extends Snprintf {
}

override int getSizeParameterIndex() { result = 1 }

override predicate parameterNeverEscapes(int index) {
// We don't know how many parameters are passed to the function since it's varargs, but they also don't escape.
index = this.getFormatParameterIndex()
}

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

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getOutputParameterIndex(false) and buffer = true and mustWrite = false
}

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
// We don't know how many parameters are passed to the function since it's varargs, but they also have read side effects.
i = this.getFormatParameterIndex() and buffer = true
}
}

/**
Expand Down
115 changes: 115 additions & 0 deletions cpp/ql/lib/semmle/code/cpp/models/implementations/StdAlgorithm.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* Provides models for C++ functions from the `algorithms` header.
*/

import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Alias

private class StdPartialSort extends Function, SideEffectFunction, AliasFunction {
StdPartialSort() { this.hasGlobalOrStdName("partial_sort") }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
}

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = this.getAnIteratorParameterIndex() and
buffer = true and
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and
buffer = false
}

private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}

override predicate parameterNeverEscapes(int index) {
index = this.getAnIteratorParameterIndex()
or
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
}

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

private class StdSortHeap extends Function, SideEffectFunction, AliasFunction {
StdSortHeap() { this.hasGlobalOrStdName("sort_heap") }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
}

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = this.getAnIteratorParameterIndex() and
buffer = true
}

private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}

override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }

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

private class StdGenerateN extends Function, SideEffectFunction, AliasFunction {
StdGenerateN() { this.hasGlobalOrStdName("generate_n") }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = this.getAnIteratorParameterIndex() and buffer = true and mustWrite = false
}

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}

private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}

override predicate parameterNeverEscapes(int index) { index = this.getAnIteratorParameterIndex() }

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

private class StdFindIfOrIfNot extends Function, SideEffectFunction, AliasFunction {
StdFindIfOrIfNot() { this.hasGlobalOrStdName(["find_if", "find_if_not"]) }

override predicate hasOnlySpecificReadSideEffects() { any() }

override predicate hasOnlySpecificWriteSideEffects() { any() }

override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = this.getAnIteratorParameterIndex() and buffer = true
or
this.getParameter(i).getUnspecifiedType() instanceof ReferenceType and buffer = false
}

private int getAnIteratorParameterIndex() {
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}

override predicate parameterNeverEscapes(int index) {
this.getParameter(index).getUnspecifiedType() instanceof ReferenceType
}

override predicate parameterEscapesOnlyViaReturn(int index) {
index = this.getAnIteratorParameterIndex()
}
}
Loading

0 comments on commit 032ae9e

Please sign in to comment.