Preliminary (and rough) support for JsonObjects with hard coded functions

Minor touches (should be cleaned) to allow debugging.
This commit is contained in:
Diego 2018-01-26 19:18:50 -08:00
Родитель 0d9c161526
Коммит a9ffd74121
7 изменённых файлов: 598 добавлений и 489 удалений

Просмотреть файл

@ -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");