Skip to content

Commit

Permalink
C#: Handle more types params types on the dispatch call logic.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelnebel committed Dec 19, 2024
1 parent 9a8bbf2 commit e1a52e3
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 2 deletions.
3 changes: 2 additions & 1 deletion csharp/ql/lib/semmle/code/csharp/Callable.qll
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Stmt
import Type
import exprs.Call
private import commons.QualifiedName
private import commons.Collections
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.metrics.Complexity
private import TypeRef
Expand Down Expand Up @@ -273,7 +274,7 @@ class Method extends Callable, Virtualizable, Attributable, @method {
Type getParamsType() {
exists(Parameter last | last = this.getParameter(this.getNumberOfParameters() - 1) |
last.isParams() and
result = last.getType().(ArrayType).getElementType()
result = last.getType().(ParamsCollectionType).getElementType()
)
}

Expand Down
35 changes: 35 additions & 0 deletions csharp/ql/lib/semmle/code/csharp/commons/Collections.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import csharp
import semmle.code.csharp.frameworks.system.Collections
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.collections.Generic

private string modifyMethodName() {
result =
Expand Down Expand Up @@ -67,6 +69,39 @@ class CollectionType extends RefType {
}
}

/**
* A collection type that can be used as a `params` parameter type.
*/
abstract private class ParamsCollectionTypeImpl extends ValueOrRefType {
abstract Type getElementType();
}

private class AddArrayType extends ParamsCollectionTypeImpl instanceof ArrayType {
override Type getElementType() { result = ArrayType.super.getElementType() }
}

private class AddCollectionTypes extends ParamsCollectionTypeImpl {
private ConstructedType base;

AddCollectionTypes() {
exists(UnboundGenericType unboundbase |
base = this.getABaseType*() and unboundbase = base.getUnboundGeneric()
|
unboundbase instanceof SystemCollectionsGenericIEnumerableTInterface or
unboundbase instanceof SystemCollectionsGenericICollectionInterface or
unboundbase instanceof SystemCollectionsGenericIListTInterface or
unboundbase instanceof SystemCollectionsGenericIReadOnlyCollectionTInterface or
unboundbase instanceof SystemCollectionsGenericIReadOnlyListTInterface or
unboundbase instanceof SystemSpanStruct or
unboundbase instanceof SystemReadOnlySpanStruct
)
}

override Type getElementType() { result = base.getTypeArgument(0) }
}

final class ParamsCollectionType = ParamsCollectionTypeImpl;

/** Holds if `t` is a collection type. */
predicate isCollectionType(ValueOrRefType t) {
t.getABaseType*() instanceof SystemCollectionsIEnumerableInterface and
Expand Down
3 changes: 2 additions & 1 deletion csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import csharp
private import semmle.code.csharp.commons.Collections
private import RuntimeCallable

/** A call. */
Expand Down Expand Up @@ -1137,7 +1138,7 @@ private module Internal {
if p.isParams()
then (
j >= i and
paramType = p.getType().(ArrayType).getElementType()
paramType = p.getType().(ParamsCollectionType).getElementType()
) else (
i = j and
paramType = p.getType()
Expand Down
16 changes: 16 additions & 0 deletions csharp/ql/lib/semmle/code/csharp/frameworks/System.qll
Original file line number Diff line number Diff line change
Expand Up @@ -755,3 +755,19 @@ class SystemNotImplementedExceptionClass extends SystemClass {
class SystemDateTimeStruct extends SystemStruct {
SystemDateTimeStruct() { this.hasName("DateTime") }
}

/** The `System.Span<T>` struct. */
class SystemSpanStruct extends SystemUnboundGenericStruct {
SystemSpanStruct() {
this.hasName("Span`1") and
this.getNumberOfTypeParameters() = 1
}
}

/** The `System.ReadOnlySpan<T>` struct. */
class SystemReadOnlySpanStruct extends SystemUnboundGenericStruct {
SystemReadOnlySpanStruct() {
this.hasName("ReadOnlySpan`1") and
this.getNumberOfTypeParameters() = 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,21 @@ class SystemCollectionsGenericIDictionaryInterface extends SystemCollectionsGene
this.getNumberOfTypeParameters() = 2
}
}

/** The ``System.Collections.Generic.IReadOnlyCollection`1`` interface. */
class SystemCollectionsGenericIReadOnlyCollectionTInterface extends SystemCollectionsGenericUnboundGenericInterface
{
SystemCollectionsGenericIReadOnlyCollectionTInterface() {
this.hasName("IReadOnlyCollection`1") and
this.getNumberOfTypeParameters() = 1
}
}

/** The ``System.Collections.Generic.IReadOnlyList`1`` interface. */
class SystemCollectionsGenericIReadOnlyListTInterface extends SystemCollectionsGenericUnboundGenericInterface
{
SystemCollectionsGenericIReadOnlyListTInterface() {
this.hasName("IReadOnlyList`1") and
this.getNumberOfTypeParameters() = 1
}
}

0 comments on commit e1a52e3

Please sign in to comment.