private static void outputNumericalValueOutput(ControlFlowGraph graph, SyntaxNode node, HashSet <SyntaxNode> history, StringBuilder builder) { if (!history.Contains(node)) { history.Add(node); builder.AppendFormat(" {{ \"key\": \"{0}\",\n \"value\": ", location(node)); if (node is LocalDeclarationStatementSyntax || node is VariableDeclarationSyntax) { VariableDeclarationSyntax s; if (node is LocalDeclarationStatementSyntax) { s = (node as LocalDeclarationStatementSyntax).Declaration; } else { s = node as VariableDeclarationSyntax; } builder.Append("{ \"type\": \"variable_declaration\", \"declarations\": ["); bool firstVar = true; foreach (var v in s.Variables) { if (firstVar) { firstVar = false; } else { builder.Append(","); } builder.AppendFormat(" {{ \"identifier\": \"{0}\", \"initializer\": ", v.Identifier); if (v.Initializer == null) { builder.Append("null"); } else { outputNumericalValueOutput(v.Initializer.Value, builder); } builder.Append(" }"); } builder.Append(" ] }"); } else if (node is AssignmentExpressionSyntax || (node is ExpressionStatementSyntax && (node as ExpressionStatementSyntax).Expression is AssignmentExpressionSyntax)) { AssignmentExpressionSyntax s; if (node is AssignmentExpressionSyntax) { s = node as AssignmentExpressionSyntax; } else { s = (node as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax; } builder.AppendFormat("{{ \"type\": \"variable_assignment\", \"left\": \"{0}\", \"right\": ", s.Left); outputNumericalValueOutput(s.Right, builder); builder.Append(" }"); } else if (node is BinaryExpressionSyntax) { builder.Append("{ \"type\": \"comparison\", \"left\": "); var s = node as BinaryExpressionSyntax; outputNumericalValueOutput(s.Left, builder); builder.AppendFormat(", \"op\": \"{0}\", \"right\": ", s.OperatorToken); outputNumericalValueOutput(s.Right, builder); builder.Append(" }"); } else { builder.Append("{ \"type\": \"other\" }"); } builder.Append(",\n \"successors\": ["); bool firstSucc = true; foreach (var succ in graph.GetSuccessorsB(node)) { if (firstSucc) { firstSucc = false; } else { builder.Append(", "); } builder.AppendFormat("{{ \"key\": \"{0}\", \"value\": {1} }}", location(succ.Key), succ.Value); } builder.Append("] }"); foreach (var succ in graph.GetSuccessors(node)) { if (!history.Contains(succ)) { builder.Append(",\n"); } outputNumericalValueOutput(graph, succ, history, builder); } } }
private void analyze(ControlFlowGraph graph, SyntaxNode node, Dictionary <string, NumericalValue <int> > variables, Dictionary <SyntaxNode, Dictionary <string, NumericalValue <int> > > history) { #region Union usagesAfter with reachingDefinitions if (history.ContainsKey(node)) { bool anyChanged = false; foreach (var pair in history[node]) { if (variables.ContainsKey(pair.Key)) { var i = variables[pair.Key]; string old = i.ToString(); //Console.WriteLine("{0} vs {1} and {2}", old, i, pair.Value); i.UnionWith(pair.Value); if (!old.Equals(i.ToString())) { anyChanged = true; } } else { variables.Add(pair.Key, pair.Value.Clone()); anyChanged = true; } } if (history[node].Count == 0 && variables.Count != 0) { anyChanged = true; } if (!anyChanged) { return; } else { var clone = new Dictionary <string, NumericalValue <int> >(); foreach (var v in variables) { clone.Add(v.Key, v.Value.Clone()); } history[node] = clone; } } else { var clone = new Dictionary <string, NumericalValue <int> >(); foreach (var v in variables) { clone.Add(v.Key, v.Value.Clone()); } history.Add(node, clone); } #endregion NumericalValue <int> rangeTrue = null; NumericalValue <int> rangeFalse = null; string rangeVar = null; #region Process node if (node is LocalDeclarationStatementSyntax || node is VariableDeclarationSyntax) { VariableDeclarationSyntax s; if (node is LocalDeclarationStatementSyntax) { s = (node as LocalDeclarationStatementSyntax).Declaration; } else { s = node as VariableDeclarationSyntax; } foreach (var v in s.Variables) { if (v.Initializer != null) { if (v.Initializer.Value is LiteralExpressionSyntax) { var valS = (v.Initializer.Value as LiteralExpressionSyntax).Token.ValueText; int valI; if (int.TryParse(valS, out valI)) { var valNV = new NumericalValue <int>(valI); if (variables.ContainsKey(v.Identifier.ToString())) { variables[v.Identifier.ToString()].AssignValue(valNV); } else { variables.Add(v.Identifier.ToString(), valNV); } } } else if (v.Initializer.Value is IdentifierNameSyntax) { var valNV = variables[v.Initializer.Value.ToString()]; if (variables.ContainsKey(v.Identifier.ToString())) { variables[v.Identifier.ToString()].AssignValue(valNV); } else { variables.Add(v.Identifier.ToString(), valNV); } } else { var valNV = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE); if (variables.ContainsKey(v.Identifier.ToString())) { variables[v.Identifier.ToString()].AssignValue(valNV); } else { variables.Add(v.Identifier.ToString(), valNV); } } } } } else if (node is ExpressionStatementSyntax && (node as ExpressionStatementSyntax).Expression is AssignmentExpressionSyntax) { var s = (node as ExpressionStatementSyntax).Expression as AssignmentExpressionSyntax; if (s.Right is LiteralExpressionSyntax) { var valS = (s.Right as LiteralExpressionSyntax).Token.ValueText; int valI; if (int.TryParse(valS, out valI)) { var valNV = new NumericalValue <int>(valI); if (variables.ContainsKey(s.Left.ToString())) { variables[s.Left.ToString()].AssignValue(valNV); } else { variables.Add(s.Left.ToString(), valNV); } } } else if (s.Right is IdentifierNameSyntax) { var valNV = variables[s.Right.ToString()]; if (variables.ContainsKey(s.Left.ToString())) { variables[s.Left.ToString()].AssignValue(valNV); } else { variables.Add(s.Left.ToString(), valNV); } } else { var valNV = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE); if (variables.ContainsKey(s.Left.ToString())) { variables[s.Left.ToString()].AssignValue(valNV); } else { variables.Add(s.Left.ToString(), valNV); } } } else if (node is BinaryExpressionSyntax) { var n = node as BinaryExpressionSyntax; if (n.Right is LiteralExpressionSyntax) { int value; if (int.TryParse((n.Right as LiteralExpressionSyntax).Token.ValueText, out value)) { if (n.OperatorToken.ToString().Equals("<")) { rangeTrue = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.EXCLUSIVE); rangeFalse = new NumericalValue <int>(value, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE); rangeVar = n.Left.ToString(); } if (n.OperatorToken.ToString().Equals("<=")) { rangeTrue = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.INCLUSIVE); rangeFalse = new NumericalValue <int>(value, Inclusivity.EXCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE); rangeVar = n.Left.ToString(); } if (n.OperatorToken.ToString().Equals(">")) { rangeTrue = new NumericalValue <int>(value, Inclusivity.EXCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE); rangeFalse = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.INCLUSIVE); rangeVar = n.Left.ToString(); } if (n.OperatorToken.ToString().Equals(">=")) { rangeTrue = new NumericalValue <int>(value, Inclusivity.INCLUSIVE, int.MaxValue, Inclusivity.INCLUSIVE); rangeFalse = new NumericalValue <int>(int.MinValue, Inclusivity.INCLUSIVE, value, Inclusivity.EXCLUSIVE); rangeVar = n.Left.ToString(); } } } } if (debug) { Console.WriteLine("({0}): {1} {2}", node.GetLocation().GetLineSpan().StartLinePosition, node, node.GetType()); foreach (var pair in variables) { Console.WriteLine(" {0} -> {1}", pair.Key, pair.Value); } } #endregion #region Recurse foreach (var succ in graph.GetSuccessorsB(node)) { var variablesPrime = new Dictionary <string, NumericalValue <int> >(); foreach (var v in variables) { variablesPrime.Add(v.Key, v.Value.Clone()); } if (succ.Value == 0) { variablesPrime[rangeVar].IntersectWith(rangeFalse); } else if (succ.Value == 1) { variablesPrime[rangeVar].IntersectWith(rangeTrue); } analyze(graph, succ.Key, variablesPrime, history); } #endregion }
static void Main(string[] args) { /*{ * var n = new NumericalValue<int>(); * n.UnionWith(new NumericalValue<int>(0, Inclusivity.INCLUSIVE, 3, Inclusivity.INCLUSIVE)); * AssertEquals(n.ToString(), "[0, 3]"); * n.UnionWith(new NumericalValue<int>(0, Inclusivity.INCLUSIVE, 3, Inclusivity.INCLUSIVE)); * AssertEquals(n.ToString(), "[0, 3]"); * n.UnionWith(new NumericalValue<int>(1, Inclusivity.INCLUSIVE, 4, Inclusivity.EXCLUSIVE)); * AssertEquals(n.ToString(), "[0, 4)"); * n.UnionWith(new NumericalValue<int>(7, Inclusivity.INCLUSIVE, 10, Inclusivity.INCLUSIVE)); * AssertEquals(n.ToString(), "[0, 4) U [7, 10]"); * n.UnionWith(new NumericalValue<int>(6, Inclusivity.INCLUSIVE, 7, Inclusivity.EXCLUSIVE)); * AssertEquals(n.ToString(), "[0, 4) U [6, 10]"); * n.UnionWith(new NumericalValue<int>(3, Inclusivity.INCLUSIVE, 7, Inclusivity.EXCLUSIVE)); * AssertEquals(n.ToString(), "[0, 10]"); * } * { * var n = new NumericalValue<int>(); * n.UnionWith(new NumericalValue<int>(0, Inclusivity.INCLUSIVE, 4, Inclusivity.EXCLUSIVE)); * n.UnionWith(new NumericalValue<int>(6, Inclusivity.INCLUSIVE, 10, Inclusivity.INCLUSIVE)); * n.UnionWith(new NumericalValue<int>(-2, Inclusivity.INCLUSIVE, -2, Inclusivity.INCLUSIVE)); * n.UnionWith(new NumericalValue<int>(14, Inclusivity.EXCLUSIVE, 15, Inclusivity.EXCLUSIVE)); * AssertEquals(n.ToString(), "[-2, -2] U [0, 4) U [6, 10] U (14, 15)"); * n.IntersectWith(3, Inclusivity.INCLUSIVE, 6, Inclusivity.INCLUSIVE); * AssertEquals(n.ToString(), "[3, 4) U [6, 6]"); * }*/ SyntaxTree tree = CSharpSyntaxTree.ParseText( @"using System; using System.Collections; using System.Linq; using System.Text; namespace HelloWorld { class ProgramUnderTest { static void Main(string[] args) {} int f() { return 4; } private void Test() { int j = 3; for (int i = 0; i < 10; i = i + 1) { if (i > j) { j = i + 1; } } return; /* int i = 0; i = 3; int j = f(); if (j + 3 > 5) { i = j; } else { i = -1; } return;*/ } } }"); var diagnostics = new List <NumericValueDiagnostic>(); var compilation = CompileCode(tree); var model = compilation.GetSemanticModel(tree); foreach (var c in tree.GetRoot().DescendantNodes().OfType <ClassDeclarationSyntax>()) { foreach (var m in c.DescendantNodes().OfType <MethodDeclarationSyntax>()) { if (m.Identifier.ToString().Equals("Test")) { ControlFlowGraph controlFlowGraph = new ControlFlowGraph(m, model); Console.WriteLine("digraph {0} {{", "Test"); HashSet <SyntaxNode> visitedNodes = new HashSet <SyntaxNode>(); printGraphViz(controlFlowGraph, controlFlowGraph.GetEntryPoint(), visitedNodes); Console.WriteLine(); foreach (var node in visitedNodes) { if (node.GetLocation().ToString().Contains("[0..7)")) { Console.WriteLine("\"{0}\" [color=\"#55AAFF\"];", node.GetLocation().ToString()); } Console.WriteLine("\"{0}\" [label=\"{1}\"];", node.GetLocation().ToString(), interpolateLabel(node.ToFullString())); } Console.WriteLine("}"); Console.Write("\n\n\n"); /*NumericalValueAnalysis numericalValueAnalysis = new NumericalValueAnalysis(controlFlowGraph);*/ StringBuilder builder = new StringBuilder(); builder.Append("{ \"nodes\": [\n"); outputNumericalValueOutput(controlFlowGraph, controlFlowGraph.GetEntryPoint(), new HashSet <SyntaxNode>(), builder); builder.Append("\n] }"); Console.WriteLine("Builder: '\n{0}\n'", builder); System.IO.File.WriteAllText("input_code.json", builder.ToString()); var process = new System.Diagnostics.Process(); process.StartInfo.FileName = "numerical_value.exe"; process.StartInfo.Arguments = "input_code.json diagnostics.json"; process.StartInfo.CreateNoWindow = true; process.Start(); process.WaitForExit(); diagnostics.AddRange(Newtonsoft.Json.JsonConvert.DeserializeObject <List <NumericValueDiagnostic> >(System.IO.File.ReadAllText("diagnostics.json"))); foreach (var diagnostic in diagnostics) { Console.WriteLine("{0}: This is always {1}", diagnostic.location, diagnostic.always_true); } } } } Console.WriteLine(); Console.Write("Press enter to continue..."); Console.ReadLine(); }
public NumericalValueAnalysis(ControlFlowGraph graph) { analyze(graph, graph.GetEntryPoint(), new Dictionary <string, NumericalValue <int> >(), new Dictionary <SyntaxNode, Dictionary <string, NumericalValue <int> > >()); }