mirror of
https://github.com/github/codeql.git
synced 2025-12-17 17:23:36 +01:00
95 lines
3.6 KiB
C#
95 lines
3.6 KiB
C#
using System.IO;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Semmle.Extraction.Kinds;
|
|
|
|
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
|
{
|
|
internal abstract class ElementAccess : Expression<ExpressionSyntax>
|
|
{
|
|
protected ElementAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, BracketedArgumentListSyntax argumentList)
|
|
: base(info.SetKind(GetKind(info.Context, qualifier)))
|
|
{
|
|
this.qualifier = qualifier;
|
|
this.argumentList = argumentList;
|
|
}
|
|
|
|
private readonly ExpressionSyntax qualifier;
|
|
private readonly BracketedArgumentListSyntax argumentList;
|
|
|
|
protected override void PopulateExpression(TextWriter trapFile)
|
|
{
|
|
if (Kind == ExprKind.POINTER_INDIRECTION)
|
|
{
|
|
var qualifierInfo = new ExpressionNodeInfo(Context, qualifier, this, 0);
|
|
var add = new Expression(new ExpressionInfo(Context, qualifierInfo.Type, Location, ExprKind.ADD, this, 0, isCompilerGenerated: false, null));
|
|
qualifierInfo.SetParent(add, 0);
|
|
CreateFromNode(qualifierInfo);
|
|
PopulateArguments(trapFile, argumentList, 1);
|
|
}
|
|
else
|
|
{
|
|
Create(Context, qualifier, this, -1);
|
|
PopulateArguments(trapFile, argumentList, 0);
|
|
|
|
var symbolInfo = Context.GetSymbolInfo(base.Syntax);
|
|
|
|
if (symbolInfo.Symbol is IPropertySymbol indexer)
|
|
{
|
|
trapFile.expr_access(this, Indexer.Create(Context, indexer));
|
|
}
|
|
}
|
|
}
|
|
|
|
public sealed override Microsoft.CodeAnalysis.Location? ReportingLocation => base.ReportingLocation;
|
|
|
|
private static bool IsArray(ITypeSymbol symbol) =>
|
|
symbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Array || symbol.IsInlineArray();
|
|
|
|
private static ExprKind GetKind(Context cx, ExpressionSyntax qualifier)
|
|
{
|
|
var qualifierType = cx.GetType(qualifier);
|
|
|
|
// This is a compilation error, so make a guess and continue.
|
|
if (qualifierType.Symbol is null)
|
|
return ExprKind.ARRAY_ACCESS;
|
|
|
|
if (qualifierType.Symbol.TypeKind == Microsoft.CodeAnalysis.TypeKind.Pointer)
|
|
{
|
|
// Convert expressions of the form a[b] into *(a+b)
|
|
return ExprKind.POINTER_INDIRECTION;
|
|
}
|
|
|
|
return IsDynamic(cx, qualifier)
|
|
? ExprKind.DYNAMIC_ELEMENT_ACCESS
|
|
: IsArray(qualifierType.Symbol)
|
|
? ExprKind.ARRAY_ACCESS
|
|
: ExprKind.INDEXER_ACCESS;
|
|
}
|
|
}
|
|
|
|
internal class NormalElementAccess : ElementAccess
|
|
{
|
|
private NormalElementAccess(ExpressionNodeInfo info)
|
|
: base(info, ((ElementAccessExpressionSyntax)info.Node).Expression, ((ElementAccessExpressionSyntax)info.Node).ArgumentList) { }
|
|
|
|
public static Expression Create(ExpressionNodeInfo info) => new NormalElementAccess(info).TryPopulate();
|
|
}
|
|
|
|
internal class BindingElementAccess : ElementAccess
|
|
{
|
|
private BindingElementAccess(ExpressionNodeInfo info)
|
|
: base(info, FindConditionalQualifier(info.Node), ((ElementBindingExpressionSyntax)info.Node).ArgumentList)
|
|
{
|
|
}
|
|
|
|
public static Expression Create(ExpressionNodeInfo info) => new BindingElementAccess(info).TryPopulate();
|
|
|
|
protected override void PopulateExpression(TextWriter trapFile)
|
|
{
|
|
base.PopulateExpression(trapFile);
|
|
MakeConditional(trapFile);
|
|
}
|
|
}
|
|
}
|