mirror of
https://github.com/github/codeql.git
synced 2026-03-31 12:48:17 +02:00
C#: Don't extract expanded assignments and swap child indices for assignments.
This commit is contained in:
@@ -22,26 +22,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
|
||||
protected override void PopulateExpression(TextWriter trapFile)
|
||||
{
|
||||
var operatorKind = OperatorKind;
|
||||
if (operatorKind.HasValue)
|
||||
{
|
||||
// Convert assignment such as `a += b` into `a = a + b`.
|
||||
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, Type, Location, ExprKind.SIMPLE_ASSIGN, this, 2, isCompilerGenerated: true, null));
|
||||
Create(Context, Syntax.Left, simpleAssignExpr, 1);
|
||||
var opexpr = new Expression(new ExpressionInfo(Context, Type, Location, operatorKind.Value, simpleAssignExpr, 0, isCompilerGenerated: true, null));
|
||||
Create(Context, Syntax.Left, opexpr, 0, isCompilerGenerated: true);
|
||||
Create(Context, Syntax.Right, opexpr, 1);
|
||||
opexpr.OperatorCall(trapFile, Syntax);
|
||||
}
|
||||
else
|
||||
{
|
||||
Create(Context, Syntax.Left, this, 1);
|
||||
Create(Context, Syntax.Right, this, 0);
|
||||
Create(Context, Syntax.Left, this, 0);
|
||||
Create(Context, Syntax.Right, this, 1);
|
||||
|
||||
if (Kind == ExprKind.ADD_EVENT || Kind == ExprKind.REMOVE_EVENT)
|
||||
{
|
||||
OperatorCall(trapFile, Syntax);
|
||||
}
|
||||
if (Kind != ExprKind.SIMPLE_ASSIGN && Kind != ExprKind.ASSIGN_COALESCE)
|
||||
{
|
||||
OperatorCall(trapFile, Syntax);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,56 +94,5 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
|
||||
return kind;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the kind of this assignment operator (<code>null</code> if the
|
||||
/// assignment is not an assignment operator). For example, the operator
|
||||
/// kind of `*=` is `*`.
|
||||
/// </summary>
|
||||
private ExprKind? OperatorKind
|
||||
{
|
||||
get
|
||||
{
|
||||
var kind = Kind;
|
||||
if (kind == ExprKind.REMOVE_EVENT || kind == ExprKind.ADD_EVENT || kind == ExprKind.SIMPLE_ASSIGN)
|
||||
return null;
|
||||
|
||||
if (CallType.AdjustKind(kind) == ExprKind.OPERATOR_INVOCATION)
|
||||
return ExprKind.OPERATOR_INVOCATION;
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case ExprKind.ASSIGN_ADD:
|
||||
return ExprKind.ADD;
|
||||
case ExprKind.ASSIGN_AND:
|
||||
return ExprKind.BIT_AND;
|
||||
case ExprKind.ASSIGN_DIV:
|
||||
return ExprKind.DIV;
|
||||
case ExprKind.ASSIGN_LSHIFT:
|
||||
return ExprKind.LSHIFT;
|
||||
case ExprKind.ASSIGN_MUL:
|
||||
return ExprKind.MUL;
|
||||
case ExprKind.ASSIGN_OR:
|
||||
return ExprKind.BIT_OR;
|
||||
case ExprKind.ASSIGN_REM:
|
||||
return ExprKind.REM;
|
||||
case ExprKind.ASSIGN_RSHIFT:
|
||||
return ExprKind.RSHIFT;
|
||||
case ExprKind.ASSIGN_URSHIFT:
|
||||
return ExprKind.URSHIFT;
|
||||
case ExprKind.ASSIGN_SUB:
|
||||
return ExprKind.SUB;
|
||||
case ExprKind.ASSIGN_XOR:
|
||||
return ExprKind.BIT_XOR;
|
||||
case ExprKind.ASSIGN_COALESCE:
|
||||
return ExprKind.NULL_COALESCING;
|
||||
default:
|
||||
Context.ModelError(Syntax, $"Couldn't unfold assignment of type {kind}");
|
||||
return ExprKind.UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public new CallType CallType => GetCallType(Context, Syntax);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,8 +83,22 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
var assignmentInfo = new ExpressionNodeInfo(Context, init, this, child++).SetKind(ExprKind.SIMPLE_ASSIGN);
|
||||
var assignmentEntity = new Expression(assignmentInfo);
|
||||
var target = Context.GetSymbolInfo(assignment.Left);
|
||||
|
||||
// If the target is null, then assume that this is an array initializer (of the form `[...] = ...`)
|
||||
var access = target.Symbol is null ?
|
||||
new Expression(new ExpressionNodeInfo(Context, assignment.Left, assignmentEntity, 0).SetKind(ExprKind.ARRAY_ACCESS)) :
|
||||
Access.Create(new ExpressionNodeInfo(Context, assignment.Left, assignmentEntity, 0), target.Symbol, false, Context.CreateEntity(target.Symbol));
|
||||
|
||||
if (assignment.Left is ImplicitElementAccessSyntax iea)
|
||||
{
|
||||
// An array/indexer initializer of the form `[...] = ...`
|
||||
access.PopulateArguments(trapFile, iea.ArgumentList.Arguments, 0);
|
||||
}
|
||||
|
||||
var typeInfoRight = Context.GetTypeInfo(assignment.Right);
|
||||
if (typeInfoRight.Type is null)
|
||||
{
|
||||
// The type may be null for nested initializers such as
|
||||
// ```csharp
|
||||
// new ClassWithArrayField() { As = { [0] = a } }
|
||||
@@ -92,21 +106,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
// In this case we take the type from the assignment
|
||||
// `As = { [0] = a }` instead
|
||||
typeInfoRight = assignmentInfo.TypeInfo;
|
||||
CreateFromNode(new ExpressionNodeInfo(Context, assignment.Right, assignmentEntity, 0, typeInfoRight));
|
||||
|
||||
var target = Context.GetSymbolInfo(assignment.Left);
|
||||
|
||||
// If the target is null, then assume that this is an array initializer (of the form `[...] = ...`)
|
||||
|
||||
var access = target.Symbol is null ?
|
||||
new Expression(new ExpressionNodeInfo(Context, assignment.Left, assignmentEntity, 1).SetKind(ExprKind.ARRAY_ACCESS)) :
|
||||
Access.Create(new ExpressionNodeInfo(Context, assignment.Left, assignmentEntity, 1), target.Symbol, false, Context.CreateEntity(target.Symbol));
|
||||
|
||||
if (assignment.Left is ImplicitElementAccessSyntax iea)
|
||||
{
|
||||
// An array/indexer initializer of the form `[...] = ...`
|
||||
access.PopulateArguments(trapFile, iea.ArgumentList.Arguments, 0);
|
||||
}
|
||||
CreateFromNode(new ExpressionNodeInfo(Context, assignment.Right, assignmentEntity, 1, typeInfoRight));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -41,11 +41,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
var loc = Context.CreateLocation(init.GetLocation());
|
||||
|
||||
var assignment = new Expression(new ExpressionInfo(Context, type, loc, ExprKind.SIMPLE_ASSIGN, objectInitializer, child++, isCompilerGenerated: false, null));
|
||||
Create(Context, init.Expression, assignment, 0);
|
||||
Property.Create(Context, property);
|
||||
|
||||
var access = new Expression(new ExpressionInfo(Context, type, loc, ExprKind.PROPERTY_ACCESS, assignment, 1, isCompilerGenerated: false, null));
|
||||
var access = new Expression(new ExpressionInfo(Context, type, loc, ExprKind.PROPERTY_ACCESS, assignment, 0, isCompilerGenerated: false, null));
|
||||
trapFile.expr_access(access, propEntity);
|
||||
|
||||
Create(Context, init.Expression, assignment, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,12 +94,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
child
|
||||
);
|
||||
|
||||
Expression.Create(cx, Expr, decl, 0);
|
||||
|
||||
var nameLoc = cx.CreateLocation(name.GetLocation());
|
||||
var access = new Expression(new ExpressionInfo(cx, type, nameLoc, ExprKind.LOCAL_VARIABLE_ACCESS, decl, 1, isCompilerGenerated: false, null));
|
||||
var access = new Expression(new ExpressionInfo(cx, type, nameLoc, ExprKind.LOCAL_VARIABLE_ACCESS, decl, 0, isCompilerGenerated: false, null));
|
||||
cx.TrapWriter.Writer.expr_access(access, LocalVariable.Create(cx, variableSymbol));
|
||||
|
||||
Expression.Create(cx, Expr, decl, 1);
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
||||
@@ -176,11 +176,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
|
||||
if (d.Initializer is not null)
|
||||
{
|
||||
Create(cx, d.Initializer.Value, ret, 0);
|
||||
|
||||
// Create an access
|
||||
var access = new Expression(new ExpressionInfo(cx, type, localVar.Location, ExprKind.LOCAL_VARIABLE_ACCESS, ret, 1, isCompilerGenerated: false, null));
|
||||
var access = new Expression(new ExpressionInfo(cx, type, localVar.Location, ExprKind.LOCAL_VARIABLE_ACCESS, ret, 0, isCompilerGenerated: false, null));
|
||||
cx.TrapWriter.Writer.expr_access(access, localVar);
|
||||
|
||||
Create(cx, d.Initializer.Value, ret, 1);
|
||||
}
|
||||
|
||||
if (d.Parent is VariableDeclarationSyntax decl)
|
||||
|
||||
@@ -116,9 +116,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
var type = Symbol.GetAnnotatedType();
|
||||
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, isCompilerGenerated: true, constValue));
|
||||
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer, simpleAssignExpr, 0));
|
||||
var access = new Expression(new ExpressionInfo(Context, type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, isCompilerGenerated: true, constValue));
|
||||
var access = new Expression(new ExpressionInfo(Context, type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 0, isCompilerGenerated: true, constValue));
|
||||
trapFile.expr_access(access, this);
|
||||
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer, simpleAssignExpr, 1));
|
||||
return access;
|
||||
}
|
||||
|
||||
|
||||
@@ -94,9 +94,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
var loc = Context.CreateLocation(initializer!.GetLocation());
|
||||
var annotatedType = AnnotatedTypeSymbol.CreateNotAnnotated(Symbol.Type);
|
||||
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, isCompilerGenerated: true, null));
|
||||
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0));
|
||||
var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 1, isCompilerGenerated: true, null));
|
||||
var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 0, isCompilerGenerated: true, null));
|
||||
trapFile.expr_access(access, this);
|
||||
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 1));
|
||||
if (!Symbol.IsStatic)
|
||||
{
|
||||
This.CreateImplicit(Context, Symbol.ContainingType, Location, access, -1);
|
||||
|
||||
Reference in New Issue
Block a user