Example #1
0
        private static void WriteResultToSarifLog(string inputPath, StreamWriter outputStream, SarifLog log, MethodDefinition moveNextMethod, DependencyPTGDomain depAnalysisResult,
                                                  SongTaoDependencyAnalysis dependencyAnalysis, IDictionary <string, ClassDefinition> processorMap)
        {
            var results = new List <Result>();

            var escapes = depAnalysisResult.Dependencies.A1_Escaping.Select(traceable => traceable.ToString());

            var inputUses      = new HashSet <Traceable>();
            var outputModifies = new HashSet <Traceable>();

            if (!depAnalysisResult.IsTop)
            {
                if (depAnalysisResult.Dependencies.A4_Ouput.Any())
                {
                    var outColumnMap        = new MapSet <TraceableColumn, Traceable>();
                    var outColumnControlMap = new MapSet <TraceableColumn, Traceable>();
                    foreach (var outColum in depAnalysisResult.Dependencies.A4_Ouput.Keys)
                    {
                        var outColumns = depAnalysisResult.GetTraceables(outColum).OfType <TraceableColumn>()
                                         .Where(t => t.TableKind == ProtectedRowKind.Output);
                        foreach (var column in outColumns)
                        {
                            if (!outColumnMap.ContainsKey(column))
                            {
                                outColumnMap.AddRange(column, depAnalysisResult.Dependencies.A4_Ouput[outColum]);
                            }
                            else
                            {
                                outColumnMap.AddRange(column, outColumnMap[column].Union(depAnalysisResult.Dependencies.A4_Ouput[outColum]));
                            }
                            if (!outColumnControlMap.ContainsKey(column))
                            {
                                outColumnControlMap.AddRange(column, depAnalysisResult.Dependencies.A4_Ouput_Control[outColum]);
                            }
                            else
                            {
                                outColumnControlMap.AddRange(column, outColumnControlMap[column].Union(depAnalysisResult.Dependencies.A4_Ouput_Control[outColum]));
                            }
                        }
                    }

                    foreach (var entryOutput in outColumnMap)
                    {
                        var result = new Result();
                        result.Id = "SingleColumn";
                        var column         = entryOutput.Key;
                        var columnString   = column.ToString();
                        var dependsOn      = entryOutput.Value;
                        var controlDepends = new HashSet <Traceable>();

                        result.SetProperty("column", columnString);
                        result.SetProperty("data depends", dependsOn.Select(traceable => traceable.ToString()));

                        if (outColumnControlMap.ContainsKey(column))
                        {
                            var controlDependsOn = outColumnControlMap[column];
                            result.SetProperty("control depends", controlDependsOn.Select(traceable => traceable.ToString()));
                        }
                        else
                        {
                            result.SetProperty("control depends", new string[] { });
                        }
                        result.SetProperty("escapes", escapes);
                        results.Add(result);

                        inputUses.AddRange(dependsOn.Where(t => t.TableKind == ProtectedRowKind.Input));
                        outputModifies.Add(column);
                    }


                    //foreach (var outColum in depAnalysisResult.Dependencies.A4_Ouput.Keys)
                    //{
                    //    //var outColumns = depAnalysisResult.Dependencies.A2_Variables[outColum].OfType<TraceableColumn>()
                    //    //                                            .Where(t => t.TableKind == ProtectedRowKind.Output);
                    //    var outColumns = depAnalysisResult.GetTraceables(outColum).OfType<TraceableColumn>()
                    //                                                .Where(t => t.TableKind == ProtectedRowKind.Output);

                    //    foreach (var column in outColumns)
                    //    {
                    //        var result = new Result();
                    //        result.Id = "SingleColumn";
                    //        var columnString = column.ToString();
                    //        var dependsOn = depAnalysisResult.Dependencies.A4_Ouput[outColum];

                    //        //dependsOn.AddRange(traceables);
                    //        result.SetProperty("column", columnString);
                    //        result.SetProperty("data depends", dependsOn.Select(traceable => traceable.ToString()));
                    //        if (depAnalysisResult.Dependencies.A4_Ouput_Control.ContainsKey(outColum))
                    //        {
                    //            var controlDependsOn = depAnalysisResult.Dependencies.A4_Ouput_Control[outColum];
                    //            result.SetProperty("control depends", controlDependsOn.Where(t => !(t is Other)).Select(traceable => traceable.ToString()));
                    //            inputUses.AddRange(controlDependsOn.Where(t => t.TableKind == ProtectedRowKind.Input));
                    //        }
                    //        else
                    //        {
                    //            result.SetProperty("control depends", new string[] { });
                    //        }
                    //        result.SetProperty("escapes", escapes);
                    //        results.Add(result);

                    //        inputUses.AddRange(dependsOn.Where(t => t.TableKind == ProtectedRowKind.Input));
                    //        outputModifies.Add(column);
                    //    }
                    //}
                }
                else
                {
                    var result = new Result();
                    result.Id = "SingleColumn";
                    result.SetProperty("column", "_EMPTY_");
                    result.SetProperty("escapes", escapes);
                    results.Add(result);
                }
                var resultSummary = new Result();
                resultSummary.Id = "Summary";

                //var inputsString = inputUses.OfType<TraceableColumn>().Select(t => t.ToString());
                //var outputsString = outputModifies.OfType<TraceableColumn>().Select(t => t.ToString());
                //result2.SetProperty("Inputs", inputsString);
                //result2.SetProperty("Outputs", outputsString);

                var inputsString  = dependencyAnalysis.InputColumns.Select(t => t.ToString());
                var outputsString = dependencyAnalysis.OutputColumns.Select(t => t.ToString());
                resultSummary.SetProperty("Inputs", inputsString);
                resultSummary.SetProperty("Outputs", outputsString);

                var inputSchemaString  = InputSchema.Columns.Select(t => t.ToString());
                var outputSchemaString = OutputSchema.Columns.Select(t => t.ToString());

                resultSummary.SetProperty("SchemaInputs", inputSchemaString);
                resultSummary.SetProperty("SchemaOutputs", outputSchemaString);
                results.Add(resultSummary);

                if (outputStream != null)
                {
                    outputStream.WriteLine("Class: [{0}] {1}", moveNextMethod.ContainingType.FullPathName(), moveNextMethod.ToSignatureString());
                    if (depAnalysisResult.IsTop)
                    {
                        outputStream.WriteLine("Analysis returns TOP");
                    }
                    outputStream.WriteLine("Inputs: {0}", String.Join(", ", inputsString));
                    outputStream.WriteLine("Outputs: {0}", String.Join(", ", outputsString));
                }
            }
            else
            {
                var result = new Result();
                result.Id = "SingleColumn";
                result.SetProperty("column", "_TOP_");
                result.SetProperty("depends", "_TOP_");
                results.Add(result);
                var resultEmpty = new Result();
                resultEmpty.Id = "Summary";
                resultEmpty.SetProperty("Inputs", "_TOP_");
                resultEmpty.SetProperty("Outputs", "_TOP_");
                resultEmpty.SetProperty("SchemaInputs", "_TOP_");
                resultEmpty.SetProperty("SchemaOutputs", "_TOP_");
                results.Add(resultEmpty);
            }


            var id = String.Format("[{0}] {1}", moveNextMethod.ContainingType.FullPathName(), moveNextMethod.ToSignatureString());

            // Very clumsy way to find the process number and the processor name from the MoveNext method.
            // But it is the process number and processor name that allow us to link these results to the information
            // in the XML file that describes the job.
            // Climb the containing type chain from the MoveNext method until we find the entry in the dictionary whose
            // value matches one of the classes.
            var done = false;

            foreach (var kv in processorMap)
            {
                if (done)
                {
                    break;
                }
                var c = moveNextMethod.ContainingType as ClassDefinition;
                while (c != null)
                {
                    if (kv.Value == c)
                    {
                        id   = kv.Value.Name + "|" + kv.Key;
                        done = true;
                        break;
                    }
                    c = c.ContainingType as ClassDefinition;
                }
            }

            AddRunToSarifOutput(log, inputPath, id, results);
        }
        /// This does the interprocedural analysis.
        /// It (currently) does NOT support recursive method invocations
        /// </summary>
        /// <param name="instruction"></param>
        /// <param name="resolvedCallee"></param>
        /// <param name="calleeCFG"></param>
        private InterProceduralReturnInfo InterproceduralAnalysis(InterProceduralCallInfo callInfo, ControlFlowGraph calleeCFG)
        {
            if (stackDepth > InterproceduralManager.MaxStackDepth)
            {
                return(new InterProceduralReturnInfo(callInfo.CallerState));
            }

            stackDepth++;
            // I currently do not support recursive calls
            // Will add support for this in the near future
            if (callStack.Contains(callInfo.Callee))
            {
                callInfo.CallerState.Dependencies.IsTop = true;
                AnalysisStats.AddAnalysisReason(new AnalysisReason(callInfo.Caller, callInfo.Instruction, String.Format(CultureInfo.InvariantCulture, "Recursive call to {0}", callInfo.Callee.Name)));
                return(new InterProceduralReturnInfo(callInfo.CallerState));
            }

            this.callStack.Push(callInfo.Callee);
            System.Console.WriteLine("Analyzing Method {0} Stack: {1}", new string(' ', stackDepth * 2) + callInfo.Callee.ToSignatureString(), stackDepth);
            // 1) Bind PTG and create a Poinst-to Analysis for the  callee. In pta.Result[node.Exit] is the PTG at exit of the callee
            var calleePTG = PTABindCallerCallee(callInfo.CallerPTG, callInfo.CallArguments, callInfo.Callee);
            IteratorPointsToAnalysis calleePTA = new IteratorPointsToAnalysis(calleeCFG, callInfo.Callee, calleePTG);

            IDictionary <IVariable, IExpression> equalities = new Dictionary <IVariable, IExpression>();

            SongTaoDependencyAnalysis.PropagateExpressions(calleeCFG, equalities);

            var rangesAnalysis = new RangeAnalysis(calleeCFG);

            rangesAnalysis.Analyze();
            // 2) Bind Parameters of the dependency analysis and run
            var calleeDomain = BindCallerCallee(callInfo);

            calleeDomain.PTG = calleePTG;
            var dependencyAnalysis = new IteratorDependencyAnalysis(callInfo.Callee, calleeCFG, calleePTA, callInfo.ProtectedNodes, equalities, this, rangesAnalysis, calleeDomain, callInfo.ScopeData);

            // If we already did the dataflow analysis for this method we recover the dataflow state
            // This should be adapted (or removed) if we want the analysis to be context sensitive

            //if (dataflowCache.ContainsKey(callInfo.Callee))
            //{
            //    var previosResult = dataflowCache[callInfo.Callee];
            //    //DataFlowAnalysisResult<DependencyPTGDomain>[] resultsCopy = new DataFlowAnalysisResult<DependencyPTGDomain>[previosResult.Length];
            //    //for(int i=0; i< previosResult.Length; i++)
            //    //{
            //    //    resultsCopy[i] = new DataFlowAnalysisResult<DependencyPTGDomain>();
            //    //    resultsCopy[i].Input = previosResult[i].Input!=null? previosResult[i].Input.Clone(): null;
            //    //    resultsCopy[i].Output = previosResult[i].Output!=null? previosResult[i].Output.Clone(): null;
            //    //}
            //    //dependencyAnalysis.SetPreviousResult(resultsCopy);

            //    dependencyAnalysis.SetPreviousResult(previosResult);
            //}

            dependencyAnalysis.Analyze();


            this.dataflowCache[callInfo.Callee] = dependencyAnalysis.Result;

            stackDepth--;
            this.callStack.Pop();

            // 3) Bind callee with caller
            // Should I need the PTG of caller and callee?
            //var exitCalleePTG = calleePTA.Result[calleeCFG.Exit.Id].Output;
            var exitCalleePTG = dependencyAnalysis.Result[calleeCFG.Exit.Id].Output.PTG;
            var exitResult    = BindCalleeCaller(callInfo, calleeCFG, dependencyAnalysis);

            // Recover the frame of the original Ptg and bind ptg results
            //PointsToGraph bindPtg = PTABindCaleeCalleer(callInfo.CallLHS, calleeCFG, calleePTA);
            var bindPtg = PTABindCaleeCalleer(callInfo.CallLHS, calleeCFG, exitCalleePTG, calleePTA.ReturnVariable);

            exitResult.PTG = bindPtg;

            return(new InterProceduralReturnInfo(exitResult));
            //return new InterProceduralReturnInfo(exitResult, bindPtg);
        }
Example #3
0
        public static SarifLog AnalyzeDll(string inputPath, ScopeMethodKind kind,

                                          bool useScopeFactory = true, bool interProc = false, StreamWriter outputStream = null)
        {
            // Determine whether to use Interproc analysis
            AnalysisOptions.DoInterProcAnalysis = interProc;

            AnalysisStats.TotalNumberFolders++;

            var host = new MyHost();

            PlatformTypes.Resolve(host);

            var loader = new MyLoader(host);

            host.Loader = loader;

            var scopeGenAssembly = loader.LoadMainAssembly(inputPath);

            AnalysisStats.TotalDllsFound++;

            loader.LoadCoreAssembly();

            var program = new ScopeProgramAnalysis(host, loader);

            // program.interprocAnalysisManager = new InterproceduralManager(host);
            program.ScopeGenAssembly = scopeGenAssembly;
            //program.ReferenceFiles = referenceFiles;

            program.ClassFilters    = new HashSet <string>();
            program.ClousureFilters = new HashSet <string>();

            program.EntryMethods = new HashSet <string>();

            if (kind == ScopeMethodKind.Reducer || kind == ScopeMethodKind.All)
            {
                program.ClassFilters.Add("Reducer");
                program.ClousureFilters.Add("<Reduce>d__");
                program.EntryMethods.Add("Reduce");
            }
            if (kind == ScopeMethodKind.Producer || kind == ScopeMethodKind.All)
            {
                program.ClassFilters.Add("Processor");
                program.ClousureFilters.Add("<Process>d__");
                program.EntryMethods.Add("Process");
                //program.ClassFilter = "Producer";
                //program.ClousureFilter = "<Produce>d__";
                //program.EntryMethod = "Produce";
            }

            program.MethodUnderAnalysisName = "MoveNext";

            IEnumerable <Tuple <MethodDefinition, MethodDefinition, MethodDefinition> > scopeMethodPairs;

            if (useScopeFactory)
            {
                scopeMethodPairs = program.ObtainScopeMethodsToAnalyze();
                if (!scopeMethodPairs.Any())
                {
                    if (outputStream != null)
                    {
                        outputStream.WriteLine("Failed to obtain methods from the ScopeFactory. ");
                    }
                    System.Console.WriteLine("Failed to obtain methods from the ScopeFactory.");

                    //System.Console.WriteLine("Now trying to find methods in the the assembly");
                    //scopeMethodPairs = program.ObtainScopeMethodsToAnalyzeFromAssemblies();
                }
            }
            else
            {
                scopeMethodPairs = program.ObtainScopeMethodsToAnalyzeFromAssemblies();
            }


            if (scopeMethodPairs.Any())
            {
                var log = CreateSarifOutput();

                IReadOnlyDictionary <string, Tuple <Schema, Schema> > allSchemas;
                if (useScopeFactory)
                {
                    allSchemas = program.ReadSchemasFromXML(inputPath);
                }
                else
                {
                    allSchemas = program.ReadSchemasFromXML2(inputPath);
                }

                foreach (var methodPair in scopeMethodPairs)
                {
                    AnalysisStats.TotalMethods++;

                    var entryMethodDef = methodPair.Item1;
                    var moveNextMethod = methodPair.Item2;
                    var getEnumMethod  = methodPair.Item3;
                    System.Console.WriteLine("Method {0} on class {1}", moveNextMethod.Name, moveNextMethod.ContainingType.FullPathName());

                    Schema inputSchema  = null;
                    Schema outputSchema = null;
                    Tuple <Schema, Schema> schemas;
                    if (allSchemas.TryGetValue(moveNextMethod.ContainingType.ContainingType.Name, out schemas))
                    {
                        inputSchema  = schemas.Item1;
                        outputSchema = schemas.Item2;
                    }

                    try
                    {
                        InputSchema  = inputSchema;
                        OutputSchema = outputSchema;
                        var dependencyAnalysis = new SongTaoDependencyAnalysis(host, program.interprocAnalysisManager, moveNextMethod, entryMethodDef, getEnumMethod);
                        var depAnalysisResult  = dependencyAnalysis.AnalyzeMoveNextMethod();

                        WriteResultToSarifLog(inputPath, outputStream, log, moveNextMethod, depAnalysisResult, dependencyAnalysis, program.factoryReducerMap);

                        InputSchema  = null;
                        OutputSchema = null;
                    }
                    catch (Exception e)
                    {
                        System.Console.WriteLine("Could not analyze {0}", inputPath);
                        System.Console.WriteLine("Exception {0}\n{1}", e.Message, e.StackTrace);
                        AnalysisStats.TotalofDepAnalysisErrors++;
                        AnalysisStats.AddAnalysisReason(new AnalysisReason(moveNextMethod, moveNextMethod.Body.Instructions[0],
                                                                           String.Format(CultureInfo.InvariantCulture, "Throw exception {0}\n{1}", e.Message, e.StackTrace.ToString())));
                    }
                }
                return(log);
            }
            else
            {
                System.Console.WriteLine("No method {0} of type {1} in {2}", program.MethodUnderAnalysisName, program.ClassFilters, inputPath);
                return(null);
            }
        }