diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll index 698f0f937ae..00a805c0858 100644 --- a/csharp/ql/lib/semmle/code/csharp/Type.qll +++ b/csharp/ql/lib/semmle/code/csharp/Type.qll @@ -11,6 +11,7 @@ private import dotnet private import semmle.code.csharp.metrics.Coupling private import TypeRef private import semmle.code.csharp.frameworks.System +private import semmle.code.csharp.frameworks.system.runtime.CompilerServices /** * A type. @@ -1008,6 +1009,58 @@ class NullableType extends ValueType, ConstructedType, @nullable_type { override string getAPrimaryQlClass() { result = "NullableType" } } +/** + * An inline array type, for example `MyInlineArray` in + * ```csharp + * [System.Runtime.CompilerServices.InlineArray(10)] + * public struct MyInlineArray + * { + * private int _elements0; + * } + * ``` + */ +class InlineArrayType extends ValueType, @inline_array_type { + private SystemRuntimeCompilerServicesInlineArrayAttribute inline_attribute; + private Field element_type_field; + + InlineArrayType() { + inline_attribute = this.(Attributable).getAnAttribute() and + element_type_field = this.getAField() and + not element_type_field.isStatic() and + not element_type_field.isConst() + } + + /** + * Gets the element type of this inline array. + */ + Type getElementType() { result = element_type_field.getType() } + + /** + * Gets the rank of this inline array (inline arrays always have rank 1). + */ + int getRank() { result = 1 } + + /** + * Gets the length of this inline array. + */ + int getLength() { result = inline_attribute.getLength() } + + /** + * Gets the dimension of this inline array. + */ + int getDimension() { + exists(Type elem | elem = this.getElementType() | + result = elem.(InlineArrayType).getDimension() + 1 + or + result = elem.(ArrayType).getDimension() + 1 + or + not elem instanceof ArrayType and not elem instanceof InlineArrayType and result = 1 + ) + } + + override string getAPrimaryQlClass() { result = "InlineArrayType" } +} + /** * An array type, for example `int[]`. */ diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll index 2b37f8c0aac..60f7ecd82f1 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll @@ -70,3 +70,15 @@ class SystemRuntimeCompilerServicesConfiguredTaskAwaitableTConfiguredTaskAwaiter /** Gets the field that stores the underlying task. */ Field getUnderlyingTaskField() { result = this.getAField() and result.hasName("m_task") } } + +/** An attribute of type `System.Runtime.CompilerServices.InlineArrayAttribute`. */ +class SystemRuntimeCompilerServicesInlineArrayAttribute extends Attribute { + SystemRuntimeCompilerServicesInlineArrayAttribute() { + this.getType().hasFullyQualifiedName("System.Runtime.CompilerServices", "InlineArrayAttribute") + } + + /** + * Gets the length of the inline array. + */ + int getLength() { result = this.getConstructorArgument(0).getValue().toInt() } +}