зеркало из https://github.com/microsoft/rudder.git
Preliminary (and rough) support for JsonObjects with hard coded functions
Minor touches (should be cleaned) to allow debugging.
This commit is contained in:
Родитель
0d9c161526
Коммит
a9ffd74121
|
@ -19,7 +19,7 @@ namespace ScopeProgramAnalysis
|
|||
{
|
||||
public const string SCOPE_ROW_ENUMERATOR_METHOD = "System.Collections.Generic.IEnumerable<ScopeRuntime.Row>.GetEnumerator";
|
||||
}
|
||||
public enum ProtectedRowKind { Unknown, Input, Output };
|
||||
public enum ProtectedRowKind { Unknown, Input, Output, Json };
|
||||
public class ProtectedRowNode : ParameterNode
|
||||
{
|
||||
public ProtectedRowKind RowKind { get; private set; }
|
||||
|
|
|
@ -329,7 +329,7 @@ namespace ScopeProgramAnalysis
|
|||
callInfo.CallerState.Dependencies.A3_Fields.UnionWith(exitResult.Dependencies.A3_Fields);
|
||||
|
||||
|
||||
callInfo.CallerState.Dependencies.IsTop = exitResult.Dependencies.IsTop;
|
||||
callInfo.CallerState.Dependencies.IsTop |= exitResult.Dependencies.IsTop;
|
||||
|
||||
if (callInfo.CallLHS != null)
|
||||
{
|
||||
|
|
|
@ -73,22 +73,22 @@ namespace Backend.Analyses
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Representation of a column in a SCOPE table.
|
||||
///
|
||||
/// If the actual column is known, then this contains its name, position, and type.
|
||||
/// There might also be partial information, e.g., the name might be known, but not
|
||||
/// the position or type.
|
||||
///
|
||||
/// There is a special instance that represents *all* columns (e.g., if the schema
|
||||
/// is unknown and there is a call to Row.CopyTo) and a special instance that represents
|
||||
/// an unknown column (i.e., TOP).
|
||||
/// Every instance is exactly one of TOP, ALL, or known.
|
||||
///
|
||||
/// TODO: Should instances be immutable?
|
||||
/// </summary>
|
||||
public class Column
|
||||
|
||||
/// <summary>
|
||||
/// Representation of a column in a SCOPE table.
|
||||
///
|
||||
/// If the actual column is known, then this contains its name, position, and type.
|
||||
/// There might also be partial information, e.g., the name might be known, but not
|
||||
/// the position or type.
|
||||
///
|
||||
/// There is a special instance that represents *all* columns (e.g., if the schema
|
||||
/// is unknown and there is a call to Row.CopyTo) and a special instance that represents
|
||||
/// an unknown column (i.e., TOP).
|
||||
/// Every instance is exactly one of TOP, ALL, or known.
|
||||
///
|
||||
/// TODO: Should instances be immutable?
|
||||
/// </summary>
|
||||
public class Column
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
|
||||
public static readonly Column TOP = new Column() { IsTOP = true };
|
||||
|
@ -268,8 +268,31 @@ namespace Backend.Analyses
|
|||
}
|
||||
}
|
||||
|
||||
public class TraceableJsonField : TraceableColumn
|
||||
{
|
||||
public string Key { get; private set; }
|
||||
public TraceableJsonField(TraceableTable table, Column column, String key) : base(table, column)
|
||||
{
|
||||
this.Key = key;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format(CultureInfo.InvariantCulture, "Col({0},Json.{1}.{2})", TableName, Column, Key);
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as TraceableJsonField;
|
||||
return oth != null && oth.Key.Equals(this.Key)
|
||||
&& base.Equals(oth);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode() + Key.GetHashCode() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
public class TraceableCounter : Traceable
|
||||
|
||||
public class TraceableCounter : Traceable
|
||||
{
|
||||
public TraceableTable Table { get; private set; }
|
||||
public TraceableCounter(TraceableTable table) : base(table)
|
||||
|
@ -723,21 +746,27 @@ namespace Backend.Analyses
|
|||
|
||||
// this is a[loc(o.f)]
|
||||
var nodes = currentPTG.GetTargets(fieldAccess.Instance);
|
||||
if (nodes.Any())
|
||||
{
|
||||
// TODO: SHould I only consider the clousure fields?
|
||||
traceables.UnionWith(this.State.GetHeapTraceables(fieldAccess.Instance, fieldAccess.Field));
|
||||
//if(IsClousureType(fieldAccess.Instance))
|
||||
{
|
||||
traceables.AddRange(this.State.GetTraceables(fieldAccess.Instance));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
this.State.SetTOP();
|
||||
AnalysisStats.AddAnalysisReason(new AnalysisReason(this.method, loadStmt, "Trying to load a field with no objects associated"));
|
||||
}
|
||||
if (nodes.Any())
|
||||
{
|
||||
// TODO: SHould I only consider the clousure fields?
|
||||
traceables.UnionWith(this.State.GetHeapTraceables(fieldAccess.Instance, fieldAccess.Field));
|
||||
//if(IsClousureType(fieldAccess.Instance))
|
||||
{
|
||||
traceables.AddRange(this.State.GetTraceables(fieldAccess.Instance));
|
||||
}
|
||||
var jsonNodes = nodes.Where(n => n.Kind == SimplePTGNodeKind.Json);
|
||||
if (jsonNodes.Any())
|
||||
{
|
||||
var jsonTraceables = traceables.OfType<TraceableColumn>().Where(t => t.TableKind == ProtectedRowKind.Input).Select(t => new TraceableJsonField(t.Table, t.Column, fieldAccess.FieldName));
|
||||
this.State.AssignTraceables(loadStmt.Result, jsonTraceables);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.State.SetTOP();
|
||||
AnalysisStats.AddAnalysisReason(new AnalysisReason(this.method, loadStmt, "Trying to load a field with no objects associated"));
|
||||
}
|
||||
//}
|
||||
this.State.AssignTraceables(loadStmt.Result, traceables);
|
||||
}
|
||||
|
@ -929,7 +958,8 @@ namespace Backend.Analyses
|
|||
|
||||
if (instruction.HasOperand)
|
||||
{
|
||||
var rv = this.iteratorDependencyAnalysis.ReturnVariable;
|
||||
// var rv = this.iteratorDependencyAnalysis.ReturnVariable;
|
||||
var rv = instruction.Operand;
|
||||
this.State.CopyTraceables(this.iteratorDependencyAnalysis.ReturnVariable, rv);
|
||||
}
|
||||
}
|
||||
|
@ -949,9 +979,16 @@ namespace Backend.Analyses
|
|||
var methodInvoked = methodCallStmt.Method;
|
||||
var callResult = methodCallStmt.Result;
|
||||
|
||||
// We are analyzing instructions of the form this.table.Schema.IndexOf("columnLiteral")
|
||||
// to maintain a mapping between column numbers and literals
|
||||
var isSchemaMethod = HandleSchemaRelatedMethod(methodCallStmt, methodInvoked);
|
||||
if (methodInvoked.Name.Value=="DeserializeObject")
|
||||
{
|
||||
UpdateCall(methodCallStmt, false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// We are analyzing instructions of the form this.table.Schema.IndexOf("columnLiteral")
|
||||
// to maintain a mapping between column numbers and literals
|
||||
var isSchemaMethod = HandleSchemaRelatedMethod(methodCallStmt, methodInvoked);
|
||||
if (!isSchemaMethod)
|
||||
{
|
||||
var isScopeRowMethod = HandleScopeRowMethods(methodCallStmt, methodInvoked);
|
||||
|
@ -993,9 +1030,9 @@ namespace Backend.Analyses
|
|||
{
|
||||
|
||||
// For the demo I'll skip this methods that do anything important
|
||||
if (isMethodToInline && !methodInvoked.IsConstructor())
|
||||
{ }
|
||||
else
|
||||
//if (isMethodToInline && !methodInvoked.IsConstructor())
|
||||
//{ }
|
||||
//else
|
||||
{
|
||||
// This updates the Dep Domain and the PTG
|
||||
var computedCalles = this.iteratorDependencyAnalysis.interproceduralManager.ComputePotentialCallees(instruction, currentPTG);
|
||||
|
@ -1207,25 +1244,25 @@ namespace Backend.Analyses
|
|||
// base.Default(instruction);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special treatment for collection methdod: some are pure, other only modify the receiver
|
||||
/// </summary>
|
||||
/// <param name="methodCallStmt"></param>
|
||||
/// <param name="methodInvoked"></param>
|
||||
/// <returns></returns>
|
||||
private bool HandleCollectionMethod(MethodCallInstruction methodCallStmt, IMethodReference methodInvoked)
|
||||
{
|
||||
var pureCollectionMethods = new HashSet<String>() { "Contains", "ContainsKey", "Count", "get_Count", "First"};
|
||||
var pureEnumerationMethods = new HashSet<String>() { "Select", "Where", "Any", "Count", "GroupBy", "Max", "Min", "First" };
|
||||
|
||||
var result = true;
|
||||
/// <summary>
|
||||
/// Special treatment for collection methdod: some are pure, other only modify the receiver
|
||||
/// </summary>
|
||||
/// <param name="methodCallStmt"></param>
|
||||
/// <param name="methodInvoked"></param>
|
||||
/// <returns></returns>
|
||||
private bool HandleCollectionMethod(MethodCallInstruction methodCallStmt, IMethodReference methodInvoked)
|
||||
{
|
||||
var pureCollectionMethods = new HashSet<String>() { "Contains", "ContainsKey", "Count", "get_Count", "First"};
|
||||
var pureEnumerationMethods = new HashSet<String>() { "Select", "Where", "Any", "Count", "GroupBy", "Max", "Min", "First" };
|
||||
|
||||
var result = true;
|
||||
// For constructors of collections we create an small summary for the PTA
|
||||
if(methodInvoked.IsConstructor() && methodInvoked.ContainingType.IsCollection())
|
||||
{
|
||||
var arg = methodCallStmt.Arguments[0];
|
||||
this.iteratorDependencyAnalysis.pta.CreateSummaryForCollection(this.State.PTG, methodCallStmt.Offset, arg);
|
||||
|
||||
}
|
||||
}
|
||||
// For GetEnum we need to create an object iterator that points-to the colecction
|
||||
else if (methodInvoked.Name.Value == "GetEnumerator"
|
||||
&& (methodInvoked.ContainingType.IsIEnumerable() || methodInvoked.ContainingType.IsEnumerable()))
|
||||
|
@ -1698,6 +1735,15 @@ namespace Backend.Analyses
|
|||
&& ( methodInvoked.ContainingType.TypeEquals(clousureType) && patterns.Any(pattern => methodInvoked.Name.Value.StartsWith(pattern))
|
||||
|| specialMethods.Any(sm => sm.Item1 == methodInvoked.ContainingType.GetName()
|
||||
&& sm.Item2 == methodInvoked.Name.Value));
|
||||
if (methodInvoked.ResolvedMethod != null && (MemberHelper.IsGetter(methodInvoked.ResolvedMethod) ||
|
||||
MemberHelper.IsSetter(methodInvoked.ResolvedMethod))
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (methodInvoked.Name.Value == "ParseJson")
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1897,7 +1943,7 @@ namespace Backend.Analyses
|
|||
}
|
||||
}
|
||||
|
||||
private void UpdateCall(MethodCallInstruction methodCallStmt)
|
||||
private void UpdateCall(MethodCallInstruction methodCallStmt, bool updatePTG = true)
|
||||
{
|
||||
if (methodCallStmt.IsConstructorCall())
|
||||
{
|
||||
|
@ -1923,7 +1969,10 @@ namespace Backend.Analyses
|
|||
}
|
||||
}
|
||||
traceables.AddRange(GetCallTraceables(methodCallStmt));
|
||||
UpdatePTAForPure(methodCallStmt);
|
||||
if (updatePTG)
|
||||
{
|
||||
UpdatePTAForPure(methodCallStmt);
|
||||
}
|
||||
this.State.AssignTraceables(result, traceables);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -300,6 +300,7 @@ namespace ScopeProgramAnalysis
|
|||
var depAnalysisResultandTime = dependencyAnalysis.AnalyzeMoveNextMethod();
|
||||
depAnalysisResult = depAnalysisResultandTime.Item1;
|
||||
depAnalysisTime = depAnalysisResultandTime.Item2;
|
||||
var analysisReasons = AnalysisStats.AnalysisReasons;
|
||||
|
||||
inputColumns = dependencyAnalysis.InputColumns;
|
||||
outputColumns = dependencyAnalysis.OutputColumns;
|
||||
|
@ -846,11 +847,14 @@ namespace ScopeProgramAnalysis
|
|||
var reducerClassDefinition = entryMethod.ContainingTypeDefinition;
|
||||
|
||||
var isCompilerGenerated = compilerGeneretedMethodMatchers.Any(regex => regex.IsMatch(reducerClassDefinition.FullName()));
|
||||
if (reducerClassDefinition.FullName().Contains(@"ScopeFilterTransformer_17"))
|
||||
{
|
||||
}
|
||||
else
|
||||
if (isCompilerGenerated)
|
||||
continue;
|
||||
|
||||
if (isCompilerGenerated)
|
||||
continue;
|
||||
|
||||
if (processorsToAnalyze.Contains(reducerClassDefinition))
|
||||
if (processorsToAnalyze.Contains(reducerClassDefinition))
|
||||
continue;
|
||||
|
||||
processorsToAnalyze.Add(reducerClassDefinition);
|
||||
|
|
|
@ -8,298 +8,323 @@ using ScopeProgramAnalysis.Framework;
|
|||
|
||||
namespace Backend.Model
|
||||
{
|
||||
public struct NodeField
|
||||
{
|
||||
public SimplePTGNode Node { get; set; }
|
||||
public IFieldReference Field { get; set; }
|
||||
public NodeField(SimplePTGNode source, IFieldReference field)
|
||||
{
|
||||
this.Node = source;
|
||||
this.Field = field;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is NodeField))
|
||||
return false;
|
||||
var oth = (NodeField)obj;
|
||||
return oth.Field.Equals(this.Field) && oth.Node.Equals(this.Node);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Field.GetHashCode() + this.Node.GetHashCode();
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return Node.ToString()+";"+Field.Name.Value;
|
||||
}
|
||||
}
|
||||
public struct NodeField
|
||||
{
|
||||
public SimplePTGNode Node { get; set; }
|
||||
public IFieldReference Field { get; set; }
|
||||
public NodeField(SimplePTGNode source, IFieldReference field)
|
||||
{
|
||||
this.Node = source;
|
||||
this.Field = field;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is NodeField))
|
||||
return false;
|
||||
var oth = (NodeField)obj;
|
||||
return oth.Field.Equals(this.Field) && oth.Node.Equals(this.Node);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Field.GetHashCode() + this.Node.GetHashCode();
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return Node.ToString() + ";" + Field.Name.Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown PTG nodes represent placeholders
|
||||
// (external objects that can be null or
|
||||
// stand for multiple objects).
|
||||
// Useful to model parameter values.
|
||||
public enum SimplePTGNodeKind
|
||||
{
|
||||
Null,
|
||||
Object,
|
||||
Unknown,
|
||||
Parameter,
|
||||
Delegate,
|
||||
Global
|
||||
}
|
||||
// Unknown PTG nodes represent placeholders
|
||||
// (external objects that can be null or
|
||||
// stand for multiple objects).
|
||||
// Useful to model parameter values.
|
||||
public enum SimplePTGNodeKind
|
||||
{
|
||||
Null,
|
||||
Object,
|
||||
Unknown,
|
||||
Parameter,
|
||||
Delegate,
|
||||
Json,
|
||||
Global
|
||||
}
|
||||
|
||||
|
||||
public interface PTGContext
|
||||
{
|
||||
public interface PTGContext
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class MethodContex : PTGContext
|
||||
{
|
||||
public MethodContex(IMethodReference method)
|
||||
{
|
||||
this.Method = method;
|
||||
}
|
||||
public IMethodReference Method { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
if (Method != null)
|
||||
{
|
||||
return Method.Name.ToString();
|
||||
}
|
||||
else return "--";
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as MethodContex;
|
||||
return oth.Method.Equals(Method);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Method.GetHashCode();
|
||||
}
|
||||
}
|
||||
public class MethodContex : PTGContext
|
||||
{
|
||||
public MethodContex(IMethodReference method)
|
||||
{
|
||||
this.Method = method;
|
||||
}
|
||||
public IMethodReference Method { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
if (Method != null)
|
||||
{
|
||||
return Method.Name.ToString();
|
||||
}
|
||||
else return "--";
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as MethodContex;
|
||||
return oth.Method.Equals(Method);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Method.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class GlobalContext : PTGContext
|
||||
{
|
||||
public static GlobalContext NullNodeContext = new GlobalContext();
|
||||
public static GlobalContext GlobalNodeContext = new GlobalContext();
|
||||
}
|
||||
public class GlobalContext : PTGContext
|
||||
{
|
||||
public static GlobalContext NullNodeContext = new GlobalContext();
|
||||
public static GlobalContext GlobalNodeContext = new GlobalContext();
|
||||
}
|
||||
|
||||
public class PTGID
|
||||
{
|
||||
public PTGID(PTGContext context, int offset)
|
||||
{
|
||||
this.Context = context;
|
||||
this.OffSet = offset;
|
||||
}
|
||||
PTGContext Context { get; set; }
|
||||
public int OffSet { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0}:{1:X4}", Context, OffSet);
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var ptgID = obj as PTGID;
|
||||
return ptgID != null && ptgID.OffSet == OffSet
|
||||
&& (ptgID.Context == Context || ptgID.Context.Equals(Context));
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (Context == null) return OffSet.GetHashCode();
|
||||
return Context.GetHashCode() + OffSet.GetHashCode();
|
||||
}
|
||||
}
|
||||
public class PTGID
|
||||
{
|
||||
public PTGID(PTGContext context, int offset)
|
||||
{
|
||||
this.Context = context;
|
||||
this.OffSet = offset;
|
||||
}
|
||||
PTGContext Context { get; set; }
|
||||
public int OffSet { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0}:{1:X4}", Context, OffSet);
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var ptgID = obj as PTGID;
|
||||
return ptgID != null && ptgID.OffSet == OffSet
|
||||
&& (ptgID.Context == Context || ptgID.Context.Equals(Context));
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (Context == null) return OffSet.GetHashCode();
|
||||
return Context.GetHashCode() + OffSet.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class SimplePTGNode
|
||||
{
|
||||
public PTGID Id { get; private set; }
|
||||
public SimplePTGNodeKind Kind { get; private set; }
|
||||
public uint Offset { get; set; }
|
||||
public ITypeReference Type { get; set; }
|
||||
public ISet<IVariable> Variables { get; private set; }
|
||||
public MapSet<IFieldReference, SimplePTGNode> Sources { get; private set; }
|
||||
public MapSet<IFieldReference, SimplePTGNode> Targets { get; private set; }
|
||||
public class SimplePTGNode
|
||||
{
|
||||
public PTGID Id { get; private set; }
|
||||
public SimplePTGNodeKind Kind { get; private set; }
|
||||
public uint Offset { get; set; }
|
||||
public ITypeReference Type { get; set; }
|
||||
public ISet<IVariable> Variables { get; private set; }
|
||||
public MapSet<IFieldReference, SimplePTGNode> Sources { get; private set; }
|
||||
public MapSet<IFieldReference, SimplePTGNode> Targets { get; private set; }
|
||||
|
||||
//public SimplePTGNode(PTGID id, SimplePTGNodeKind kind = SimplePTGNodeKind.Null)
|
||||
// {
|
||||
// this.Id = id;
|
||||
// this.Kind = kind;
|
||||
// this.Variables = new HashSet<IVariable>();
|
||||
// this.Sources = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
// this.Targets = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
// }
|
||||
//public SimplePTGNode(PTGID id, SimplePTGNodeKind kind = SimplePTGNodeKind.Null)
|
||||
// {
|
||||
// this.Id = id;
|
||||
// this.Kind = kind;
|
||||
// this.Variables = new HashSet<IVariable>();
|
||||
// this.Sources = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
// this.Targets = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
// }
|
||||
|
||||
public SimplePTGNode(PTGID id, ITypeReference type, SimplePTGNodeKind kind = SimplePTGNodeKind.Object)
|
||||
// : this(id, kind)
|
||||
{
|
||||
this.Id = id;
|
||||
this.Type = type;
|
||||
this.Kind = kind;
|
||||
this.Variables = new HashSet<IVariable>();
|
||||
this.Sources = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
this.Targets = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
}
|
||||
public SimplePTGNode(PTGID id, ITypeReference type, SimplePTGNodeKind kind = SimplePTGNodeKind.Object)
|
||||
// : this(id, kind)
|
||||
{
|
||||
this.Id = id;
|
||||
this.Type = type;
|
||||
this.Kind = kind;
|
||||
this.Variables = new HashSet<IVariable>();
|
||||
this.Sources = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
this.Targets = new MapSet<IFieldReference, SimplePTGNode>();
|
||||
}
|
||||
|
||||
public bool SameEdges(SimplePTGNode node)
|
||||
{
|
||||
if (node == null) throw new ArgumentNullException("node");
|
||||
public bool SameEdges(SimplePTGNode node)
|
||||
{
|
||||
if (node == null) throw new ArgumentNullException("node");
|
||||
|
||||
return this.Variables.SetEquals(node.Variables) &&
|
||||
this.Sources.MapEquals(node.Sources) &&
|
||||
this.Targets.MapEquals(node.Targets);
|
||||
}
|
||||
return this.Variables.SetEquals(node.Variables) &&
|
||||
this.Sources.MapEquals(node.Sources) &&
|
||||
this.Targets.MapEquals(node.Targets);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (object.ReferenceEquals(this, obj)) return true;
|
||||
var other = obj as SimplePTGNode;
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (object.ReferenceEquals(this, obj)) return true;
|
||||
var other = obj as SimplePTGNode;
|
||||
|
||||
return other != null &&
|
||||
this.Id.Equals(other.Id) &&
|
||||
this.Kind == other.Kind &&
|
||||
//this.Offset == other.Offset &&
|
||||
this.Type.TypeEquals(other.Type);
|
||||
}
|
||||
return other != null &&
|
||||
this.Id.Equals(other.Id) &&
|
||||
this.Kind == other.Kind &&
|
||||
//this.Offset == other.Offset &&
|
||||
this.Type.TypeEquals(other.Type);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
//return this.Id.GetHashCode();
|
||||
return this.Id.GetHashCode() + this.Type.GetHashCode() + this.Kind.GetHashCode();
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
//return this.Id.GetHashCode();
|
||||
return this.Id.GetHashCode() + this.Type.GetHashCode() + this.Kind.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
string result;
|
||||
public override string ToString()
|
||||
{
|
||||
string result;
|
||||
|
||||
switch (this.Kind)
|
||||
{
|
||||
case SimplePTGNodeKind.Null:
|
||||
result = "null";
|
||||
break;
|
||||
switch (this.Kind)
|
||||
{
|
||||
case SimplePTGNodeKind.Null:
|
||||
result = "null";
|
||||
break;
|
||||
|
||||
default:
|
||||
result = string.Format("{0:X$}: {1}", this.Id, this.Type);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
result = string.Format("{0:X$}: {1}", this.Id, this.Type);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
public virtual SimplePTGNode Clone()
|
||||
{
|
||||
var clone = new SimplePTGNode(this.Id, this.Type, this.Kind);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public virtual SimplePTGNode Clone()
|
||||
{
|
||||
var clone = new SimplePTGNode(this.Id, this.Type, this.Kind);
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
public class NullNode : SimplePTGNode
|
||||
{
|
||||
public static PTGID nullID = new PTGID(GlobalContext.NullNodeContext, 0);
|
||||
public class NullNode : SimplePTGNode
|
||||
{
|
||||
public static PTGID nullID = new PTGID(GlobalContext.NullNodeContext, 0);
|
||||
|
||||
public NullNode() : base(nullID, MyLoader.PlatformTypes.SystemObject, SimplePTGNodeKind.Null)
|
||||
{
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as NullNode;
|
||||
return oth != null;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return "Null";
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
public NullNode() : base(nullID, MyLoader.PlatformTypes.SystemObject, SimplePTGNodeKind.Null)
|
||||
{
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as NullNode;
|
||||
return oth != null;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return "Null";
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public class GlobalNode : SimplePTGNode
|
||||
{
|
||||
public static PTGID globalID = new PTGID(GlobalContext.GlobalNodeContext, -1);
|
||||
public class GlobalNode : SimplePTGNode
|
||||
{
|
||||
public static PTGID globalID = new PTGID(GlobalContext.GlobalNodeContext, -1);
|
||||
|
||||
public GlobalNode() : base(globalID, MyLoader.PlatformTypes.SystemObject, SimplePTGNodeKind.Global)
|
||||
{
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as GlobalNode;
|
||||
return oth != null;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return "Global";
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
public GlobalNode() : base(globalID, MyLoader.PlatformTypes.SystemObject, SimplePTGNodeKind.Global)
|
||||
{
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as GlobalNode;
|
||||
return oth != null;
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return "Global";
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class ParameterNode : SimplePTGNode
|
||||
{
|
||||
public string Parameter { get; private set; }
|
||||
public ParameterNode(PTGID id, string parameter, ITypeReference type, SimplePTGNodeKind kind = SimplePTGNodeKind.Null) : base(id, type, SimplePTGNodeKind.Parameter)
|
||||
{
|
||||
this.Parameter = parameter;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as ParameterNode;
|
||||
return oth != null && oth.Parameter.Equals(Parameter) && base.Equals(oth);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Parameter.GetHashCode() + base.GetHashCode();
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
var clone = new ParameterNode(this.Id, this.Parameter, this.Type);
|
||||
return clone;
|
||||
}
|
||||
public class ParameterNode : SimplePTGNode
|
||||
{
|
||||
public string Parameter { get; private set; }
|
||||
public ParameterNode(PTGID id, string parameter, ITypeReference type, SimplePTGNodeKind kind = SimplePTGNodeKind.Null) : base(id, type, SimplePTGNodeKind.Parameter)
|
||||
{
|
||||
this.Parameter = parameter;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as ParameterNode;
|
||||
return oth != null && oth.Parameter.Equals(Parameter) && base.Equals(oth);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Parameter.GetHashCode() + base.GetHashCode();
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
var clone = new ParameterNode(this.Id, this.Parameter, this.Type);
|
||||
return clone;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class DelegateNode : SimplePTGNode
|
||||
{
|
||||
public IMethodReference Method { get; private set; }
|
||||
public IVariable Instance { get; set; }
|
||||
public bool IsStatic { get; private set; }
|
||||
public class DelegateNode : SimplePTGNode
|
||||
{
|
||||
public IMethodReference Method { get; private set; }
|
||||
public IVariable Instance { get; set; }
|
||||
public bool IsStatic { get; private set; }
|
||||
|
||||
public DelegateNode(PTGID id, IMethodReference method, IVariable instance) : base(id, method.Type, SimplePTGNodeKind.Delegate)
|
||||
public DelegateNode(PTGID id, IMethodReference method, IVariable instance) : base(id, method.Type, SimplePTGNodeKind.Delegate)
|
||||
{
|
||||
this.Method = method;
|
||||
this.Instance = instance;
|
||||
this.IsStatic = instance == null;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as DelegateNode;
|
||||
return oth != null && oth.Method.Equals(Method)
|
||||
&& oth.Instance == this.Instance
|
||||
&& base.Equals(oth);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Method.GetHashCode() + (this.IsStatic ? 1 : this.Instance.GetHashCode())
|
||||
+ base.GetHashCode();
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
var node = new DelegateNode(this.Id, this.Method, this.Instance);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
public class JSonNode : SimplePTGNode
|
||||
{
|
||||
public ITypeReference ObjectType { get; private set; }
|
||||
public JSonNode(PTGID id, ITypeReference oType) : base(id, oType, SimplePTGNodeKind.Json)
|
||||
{
|
||||
this.Method = method;
|
||||
this.Instance = instance;
|
||||
this.IsStatic = instance == null;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as DelegateNode;
|
||||
return oth != null && oth.Method.Equals(Method)
|
||||
&& oth.Instance == this.Instance
|
||||
&& base.Equals(oth);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.Method.GetHashCode() + (this.IsStatic ? 1 : this.Instance.GetHashCode())
|
||||
+ base.GetHashCode();
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
var node = new DelegateNode(this.Id, this.Method, this.Instance);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
this.ObjectType = oType;
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var oth = obj as JSonNode;
|
||||
return oth != null && oth.ObjectType.Equals(this.ObjectType)
|
||||
&& base.Equals(oth);
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.ObjectType.GetHashCode()+ base.GetHashCode();
|
||||
}
|
||||
public override SimplePTGNode Clone()
|
||||
{
|
||||
var node = new JSonNode(this.Id, this.ObjectType);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
public class SimplePointsToGraph
|
||||
{
|
||||
|
|
|
@ -17,181 +17,194 @@ namespace Backend.Analyses
|
|||
// May Points-To Analysis
|
||||
public class PointsToAnalysis : ForwardDataFlowAnalysis<SimplePointsToGraph>
|
||||
{
|
||||
public class PTAVisitor : InstructionVisitor
|
||||
{
|
||||
public SimplePointsToGraph State { get; set; }
|
||||
private PointsToAnalysis ptAnalysis;
|
||||
private bool analyzeNextDelegateCtor;
|
||||
public class PTAVisitor : InstructionVisitor
|
||||
{
|
||||
public SimplePointsToGraph State { get; set; }
|
||||
private PointsToAnalysis ptAnalysis;
|
||||
private bool analyzeNextDelegateCtor;
|
||||
|
||||
/// <summary>
|
||||
/// Hack until I add support from addresses
|
||||
/// </summary>
|
||||
private Dictionary<IVariable, IValue> addressMap = new Dictionary<IVariable, IValue>();
|
||||
/// <summary>
|
||||
/// Hack until I add support from addresses
|
||||
/// </summary>
|
||||
private Dictionary<IVariable, IValue> addressMap = new Dictionary<IVariable, IValue>();
|
||||
|
||||
internal PTAVisitor(SimplePointsToGraph ptg, PointsToAnalysis ptAnalysis)
|
||||
{
|
||||
this.State = ptg;
|
||||
this.ptAnalysis = ptAnalysis;
|
||||
this.analyzeNextDelegateCtor = false;
|
||||
}
|
||||
public override void Visit(LoadInstruction instruction)
|
||||
{
|
||||
var load = instruction as LoadInstruction;
|
||||
var operand = load.Operand;
|
||||
internal PTAVisitor(SimplePointsToGraph ptg, PointsToAnalysis ptAnalysis)
|
||||
{
|
||||
this.State = ptg;
|
||||
this.ptAnalysis = ptAnalysis;
|
||||
this.analyzeNextDelegateCtor = false;
|
||||
}
|
||||
public override void Visit(LoadInstruction instruction)
|
||||
{
|
||||
var load = instruction as LoadInstruction;
|
||||
var operand = load.Operand;
|
||||
|
||||
HandleLoadWithOperand(load, operand);
|
||||
HandleLoadWithOperand(load, operand);
|
||||
|
||||
if (operand is Reference)
|
||||
{
|
||||
var referencedValue = (operand as Reference).Value;
|
||||
var isHandled = HandleLoadWithOperand(load, referencedValue);
|
||||
if(!(referencedValue is IVariable))
|
||||
{ }
|
||||
addressMap[instruction.Result] = referencedValue;
|
||||
}
|
||||
else if (operand is Dereference)
|
||||
{
|
||||
var reference = (operand as Dereference).Reference;
|
||||
var isHandled = HandleLoadWithOperand(load, reference);
|
||||
}
|
||||
if (operand is Reference)
|
||||
{
|
||||
var referencedValue = (operand as Reference).Value;
|
||||
var isHandled = HandleLoadWithOperand(load, referencedValue);
|
||||
if (!(referencedValue is IVariable))
|
||||
{ }
|
||||
addressMap[instruction.Result] = referencedValue;
|
||||
}
|
||||
else if (operand is Dereference)
|
||||
{
|
||||
var reference = (operand as Dereference).Reference;
|
||||
var isHandled = HandleLoadWithOperand(load, reference);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private bool HandleLoadWithOperand(LoadInstruction load, IValue operand)
|
||||
{
|
||||
var result = true;
|
||||
if (operand is Constant)
|
||||
{
|
||||
var constant = operand as Constant;
|
||||
private bool HandleLoadWithOperand(LoadInstruction load, IValue operand)
|
||||
{
|
||||
var result = true;
|
||||
if (operand is Constant)
|
||||
{
|
||||
var constant = operand as Constant;
|
||||
|
||||
if (constant.Value == null)
|
||||
{
|
||||
ptAnalysis.ProcessNull(State, load.Result);
|
||||
}
|
||||
}
|
||||
if (operand is IVariable)
|
||||
{
|
||||
var variable = operand as IVariable;
|
||||
ptAnalysis.ProcessCopy(State, load.Result, variable);
|
||||
}
|
||||
else if (operand is InstanceFieldAccess)
|
||||
{
|
||||
var access = operand as InstanceFieldAccess;
|
||||
ptAnalysis.ProcessLoad(State, load.Offset, load.Result, access.Instance, access.Field);
|
||||
}
|
||||
else if(operand is StaticFieldAccess)
|
||||
{
|
||||
var access = operand as StaticFieldAccess;
|
||||
ptAnalysis.ProcessLoad(State, load.Offset, load.Result, PointsToAnalysis.GlobalVariable, access.Field);
|
||||
if (constant.Value == null)
|
||||
{
|
||||
ptAnalysis.ProcessNull(State, load.Result);
|
||||
}
|
||||
}
|
||||
if (operand is IVariable)
|
||||
{
|
||||
var variable = operand as IVariable;
|
||||
ptAnalysis.ProcessCopy(State, load.Result, variable);
|
||||
}
|
||||
else if (operand is InstanceFieldAccess)
|
||||
{
|
||||
var access = operand as InstanceFieldAccess;
|
||||
ptAnalysis.ProcessLoad(State, load.Offset, load.Result, access.Instance, access.Field);
|
||||
}
|
||||
else if (operand is StaticFieldAccess)
|
||||
{
|
||||
var access = operand as StaticFieldAccess;
|
||||
ptAnalysis.ProcessLoad(State, load.Offset, load.Result, PointsToAnalysis.GlobalVariable, access.Field);
|
||||
|
||||
}
|
||||
else if(operand is ArrayElementAccess)
|
||||
{
|
||||
var arrayAccess = operand as ArrayElementAccess;
|
||||
var baseArray = arrayAccess.Array;
|
||||
ptAnalysis.ProcessLoad(State, load.Offset, load.Result, baseArray, new FieldReference("[]", operand.Type, this.ptAnalysis.method.ContainingType));
|
||||
}
|
||||
else if (operand is VirtualMethodReference)
|
||||
{
|
||||
var loadDelegateStmt = operand as VirtualMethodReference;
|
||||
var methodRef = loadDelegateStmt.Method;
|
||||
var instance = loadDelegateStmt.Instance;
|
||||
ptAnalysis.ProcessDelegateAddr(State, load.Offset, load.Result, methodRef, instance);
|
||||
}
|
||||
else if (operand is ArrayElementAccess)
|
||||
{
|
||||
var arrayAccess = operand as ArrayElementAccess;
|
||||
var baseArray = arrayAccess.Array;
|
||||
ptAnalysis.ProcessLoad(State, load.Offset, load.Result, baseArray, new FieldReference("[]", operand.Type, this.ptAnalysis.method.ContainingType));
|
||||
}
|
||||
else if (operand is VirtualMethodReference)
|
||||
{
|
||||
var loadDelegateStmt = operand as VirtualMethodReference;
|
||||
var methodRef = loadDelegateStmt.Method;
|
||||
var instance = loadDelegateStmt.Instance;
|
||||
ptAnalysis.ProcessDelegateAddr(State, load.Offset, load.Result, methodRef, instance);
|
||||
|
||||
}
|
||||
else if (operand is StaticMethodReference)
|
||||
{
|
||||
var loadDelegateStmt = operand as StaticMethodReference;
|
||||
var methodRef = loadDelegateStmt.Method;
|
||||
ptAnalysis.ProcessDelegateAddr(State, load.Offset, load.Result, methodRef, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else if (operand is StaticMethodReference)
|
||||
{
|
||||
var loadDelegateStmt = operand as StaticMethodReference;
|
||||
var methodRef = loadDelegateStmt.Method;
|
||||
ptAnalysis.ProcessDelegateAddr(State, load.Offset, load.Result, methodRef, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public override void Visit(StoreInstruction instruction)
|
||||
{
|
||||
var store = instruction;
|
||||
var lhs= store.Result;
|
||||
if (lhs is InstanceFieldAccess)
|
||||
{
|
||||
var access = lhs as InstanceFieldAccess;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, access.Instance, access.Field, store.Operand);
|
||||
}
|
||||
else if(lhs is StaticFieldAccess)
|
||||
{
|
||||
var access = lhs as StaticFieldAccess;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, PointsToAnalysis.GlobalVariable, access.Field, store.Operand);
|
||||
}
|
||||
else if (lhs is ArrayElementAccess)
|
||||
{
|
||||
var arrayAccess = lhs as ArrayElementAccess;
|
||||
var baseArray = arrayAccess.Array;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, baseArray, new FieldReference("[]", lhs.Type, this.ptAnalysis.method.ContainingType), store.Operand);
|
||||
}
|
||||
public override void Visit(StoreInstruction instruction)
|
||||
{
|
||||
var store = instruction;
|
||||
var lhs = store.Result;
|
||||
if (lhs is InstanceFieldAccess)
|
||||
{
|
||||
var access = lhs as InstanceFieldAccess;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, access.Instance, access.Field, store.Operand);
|
||||
}
|
||||
else if (lhs is StaticFieldAccess)
|
||||
{
|
||||
var access = lhs as StaticFieldAccess;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, PointsToAnalysis.GlobalVariable, access.Field, store.Operand);
|
||||
}
|
||||
else if (lhs is ArrayElementAccess)
|
||||
{
|
||||
var arrayAccess = lhs as ArrayElementAccess;
|
||||
var baseArray = arrayAccess.Array;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, baseArray, new FieldReference("[]", lhs.Type, this.ptAnalysis.method.ContainingType), store.Operand);
|
||||
}
|
||||
|
||||
}
|
||||
public override void Visit(CreateObjectInstruction instruction)
|
||||
{
|
||||
if (instruction is CreateObjectInstruction)
|
||||
{
|
||||
var allocation = instruction as CreateObjectInstruction;
|
||||
// hack for handling delegates
|
||||
if (allocation.AllocationType.ResolvedType.IsDelegate)
|
||||
{
|
||||
this.analyzeNextDelegateCtor = true;
|
||||
}
|
||||
// TODO: Check if we can avoid adding the node in case of delegate (it was already added in load address for method)
|
||||
ptAnalysis.ProcessObjectAllocation(State, allocation.Offset, allocation.Result);
|
||||
}
|
||||
}
|
||||
public override void Visit(CreateArrayInstruction instruction)
|
||||
{
|
||||
var allocation = instruction;
|
||||
ptAnalysis.ProcessArrayAllocation(State, allocation.Offset, allocation.Result);
|
||||
}
|
||||
public override void Visit(InitializeMemoryInstruction instruction)
|
||||
{
|
||||
var addr = instruction.TargetAddress;
|
||||
//ptAnalysis.ProcessArrayAllocation(State, allocation.Offset, allocation.Result);
|
||||
}
|
||||
public override void Visit(InitializeObjectInstruction instruction)
|
||||
{
|
||||
var addr = instruction.TargetAddress;
|
||||
ptAnalysis.ProcessObjectAllocation(State, instruction.Offset, addr);
|
||||
if(addressMap.ContainsKey(addr))
|
||||
{
|
||||
var value = addressMap[addr];
|
||||
if (value is IVariable)
|
||||
{
|
||||
ptAnalysis.ProcessCopy(State, value as IVariable, addr);
|
||||
}
|
||||
if(value is InstanceFieldAccess)
|
||||
{
|
||||
var fieldAccess = value as InstanceFieldAccess;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, fieldAccess.Instance, fieldAccess.Field , addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Visit(ConvertInstruction instruction)
|
||||
{
|
||||
ptAnalysis.ProcessCopy(State, instruction.Result, instruction.Operand);
|
||||
}
|
||||
public override void Visit(MethodCallInstruction instruction)
|
||||
{
|
||||
var methodCall = instruction as MethodCallInstruction;
|
||||
// Hack for mapping delegates to nodes
|
||||
if (methodCall.Method.Name.Value == ".ctor" && this.analyzeNextDelegateCtor)
|
||||
{
|
||||
ProcessDelegateCtor(methodCall);
|
||||
this.analyzeNextDelegateCtor = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Visit(CreateObjectInstruction instruction)
|
||||
{
|
||||
if (instruction is CreateObjectInstruction)
|
||||
{
|
||||
var allocation = instruction as CreateObjectInstruction;
|
||||
// hack for handling delegates
|
||||
if (allocation.AllocationType.ResolvedType.IsDelegate)
|
||||
{
|
||||
this.analyzeNextDelegateCtor = true;
|
||||
}
|
||||
// TODO: Check if we can avoid adding the node in case of delegate (it was already added in load address for method)
|
||||
ptAnalysis.ProcessObjectAllocation(State, allocation.Offset, allocation.Result);
|
||||
}
|
||||
}
|
||||
public override void Visit(CreateArrayInstruction instruction)
|
||||
{
|
||||
var allocation = instruction;
|
||||
ptAnalysis.ProcessArrayAllocation(State, allocation.Offset, allocation.Result);
|
||||
}
|
||||
public override void Visit(InitializeMemoryInstruction instruction)
|
||||
{
|
||||
var addr = instruction.TargetAddress;
|
||||
//ptAnalysis.ProcessArrayAllocation(State, allocation.Offset, allocation.Result);
|
||||
}
|
||||
public override void Visit(InitializeObjectInstruction instruction)
|
||||
{
|
||||
var addr = instruction.TargetAddress;
|
||||
ptAnalysis.ProcessObjectAllocation(State, instruction.Offset, addr);
|
||||
if (addressMap.ContainsKey(addr))
|
||||
{
|
||||
var value = addressMap[addr];
|
||||
if (value is IVariable)
|
||||
{
|
||||
ptAnalysis.ProcessCopy(State, value as IVariable, addr);
|
||||
}
|
||||
if (value is InstanceFieldAccess)
|
||||
{
|
||||
var fieldAccess = value as InstanceFieldAccess;
|
||||
ptAnalysis.ProcessStore(State, instruction.Offset, fieldAccess.Instance, fieldAccess.Field, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
public override void Visit(ConvertInstruction instruction)
|
||||
{
|
||||
ptAnalysis.ProcessCopy(State, instruction.Result, instruction.Operand);
|
||||
}
|
||||
public override void Visit(MethodCallInstruction instruction)
|
||||
{
|
||||
var methodCall = instruction as MethodCallInstruction;
|
||||
// Hack for mapping delegates to nodes
|
||||
if (methodCall.Method.Name.Value == ".ctor" && this.analyzeNextDelegateCtor)
|
||||
{
|
||||
ProcessDelegateCtor(methodCall);
|
||||
this.analyzeNextDelegateCtor = false;
|
||||
}
|
||||
if (methodCall.Method.ContainingType.GetName().Contains("JsonConvert"))
|
||||
{
|
||||
ProcessJsonCall(methodCall);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessDelegateCtor(MethodCallInstruction methodCall)
|
||||
private void ProcessJsonCall(MethodCallInstruction methodCall)
|
||||
{
|
||||
if (methodCall.Method.Name.Value == "DeserializeObject")
|
||||
{
|
||||
ptAnalysis.ProcessJSonAlloc(State, methodCall.Offset, methodCall.Result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void ProcessDelegateCtor(MethodCallInstruction methodCall)
|
||||
{
|
||||
if (methodCall.Arguments.Any())
|
||||
{
|
||||
|
@ -432,7 +445,19 @@ namespace Backend.Analyses
|
|||
ptg.PointsTo(dst, node);
|
||||
}
|
||||
|
||||
internal void ProcessCopy(SimplePointsToGraph ptg, IVariable dst, IEnumerable<IVariable> srcs)
|
||||
private void ProcessJSonAlloc(SimplePointsToGraph ptg, uint offset, IVariable dst)
|
||||
{
|
||||
ptg.RemoveRootEdges(dst);
|
||||
if (!dst.Type.IsClassOrStruct()) return;
|
||||
var ptgId = new PTGID(new MethodContex(this.method), (int)offset);
|
||||
|
||||
var node = new JSonNode(ptgId, dst.Type);
|
||||
|
||||
ptg.PointsTo(dst, node);
|
||||
}
|
||||
|
||||
|
||||
internal void ProcessCopy(SimplePointsToGraph ptg, IVariable dst, IEnumerable<IVariable> srcs)
|
||||
{
|
||||
ptg.RemoveRootEdges(dst);
|
||||
|
||||
|
@ -502,7 +527,8 @@ namespace Backend.Analyses
|
|||
}
|
||||
}
|
||||
|
||||
public SimplePTGNode CreateSummaryForCollection(SimplePointsToGraph ptg, uint offset, IVariable collectionVariable)
|
||||
#region Methods that provides summaries for handling collections
|
||||
public SimplePTGNode CreateSummaryForCollection(SimplePointsToGraph ptg, uint offset, IVariable collectionVariable)
|
||||
{
|
||||
var ptgId = new PTGID(new MethodContex(this.method), (int)offset);
|
||||
var collectionNode = this.NewNode(ptg, ptgId, collectionVariable.Type);
|
||||
|
@ -581,9 +607,10 @@ namespace Backend.Analyses
|
|||
ptg.PointsTo(result, targets);
|
||||
return targets;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
private bool MayReacheableFromParameter(SimplePointsToGraph ptg, SimplePTGNode n)
|
||||
private bool MayReacheableFromParameter(SimplePointsToGraph ptg, SimplePTGNode n)
|
||||
{
|
||||
var body = MethodBodyProvider.Instance.GetBody(method);
|
||||
var rootNodes = body.Parameters.SelectMany(p => ptg.GetTargets(p)).Union(new HashSet<SimplePTGNode>() { SimplePointsToGraph.GlobalNode });
|
||||
|
|
|
@ -149,6 +149,10 @@ namespace ScopeProgramAnalysis
|
|||
|
||||
input = @"C:\Temp\Scope\InterestingScopeProjects\0ce5ea59-dec8-4f6f-be08-0e0746e12515\__ScopeCodeGen__.dll";
|
||||
input = @"C:\Temp\Scope\NewtonSoftMethodSurvey_E18FC06FBAF9E44\__ScopeCodeGen__.dll";
|
||||
|
||||
input = @"C:\Temp\Scope\JsonSurvey\0195e2b3-3fb3-4f36-bc10-cadbfd76c8cd\__ScopeCodeGen__.dll";
|
||||
input = @"C:\Temp\Scope\JsonSurvey\SimpleJsonProcessors\bin\Debug\6BEA71AFD72D97FF\UDO1_C79877185261167E\__ScopeCodeGen__.dll";
|
||||
|
||||
string[] directories = Path.GetDirectoryName(input).Split(Path.DirectorySeparatorChar);
|
||||
var outputPath = Path.Combine(@"c:\Temp\", directories.Last()) + "_" + Path.ChangeExtension(Path.GetFileName(input), ".sarif");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче