Merge pull request #4821 from tamasvajk/feature/csharp9-cil-init-prop

C#: Extract init only accessors from CIL
This commit is contained in:
Tamás Vajk
2021-01-07 15:04:40 +01:00
committed by GitHub
30 changed files with 6525 additions and 2248 deletions

View File

@@ -0,0 +1,4 @@
lgtm,codescanning
* CIL extraction has been improved to store `modreq` and `modopt` custom modifiers.
The extracted information is surfaced through the `CustomModifierReceiver` class. Additionally,
the information is also used to evaluate the new `Setter::isInitOnly` predicate.

View File

@@ -76,9 +76,10 @@ namespace Semmle.Extraction.CIL.Entities
var typeSignature = md.DecodeSignature(Cx.TypeSignatureDecoder, this);
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var c in Parameters)
foreach (var c in parameters)
yield return c;
foreach (var c in PopulateFlags)
@@ -95,7 +96,12 @@ namespace Semmle.Extraction.CIL.Entities
}
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
yield return Tuples.cil_method(this, Name, declaringType, typeSignature.ReturnType);
foreach (var m in GetMethodExtractionProducts(Name, declaringType, typeSignature.ReturnType))
{
yield return m;
}
yield return Tuples.cil_method_source_declaration(this, this);
yield return Tuples.cil_method_location(this, Cx.Assembly);

View File

@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// An entity representing a field.
/// </summary>
internal abstract class Field : GenericContext, IMember
internal abstract class Field : GenericContext, IMember, ICustomModifierReceiver
{
protected Field(Context cx) : base(cx)
{
@@ -45,7 +45,13 @@ namespace Semmle.Extraction.CIL.Entities
{
get
{
yield return Tuples.cil_field(this, DeclaringType, Name, Type);
var t = Type;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
yield return Tuples.cil_field(this, DeclaringType, Name, t);
}
}

View File

@@ -76,12 +76,16 @@ namespace Semmle.Extraction.CIL.Entities
var typeSignature = mr.DecodeMethodSignature(Cx.TypeSignatureDecoder, this);
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
foreach (var p in Parameters) yield return p;
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var p in parameters) yield return p;
foreach (var f in PopulateFlags) yield return f;
yield return Tuples.cil_method(this, Name, DeclaringType, typeSignature.ReturnType);
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, typeSignature.ReturnType))
{
yield return m;
}
if (SourceDeclaration != null)
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);

View File

@@ -3,14 +3,13 @@ using System.Reflection.Metadata;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A method entity.
/// </summary>
internal abstract class Method : TypeContainer, IMember
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver
{
protected MethodTypeParameter[]? genericParams;
protected GenericContext gc;
@@ -21,6 +20,8 @@ namespace Semmle.Extraction.CIL.Entities
this.gc = gc;
}
public ITypeSignature ReturnType => signature.ReturnType;
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
public override IEnumerable<Type> MethodParameters =>
@@ -76,7 +77,7 @@ namespace Semmle.Extraction.CIL.Entities
public abstract bool IsStatic { get; }
protected IEnumerable<Parameter> MakeParameters(IEnumerable<Type> parameterTypes)
protected IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes)
{
var i = 0;
@@ -86,7 +87,26 @@ namespace Semmle.Extraction.CIL.Entities
}
foreach (var p in parameterTypes)
yield return Cx.Populate(new Parameter(Cx, this, i++, p));
{
var t = p;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
yield return Cx.Populate(new Parameter(Cx, this, i++, t));
}
}
protected IEnumerable<IExtractionProduct> GetMethodExtractionProducts(string name, Type declaringType, Type returnType)
{
var t = returnType;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
yield return Tuples.cil_method(this, name, declaringType, t);
}
}
}

View File

@@ -77,14 +77,19 @@ namespace Semmle.Extraction.CIL.Entities
throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}");
}
Parameters = MakeParameters(constructedTypeSignature.ParameterTypes).ToArray();
foreach (var p in Parameters)
var parameters = GetParameterExtractionProducts(constructedTypeSignature.ParameterTypes).ToArray();
Parameters = parameters.OfType<Parameter>().ToArray();
foreach (var p in parameters)
yield return p;
foreach (var f in PopulateFlags)
yield return f;
yield return Tuples.cil_method(this, Name, DeclaringType, constructedTypeSignature.ReturnType);
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, constructedTypeSignature.ReturnType))
{
yield return m;
}
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
if (typeParams.Length != unboundMethod.GenericParameterCount)

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Modified types are not written directly to trap files. Instead, the modifiers are stored
/// on the modifiable entity (field type, property/method/function pointer parameter or return types).
/// </summary>
internal sealed class ModifiedType : Type
{
public ModifiedType(Context cx, Type unmodified, Type modifier, bool isRequired) : base(cx)
{
Unmodified = unmodified;
Modifier = modifier;
IsRequired = isRequired;
}
public Type Unmodified { get; }
public Type Modifier { get; }
public bool IsRequired { get; }
public override CilTypeKind Kind => throw new NotImplementedException();
public override Namespace? ContainingNamespace => throw new NotImplementedException();
public override Type? ContainingType => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override int ThisTypeParameterCount => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override string Name => $"{Unmodified.Name} {(IsRequired ? "modreq" : "modopt")}({Modifier.Name})";
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(TextWriter trapFile, bool inContext) => throw new NotImplementedException();
}
}

View File

@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// A property.
/// </summary>
internal sealed class Property : LabelledEntity
internal sealed class Property : LabelledEntity, ICustomModifierReceiver
{
private readonly Handle handle;
private readonly Type type;
@@ -54,7 +54,15 @@ namespace Semmle.Extraction.CIL.Entities
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
var sig = pd.DecodeSignature(Cx.TypeSignatureDecoder, type);
yield return Tuples.cil_property(this, type, Cx.ShortName(pd.Name), sig.ReturnType);
var name = Cx.ShortName(pd.Name);
var t = sig.ReturnType;
if (t is ModifiedType mt)
{
t = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
yield return Tuples.cil_property(this, type, name, t);
var accessors = pd.GetAccessors();
if (!accessors.Getter.IsNil)

View File

@@ -1,6 +1,7 @@
using System.Reflection.Metadata;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CIL.Entities
{
@@ -138,21 +139,28 @@ namespace Semmle.Extraction.CIL.Entities
private class Modified : ITypeSignature
{
private readonly ITypeSignature unmodifiedType;
private readonly ITypeSignature modifier;
private readonly bool isRequired;
public Modified(ITypeSignature unmodifiedType)
public Modified(ITypeSignature unmodifiedType, ITypeSignature modifier, bool isRequired)
{
this.unmodifiedType = unmodifiedType;
this.modifier = modifier;
this.isRequired = isRequired;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
unmodifiedType.WriteId(trapFile, gc);
trapFile.Write(isRequired ? " modreq(" : " modopt(");
modifier.WriteId(trapFile, gc);
trapFile.Write(")");
}
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetModifiedType(ITypeSignature modifier, ITypeSignature unmodifiedType, bool isRequired)
{
return new Modified(unmodifiedType);
return new Modified(unmodifiedType, modifier, isRequired);
}
private class Pinned : ITypeSignature

View File

@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CIL.Entities
genericContext.GetGenericTypeParameter(index);
Type ISignatureTypeProvider<Type, GenericContext>.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) =>
unmodifiedType; // !! Not implemented properly
new ModifiedType(cx, unmodifiedType, modifier, isRequired);
Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) =>
cx.Populate(new PointerType(cx, elementType));

View File

@@ -0,0 +1,6 @@
namespace Semmle.Extraction.CIL
{
internal interface ICustomModifierReceiver
{
}
}

View File

@@ -188,6 +188,9 @@ namespace Semmle.Extraction.CIL
internal static Tuple cil_virtual(Method method) =>
new Tuple("cil_virtual", method);
internal static Tuple cil_custom_modifiers(ICustomModifierReceiver receiver, Type modifier, bool isRequired) =>
new Tuple("cil_custom_modifiers", receiver, modifier, isRequired ? 1 : 0);
internal static Tuple containerparent(Folder parent, IFileOrFolder child) =>
new Tuple("containerparent", parent, child);

View File

@@ -18,3 +18,4 @@ import ControlFlow
import DataFlow
import Attribute
import Stubs
import CustomModifierReceiver

View File

@@ -0,0 +1,21 @@
/**
* Provides a class to represent `modopt` and `modreq` declarations.
*/
private import CIL
private import dotnet
/**
* A class to represent entities that can receive custom modifiers. Custom modifiers can be attached to
* - the type of a `Field`,
* - the return type of a `Method` or `Property`,
* - the type of parameters.
* A `CustomModifierReceiver` is therefore either a `Field`, `Property`, `Method`, or `Parameter`.
*/
class CustomModifierReceiver extends Declaration, @cil_custom_modifier_receiver {
/** Holds if this targeted type has `modifier` applied as `modreq`. */
predicate hasRequiredCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 1) }
/** Holds if this targeted type has `modifier` applied as `modopt`. */
predicate hasOptionalCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 0) }
}

View File

@@ -82,7 +82,7 @@ class Member extends DotNet::Member, Declaration, @cil_member {
}
/** A property. */
class Property extends DotNet::Property, Member, @cil_property {
class Property extends DotNet::Property, Member, CustomModifierReceiver, @cil_property {
override string getName() { cil_property(this, _, result, _) }
/** Gets the type of this property. */

View File

@@ -66,7 +66,8 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation {
* A method, which corresponds to any callable in C#, including constructors,
* destructors, operators, accessors and so on.
*/
class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode, @cil_method {
class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode,
CustomModifierReceiver, @cil_method {
/**
* Gets a method implementation, if any. Note that there can
* be several implementations in different assemblies.
@@ -246,6 +247,13 @@ class Setter extends Accessor {
Setter() { cil_setter(_, this) }
override Property getProperty() { cil_setter(result, this) }
/** Holds if this setter is an `init` accessor. */
predicate isInitOnly() {
exists(Type t | t.getQualifiedName() = "System.Runtime.CompilerServices.IsExternalInit" |
this.hasRequiredCustomModifier(t)
)
}
}
/**

View File

@@ -57,7 +57,7 @@ class LocalVariable extends StackVariable, @cil_local_variable {
}
/** A method parameter. */
class Parameter extends DotNet::Parameter, StackVariable, @cil_parameter {
class Parameter extends DotNet::Parameter, StackVariable, CustomModifierReceiver, @cil_parameter {
/** Gets the method declaring this parameter. */
override Method getMethod() { this = result.getARawParameter() }
@@ -122,7 +122,7 @@ class ThisParameter extends Parameter {
}
/** A field. */
class Field extends DotNet::Field, Variable, Member, @cil_field {
class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @cil_field {
override string toString() { result = getName() }
override string toStringWithTypes() {

View File

@@ -588,16 +588,19 @@ predicate implementsEquals(ValueOrRefType t) { getInvokedEqualsMethod(t).getDecl
* from the `object.Equals(object)` method inherited by `t`.
*/
Method getInvokedEqualsMethod(ValueOrRefType t) {
result = getInheritedEqualsMethod(t) and
result = getInheritedEqualsMethod(t, _) and
not exists(getInvokedIEquatableEqualsMethod(t, result))
or
exists(EqualsMethod eq |
result = getInvokedIEquatableEqualsMethod(t, eq) and
getInheritedEqualsMethod(t) = eq
getInheritedEqualsMethod(t, _) = eq
)
}
private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t) { t.hasMethod(result) }
pragma[noinline]
private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t, ValueOrRefType decl) {
t.hasMethod(result) and decl = result.getDeclaringType()
}
/**
* Equals method `eq` is inherited by `t`, `t` overrides `IEquatable<T>.Equals(T)`
@@ -621,10 +624,9 @@ private EqualsMethod getInheritedEqualsMethod(ValueOrRefType t) { t.hasMethod(re
*/
private IEquatableEqualsMethod getInvokedIEquatableEqualsMethod(ValueOrRefType t, EqualsMethod eq) {
t.hasMethod(result) and
eq = getInheritedEqualsMethod(t.getBaseClass()) and
exists(IEquatableEqualsMethod ieem |
result = ieem.getAnOverrider*() and
eq.getDeclaringType() = ieem.getDeclaringType()
eq = getInheritedEqualsMethod(t.getBaseClass(), ieem.getDeclaringType())
|
not ieem.fromSource()
or

View File

@@ -1712,6 +1712,7 @@ cil_field(
@cil_variable = @cil_field | @cil_stack_variable;
@cil_stack_variable = @cil_local_variable | @cil_parameter;
@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type
#keyset[method, index]
cil_parameter(
@@ -1726,6 +1727,12 @@ cil_parameter_out(unique int id: @cil_parameter ref);
cil_setter(unique int prop: @cil_property ref,
int method: @cil_method ref);
#keyset[id, modifier]
cil_custom_modifiers(
int id: @cil_custom_modifier_receiver ref,
int modifier: @cil_type ref,
int kind: int ref); // modreq: 1, modopt: 0
cil_getter(unique int prop: @cil_property ref,
int method: @cil_method ref);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
// semmle-extractor-options: --cil
using System;
class Test
{
static void Main(string[] args)
{
}
}

View File

@@ -0,0 +1,13 @@
namespace System.Runtime.CompilerServices
{
class IsExternalInit { }
}
namespace cil_init_prop
{
class SomeClass
{
public int Prop1 { get; set; }
public int Prop2 { get; init; }
}
}

View File

@@ -0,0 +1,107 @@
| AsRef | System.Runtime.InteropServices.InAttribute | modreq |
| BeginInvoke | System.Runtime.InteropServices.InAttribute | modreq |
| EndInvoke | System.Runtime.InteropServices.InAttribute | modreq |
| EventWriteTransfer | System.Runtime.InteropServices.InAttribute | modreq |
| GetPinnableReference | System.Runtime.InteropServices.InAttribute | modreq |
| Invoke | System.Runtime.InteropServices.InAttribute | modreq |
| Max | System.Runtime.InteropServices.InAttribute | modreq |
| Min | System.Runtime.InteropServices.InAttribute | modreq |
| Value | System.Runtime.CompilerServices.IsVolatile | modreq |
| _bufferedValues | System.Runtime.CompilerServices.IsVolatile | modreq |
| _bufferedValuesIndex | System.Runtime.CompilerServices.IsVolatile | modreq |
| _callbackPartitions | System.Runtime.CompilerServices.IsVolatile | modreq |
| _canceled | System.Runtime.CompilerServices.IsVolatile | modreq |
| _container | System.Runtime.CompilerServices.IsVolatile | modreq |
| _fullyInitialized | System.Runtime.CompilerServices.IsVolatile | modreq |
| _head | System.Runtime.CompilerServices.IsVolatile | modreq |
| _initialized | System.Runtime.CompilerServices.IsVolatile | modreq |
| _isFullyInitialized | System.Runtime.CompilerServices.IsVolatile | modreq |
| _isWriterInProgress | System.Runtime.CompilerServices.IsVolatile | modreq |
| _kernelEvent | System.Runtime.CompilerServices.IsVolatile | modreq |
| _localTimeZone | System.Runtime.CompilerServices.IsVolatile | modreq |
| _next | System.Runtime.CompilerServices.IsVolatile | modreq |
| _notifyWhenNoCallbacksRunning | System.Runtime.CompilerServices.IsVolatile | modreq |
| _oldKeepAlive | System.Runtime.CompilerServices.IsVolatile | modreq |
| _owner | System.Runtime.CompilerServices.IsVolatile | modreq |
| _pauseTicks | System.Runtime.CompilerServices.IsVolatile | modreq |
| _previous | System.Runtime.CompilerServices.IsVolatile | modreq |
| _queues | System.Runtime.CompilerServices.IsVolatile | modreq |
| _saDurationFormats | System.Runtime.CompilerServices.IsVolatile | modreq |
| _saLongTimes | System.Runtime.CompilerServices.IsVolatile | modreq |
| _saShortTimes | System.Runtime.CompilerServices.IsVolatile | modreq |
| _slotArray | System.Runtime.CompilerServices.IsVolatile | modreq |
| _state | System.Runtime.CompilerServices.IsVolatile | modreq |
| _tail | System.Runtime.CompilerServices.IsVolatile | modreq |
| _threadIDExecutingCallbacks | System.Runtime.CompilerServices.IsVolatile | modreq |
| _timer | System.Runtime.CompilerServices.IsVolatile | modreq |
| _version | System.Runtime.CompilerServices.IsVolatile | modreq |
| _waCalendars | System.Runtime.CompilerServices.IsVolatile | modreq |
| currentTimeZone | System.Runtime.CompilerServices.IsVolatile | modreq |
| g_nameCache | System.Runtime.CompilerServices.IsVolatile | modreq |
| get_Current | System.Runtime.InteropServices.InAttribute | modreq |
| get_Item | System.Runtime.InteropServices.InAttribute | modreq |
| m_Dispatchers | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_Next | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_array | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_channelData | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_combinedState | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_completionCountdown | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_completionEvent | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_continuationObject | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_currentCount | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_declaringType | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_etwProvider | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_eventData | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_eventObj | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_eventPipeProvider | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_exceptionalChildren | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_exceptionsHolder | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_faultExceptions | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_first | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_head | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_headIndex | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_internalCancellationRequested | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_isHandled | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_last | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_lock | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_mask | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_nameIsCached | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_rawManifest | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_signature | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_stateFlags | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_tail | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_tailIndex | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_taskId | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_taskSchedulerId | System.Runtime.CompilerServices.IsVolatile | modreq |
| m_waitHandle | System.Runtime.CompilerServices.IsVolatile | modreq |
| numOutstandingThreadRequests | System.Runtime.CompilerServices.IsVolatile | modreq |
| property Current | System.Runtime.InteropServices.InAttribute | modreq |
| property Item | System.Runtime.InteropServices.InAttribute | modreq |
| s_DefaultThreadCurrentCulture | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_DefaultThreadCurrentUICulture | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_Invariant | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_LcidCachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_NameCachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_anonymouslyHostedDynamicMethodsModule | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_cachedCultures | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_cachedRegions | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_currentRegionInfo | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_defaultBinder | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_defaultInstance | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_indentSize | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_initialized | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_invariant | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_invariantInfo | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_jajpDTFI | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_japaneseEraInfo | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_knownWords | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_lastProcessorCountRefreshTicks | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_processorCount | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_provider | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_providers | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_regionNames | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_userDefaultCulture | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_userDefaultUICulture | System.Runtime.CompilerServices.IsVolatile | modreq |
| s_zhtwDTFI | System.Runtime.CompilerServices.IsVolatile | modreq |
| set_Prop2 | System.Runtime.CompilerServices.IsExternalInit | modreq |
| threadPoolInitialized | System.Runtime.CompilerServices.IsVolatile | modreq |

View File

@@ -0,0 +1,13 @@
import semmle.code.cil.Type
bindingset[kind]
private string getKind(int kind) { if kind = 1 then result = "modreq" else result = "modopt" }
from string receiver, string modifier, int kind
where
exists(Type modType, CustomModifierReceiver cmr |
receiver = cmr.toString() and
cil_custom_modifiers(cmr, modType, kind) and
modType.getQualifiedName() = modifier
)
select receiver, modifier, getKind(kind)

View File

@@ -0,0 +1,2 @@
| cil-init-prop.dll:0:0:0:0 | set_Prop1 | set |
| cil-init-prop.dll:0:0:0:0 | set_Prop2 | init |

View File

@@ -0,0 +1,8 @@
import semmle.code.cil.Method
import semmle.code.csharp.Location
private string getType(Setter s) { if s.isInitOnly() then result = "init" else result = "set" }
from Setter s
where s.getLocation().(Assembly).getName() = "cil-init-prop"
select s, getType(s)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Added 'cil_custom_modifiers' to store custom modifiers ('modreq', 'modopt').
compatibility: backwards