/// <summary> /// Runs the first phase analysis. /// </summary> private void runFirstPhaseAnalysis() { State = AnalysisState.ForwardAnalysis; FirstPhaseInitialMemory = GC.GetTotalMemory(true); WatchFirstPhase.Start(); try { firstPhaseAnalysis = new Weverca.Analysis.ForwardAnalysis(controlFlowGraph, MemoryModel); IsFirstPhaseStarted = true; firstPhaseAnalysis.Analyse(); } finally { WatchFirstPhase.Stop(); FirstPhaseEndMemory = GC.GetTotalMemory(true); if (IsFirstPhaseStarted) { programPointGraph = firstPhaseAnalysis.ProgramPointGraph; analysisWarnings = AnalysisWarningHandler.GetWarnings(); securityWarnings = AnalysisWarningHandler.GetSecurityWarnings(); } } if (IsFirstPhaseStarted) { IsFirstPhaseFinished = true; } }
/// <summary> /// Report a warning for the position of current expression. /// </summary> /// <param name="flow">Flow controller of program point providing data for evaluation.</param> /// <param name="message">Message of the warning.</param> /// <param name="cause">Cause of the warning.</param> private static void SetWarning(FlowController flow, string message, AnalysisWarningCause cause) { var warning = new AnalysisWarning(flow.CurrentScript.FullName, message, flow.CurrentPartial, flow.CurrentProgramPoint, cause); AnalysisWarningHandler.SetWarning(flow.OutSet, warning); }
/// <summary> /// Report a warning for the position of current expression. /// </summary> /// <param name="message">Message of the warning.</param> /// <param name="cause">Cause of the warning.</param> protected void SetWarning(string message, AnalysisWarningCause cause) { var warning = new AnalysisWarning(flow.CurrentScript.FullName, message, flow.CurrentPartial, flow.CurrentProgramPoint, cause); AnalysisWarningHandler.SetWarning(OutSet, warning); }
public static bool ContainsSecurityWarning(FlowOutputSet outset, FlagType cause) { var warnings = AnalysisWarningHandler.ReadWarnings <AnalysisSecurityWarning>(outset); foreach (var value in warnings) { var infoValue = (InfoValue <AnalysisSecurityWarning>)value; if (infoValue.Data.Flag == cause) { return(true); } } return(false); }
/// <summary> /// Checks arguments in functions and generates warning if the arguments don't match. /// </summary> /// <param name="flow">FlowController</param> /// <param name="nativeFunctions">nativeFunctions</param> public static void checkArgumentTypes(FlowController flow, List <NativeFunction> nativeFunctions) { List <List <AnalysisWarning> > warningsList = new List <List <AnalysisWarning> >(); MemoryEntry argc = flow.InSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(flow.OutSet.Snapshot); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; foreach (var nativeFunction in nativeFunctions) { if (nativeFunction.MinArgumentCount <= argumentCount && nativeFunction.MaxArgumentCount >= argumentCount) { warningsList.Add(new List <AnalysisWarning>()); int functionArgumentNumber = 0; for (int i = 0; i < argumentCount; i++) { MemoryEntry arg = flow.InSet.ReadVariable(Argument(i)).ReadMemory(flow.InSet.Snapshot); NativeFunctionArgument functionArgument = nativeFunction.Arguments.ElementAt(functionArgumentNumber); CheckArgumentTypes(flow, arg, functionArgument, i + 1, nativeFunctions.ElementAt(0).Name.ToString(), warningsList.Last()); //incremeneting functionArgumentNumber if (nativeFunction.Arguments.ElementAt(functionArgumentNumber).Dots == false) { functionArgumentNumber++; } } } } int index_min = -1; int value_min = int.MaxValue; for (int i = 0; i < warningsList.Count; i++) { if (warningsList[i].Count < value_min) { value_min = warningsList[i].Count; index_min = i; } } foreach (AnalysisWarning warning in warningsList[index_min]) { AnalysisWarningHandler.SetWarning(flow.OutSet, warning); } }
/// <summary> /// Clears the inner fields before new computation is performed. /// </summary> private void clearComputation() { AnalysisWarningHandler.ResetWarnings(); IsFirstPhaseStarted = false; IsSecondPhaseStarted = false; IsFirstPhaseFinished = false; IsSecondPhaseFinished = false; analysisWarnings = null; securityWarnings = null; secondPhaseWarnings = null; programPointGraph = null; firstPhaseAnalysis = null; secondPhaseAnalysis = null; // Force garbage collecting GC.Collect(); GC.WaitForPendingFinalizers(); }
/// <summary> /// Models constructor of native object /// </summary> /// <param name="flow">FlowController</param> public void initObject(FlowController flow) { var nativeClass = NativeObjectAnalyzer.GetInstance(flow.OutSet).GetClass(ObjectName); var fields = nativeClass.Fields; var thisVariable = flow.OutSet.GetVariable(new VariableIdentifier("this")); List <Value> inputValues = new List <Value>(); foreach (var argument in getArguments(flow)) { inputValues.AddRange(argument.PossibleValues); } MethodIdentifier methodIdentifier = new MethodIdentifier(ObjectName, Method.Name.Name); if (NativeObjectAnalyzer.ReportingFunctions.ContainsKey(methodIdentifier)) { foreach (var flag in NativeObjectAnalyzer.ReportingFunctions[methodIdentifier]) { if (FlagsHandler.IsDirty(inputValues, flag)) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisSecurityWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), flow.CurrentPartial, flow.CurrentProgramPoint, flag, methodIdentifier.Name.ToString())); break; } } } foreach (FieldInfo field in fields.Values) { if (field.IsStatic == false) { MemoryEntry fieldValues = NativeAnalyzerUtils.ResolveReturnValue(field.Type, flow); fieldValues = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, fieldValues.PossibleValues)); var fieldEntry = thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)); fieldEntry.WriteMemory(flow.OutSet.Snapshot, fieldValues); } } }
public static ResultModel Run(string phpCode, AnalysisModel analysisModel) { string fileName = @"\UserInput\userInput.php"; SyntaxParser parser = InitializeParser(phpCode, fileName); var cfg = ControlFlowGraph.ControlFlowGraph.FromSource(parser.Ast, new FileInfo(fileName)); var result = new ResultModel(phpCode); AnalysisWarningHandler.ResetWarnings(); if (analysisModel.RunVerification) { result.Output = RunVerification(cfg, fileName, analysisModel.GetMemoryModel()); } if (analysisModel.RunMetrics) { RunMetrics(parser, analysisModel, result); } result.LoadWarnings(); return(result); }
public void LoadWarnings() { Warnings = AnalysisWarningHandler.GetWarnings(); SecurityWarnings = AnalysisWarningHandler.GetSecurityWarnings(); }
/// <summary> /// Generates a warning of the proper type and with the given message /// </summary> /// <param name="message">Text of warning</param> /// <param name="cause">More specific warning type</param> public void SetWarning(string message, AnalysisWarningCause cause) { AnalysisWarningHandler.SetWarning(Context, new AnalysisWarning(Point.OwningScriptFullName, message, Point.Partial, Point, cause)); }
/// <summary> /// Models a called method. /// </summary> /// <param name="flow"></param> public void Analyze(FlowController flow) { if (NativeAnalyzerUtils.checkArgumentsCount(flow, Method)) { NativeAnalyzerUtils.checkArgumentTypes(flow, Method); } MethodIdentifier methodIdentifier = new MethodIdentifier(ObjectName, Method.Name.Name); var nativeClass = NativeObjectAnalyzer.GetInstance(flow.OutSet).GetClass(ObjectName); var fields = nativeClass.Fields; var functionResult = NativeAnalyzerUtils.ResolveReturnValue(Method.ReturnType, flow); var arguments = getArguments(flow); var thisVariable = flow.OutSet.GetVariable(new VariableIdentifier("this")); List <Value> inputValues = new List <Value>(); bool isStaticCall = false; if (thisVariable.ReadMemory(flow.OutSet.Snapshot).PossibleValues.Count() == 1 && thisVariable.ReadMemory(flow.OutSet.Snapshot).PossibleValues.First() is UndefinedValue) { isStaticCall = true; var fieldsEntries = new List <MemoryEntry>(); foreach (FieldInfo field in fields.Values) { var fieldEntry = thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)); fieldsEntries.Add(fieldEntry.ReadMemory(flow.OutSet.Snapshot)); inputValues.AddRange(fieldEntry.ReadMemory(flow.OutSet.Snapshot).PossibleValues); } fieldsEntries.AddRange(arguments); foreach (FieldInfo field in fields.Values) { var fieldEntry = thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)); MemoryEntry newfieldValues = NativeAnalyzerUtils.ResolveReturnValue(field.Type, flow); newfieldValues = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, newfieldValues.PossibleValues)); HashSet <Value> newValues = new HashSet <Value>((fieldEntry.ReadMemory(flow.OutSet.Snapshot)).PossibleValues); foreach (var newValue in newfieldValues.PossibleValues) { newValues.Add(newValue); } thisVariable.ReadField(flow.OutSet.Snapshot, new VariableIdentifier(field.Name.Value)).WriteMemory(flow.OutSet.Snapshot, new MemoryEntry(newValues)); } } foreach (var argument in arguments) { inputValues.AddRange(argument.PossibleValues); } if (NativeObjectAnalyzer.ReportingFunctions.ContainsKey(methodIdentifier)) { foreach (var flag in NativeObjectAnalyzer.ReportingFunctions[methodIdentifier]) { if (FlagsHandler.IsDirty(inputValues, flag)) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisSecurityWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), flow.CurrentPartial, flow.CurrentProgramPoint, flag, methodIdentifier.Name.ToString())); break; } } } if (isStaticCall == true) { thisVariable.WriteMemory(flow.OutSet.Snapshot, new MemoryEntry(FlagsHandler.CopyFlags(inputValues, thisVariable.ReadMemory(flow.OutSet.Snapshot).PossibleValues))); } functionResult = new MemoryEntry(FlagsHandler.CopyFlags(inputValues, functionResult.PossibleValues)); if (NativeObjectAnalyzer.CleaningFunctions.ContainsKey(methodIdentifier)) { foreach (var flag in NativeObjectAnalyzer.CleaningFunctions[methodIdentifier]) { functionResult = new MemoryEntry(FlagsHandler.Clean(functionResult.PossibleValues, flag)); } } flow.OutSet.GetLocalControlVariable(SnapshotBase.ReturnValue).WriteMemory(flow.OutSet.Snapshot, functionResult); var assigned_aliases = NativeAnalyzerUtils.ResolveAliasArguments(flow, inputValues, (new NativeFunction[1] { Method }).ToList()); }
/// <summary> /// Checks number of arguments in called function. /// </summary> /// <param name="flow">FlowControllers</param> /// <param name="nativeFunctions">NativeFunctions</param> /// <returns>true if the arguments count matches, false otherwise</returns> static public bool checkArgumentsCount(FlowController flow, List <NativeFunction> nativeFunctions) { //check number of arduments MemoryEntry argc = flow.InSet.ReadVariable(new VariableIdentifier(".argument_count")).ReadMemory(flow.OutSet.Snapshot); int argumentCount = ((IntegerValue)argc.PossibleValues.ElementAt(0)).Value; //argument count hassnt been comupted yet if (nativeFunctions.ElementAt(0).MinArgumentCount == -1) { foreach (var nativeFuntion in nativeFunctions) { nativeFuntion.MinArgumentCount = 0; nativeFuntion.MaxArgumentCount = 0; foreach (var nativeFunctionArgument in nativeFuntion.Arguments) { if (nativeFunctionArgument.Dots) { nativeFuntion.MaxArgumentCount = 1000000000; } else if (nativeFunctionArgument.Optional) { nativeFuntion.MaxArgumentCount++; } else { nativeFuntion.MinArgumentCount++; nativeFuntion.MaxArgumentCount++; } } //Console.WriteLine("Name: {0},Min: {1}, Max: {2}", nativeFuntion.Name,nativeFuntion.MinArgumentCount, nativeFuntion.MaxArgumentCount); } } string numberOfArgumentMessage = ""; bool argumentCountMatches = false; foreach (var nativeFunction in nativeFunctions) { if (nativeFunction.MinArgumentCount <= argumentCount && nativeFunction.MaxArgumentCount >= argumentCount) { argumentCountMatches = true; } if (numberOfArgumentMessage != "") { numberOfArgumentMessage += " or"; } if (nativeFunction.MaxArgumentCount >= 1000000000) { if (nativeFunction.MinArgumentCount == 1) { numberOfArgumentMessage += " at least " + nativeFunction.MinArgumentCount + " parameter"; } else { numberOfArgumentMessage += " at least " + nativeFunction.MinArgumentCount + " parameters"; } } else { if (nativeFunction.MaxArgumentCount == nativeFunction.MinArgumentCount) { if (nativeFunction.MinArgumentCount == 1) { numberOfArgumentMessage += " " + nativeFunction.MinArgumentCount + " parameter"; } else { numberOfArgumentMessage += " " + nativeFunction.MinArgumentCount + " parameters"; } } else { numberOfArgumentMessage += " " + nativeFunction.MinArgumentCount + "-" + nativeFunction.MaxArgumentCount + " parameters"; } } } if (argumentCountMatches == false) { string s = ""; if (argumentCount != 1) { s = "s"; } AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(NativeAnalyzerUtils.GetCallerScript(flow.OutSet), "Function " + nativeFunctions.ElementAt(0).Name.ToString() + " expects" + numberOfArgumentMessage + ", " + argumentCount + " parameter" + s + " given.", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.WRONG_NUMBER_OF_ARGUMENTS)); return(false); } else { return(true); } }
public static int NumWarnings(FlowOutputSet outset) { return(AnalysisWarningHandler.ReadWarnings <AnalysisWarning>(outset).Count()); }
/// <summary> /// Is called after each include/require/include_once/require_once expression (can be resolved according to flow.CurrentPartial) /// </summary> /// <param name="flow">Flow controller where include extensions can be stored</param> /// <param name="includeFile">File argument of include statement</param> public override void Include(FlowController flow, MemoryEntry includeFile) { if (FlagsHandler.IsDirty(includeFile.PossibleValues, FlagType.FilePathDirty)) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisSecurityWarning(flow.CurrentScript.FullName, flow.CurrentPartial, flow.CurrentProgramPoint, FlagType.FilePathDirty, "")); } bool isAlwaysConcrete = true; //extend current program point as Include List <string> files = FunctionResolver.GetFunctionNames(includeFile, flow, out isAlwaysConcrete); if (isAlwaysConcrete == false) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Couldn't resolve all possible includes", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.COULDNT_RESOLVE_ALL_INCLUDES)); } IncludingEx includeExpression = flow.CurrentPartial as IncludingEx; foreach (var branchKey in flow.ExtensionKeys) { if (!files.Remove(branchKey as string)) { //this include is now not resolved as possible include branch flow.RemoveExtension(branchKey); } } int numberOfWarnings = 0; var includedFiles = flow.OutSet.GetControlVariable(new VariableName(".includedFiles")).ReadMemory(flow.OutSet.Snapshot); foreach (var file in files) { var fileInfo = findFile(flow, file); if (fileInfo == null) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "The file " + file + " to be included not found", flow.CurrentProgramPoint.Partial, flow.CurrentProgramPoint, AnalysisWarningCause.FILE_TO_BE_INCLUDED_NOT_FOUND)); numberOfWarnings++; continue; } string fileName = fileInfo.FullName; // Handling include_once, require_once var varIncluded = flow.OutSet.GetControlVariable(new VariableName(fileName)); if (includeExpression.InclusionType == InclusionTypes.IncludeOnce || includeExpression.InclusionType == InclusionTypes.RequireOnce) { var includedInfo = varIncluded.ReadMemory(flow.OutSet.Snapshot); if (includedInfo != null) { var includeType = (includeExpression.InclusionType == InclusionTypes.IncludeOnce) ? "include_once" : "require_once"; if (includedInfo.PossibleValues.Count() > 1) { //TODO: report or not? //AnalysisWarningHandler.SetWarning (flow.OutSet, new AnalysisWarning (flow.CurrentScript.FullName, includeType + " is called more times in some program paths with the file " + fileName, flow.CurrentProgramPoint.Partial, flow.CurrentProgramPoint, AnalysisWarningCause.INCLUDE_REQUIRE_ONCE_CALLED_MORE_TIMES_WITH_SAME_FILE)); // TODO: include the file or not?? continue; } else { if (!(includedInfo.PossibleValues.First() is UndefinedValue)) { //TODO: report or not? //AnalysisWarningHandler.SetWarning (flow.OutSet, new AnalysisWarning (flow.CurrentScript.FullName, includeType + " is called more times with the file " + fileName, flow.CurrentProgramPoint.Partial, flow.CurrentProgramPoint, AnalysisWarningCause.INCLUDE_REQUIRE_ONCE_CALLED_MORE_TIMES_WITH_SAME_FILE)); continue; } } } } // Avoid recursive includes // the file was never included int numberOfIncludes = -1; // TODO: optimization - avoid iterating all included files // - make .includedFiles associative array with names of functions as indexes foreach (InfoValue <NumberOfCalls <string> > includeInfo in includedFiles.PossibleValues.Where(a => (a is InfoValue <NumberOfCalls <string> >))) { if (includeInfo.Data.Callee == fileName) { numberOfIncludes = Math.Max(numberOfIncludes, includeInfo.Data.TimesCalled); } } if (numberOfIncludes >= 0) { if (numberOfIncludes > 2 || sharedFiles.Contains(fileName)) { if (sharedFiles.Contains(fileName)) { //set graph sharing for this function if (!sharedProgramPoints.ContainsKey(fileName)) { try { //create single graph instance sharedProgramPoints[fileName] = ProgramPointGraph.FromSource(ControlFlowGraph.ControlFlowGraph.FromFile(fileInfo)); } catch (ControlFlowGraph.ControlFlowException) { numberOfWarnings++; AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Control flow graph creation error", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.CFG_EXCEPTION_IN_INCLUDE_OR_EVAL)); } catch (Parsers.ParserException) { numberOfWarnings++; AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Parser error", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.PARSER_EXCEPTION_IN_INCLUDE_OR_EVAL)); } } //get shared instance of program point graph flow.AddExtension(fileName, sharedProgramPoints[fileName], ExtensionType.ParallelInclude); continue; } else { sharedFiles.Add(fileName); } } } try { // Write information about inclusion of the file varIncluded.WriteMemory(flow.OutSet.Snapshot, new MemoryEntry(flow.OutSet.Snapshot.CreateBool(true))); //Create graph for every include - NOTE: we can share pp graphs var cfg = ControlFlowGraph.ControlFlowGraph.FromFile(fileInfo); var ppGraph = ProgramPointGraph.FromSource(cfg); flow.AddExtension(fileName, ppGraph, ExtensionType.ParallelInclude); } catch (ControlFlowGraph.ControlFlowException) { numberOfWarnings++; AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Control flow graph creation error", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.CFG_EXCEPTION_IN_INCLUDE_OR_EVAL)); } catch (Parsers.ParserException) { numberOfWarnings++; AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Parser error", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.PARSER_EXCEPTION_IN_INCLUDE_OR_EVAL)); } } if (numberOfWarnings > 0 && (includeExpression.InclusionType == InclusionTypes.Require || includeExpression.InclusionType == InclusionTypes.RequireOnce)) { if (numberOfWarnings == files.Count && isAlwaysConcrete == true) { fatalError(flow, true); } else { fatalError(flow, false); } } }
/// <summary> /// Process throw statement according to current flow /// </summary> /// <param name="flow">Flow controller which provides API usefull for throw resolvings</param> /// <param name="outSet">Flow output set</param> /// <param name="throwStmt">Processed throw statement</param> /// <param name="throwedValue">Value that was supplied into throw statement</param> /// <returns> /// All possible ThrowInfo branches /// </returns> public override IEnumerable <ThrowInfo> Throw(FlowController flow, FlowOutputSet outSet, ThrowStmt throwStmt, MemoryEntry throwedValue) { var catchBlocks = outSet.GetControlVariable(new VariableName(".catchBlocks")); var stack = new List <HashSet <CatchBlockDescription> >(); foreach (var value in catchBlocks.ReadMemory(outSet.Snapshot).PossibleValues) { if (stack.Count == 0) { for (int i = 0; i < (value as InfoValue <TryBlockStack>).Data.blocks.Count; i++) { stack.Add(new HashSet <CatchBlockDescription>()); } } for (int i = 0; i < (value as InfoValue <TryBlockStack>).Data.blocks.Count; i++) { foreach (var block in (value as InfoValue <TryBlockStack>).Data.blocks[i]) { stack[i].Add(block); } } } Dictionary <CatchBlockDescription, List <Value> > result = new Dictionary <CatchBlockDescription, List <Value> >(); int numberOfWarnings = 0; foreach (Value value in throwedValue.PossibleValues) { bool foundMatch = false; if (value is ObjectValue) { TypeValue type = outSet.ObjectType(value as ObjectValue); var exceptionName = new QualifiedName(new Name("Exception")); if (type.Declaration.BaseClasses.Where(a => a.Equals(exceptionName)).Count() == 0 && !type.QualifiedName.Equals(exceptionName)) { AnalysisWarningHandler.SetWarning(outSet, new AnalysisWarning(flow.CurrentScript.FullName, "Only objects derived from Exception can be thrown", throwStmt, flow.CurrentProgramPoint, AnalysisWarningCause.ONLY_OBJECT_CAM_BE_THROWN)); foundMatch = false; } else { for (int i = stack.Count - 1; i >= 0; i--) { foreach (var block in stack[i]) { if (type.QualifiedName == block.CatchedType.QualifiedName) { var key = block; if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); foundMatch = true; } else { for (int j = type.Declaration.BaseClasses.Count - 1; j >= 0; j--) { if (type.Declaration.BaseClasses[j] == block.CatchedType.QualifiedName) { var key = block; if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); foundMatch = true; break; } } } if (foundMatch) { break; } } if (foundMatch) { break; } } } } else if (value is AnyObjectValue || value is AnyValue) { for (int i = stack.Count - 1; i >= 0; i--) { foreach (var block in stack[i]) { var key = block; if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); foundMatch = true; } } } else { AnalysisWarningHandler.SetWarning(outSet, new AnalysisWarning(flow.CurrentScript.FullName, "Only objects can be thrown", throwStmt, flow.CurrentProgramPoint, AnalysisWarningCause.ONLY_OBJECT_CAM_BE_THROWN)); numberOfWarnings++; foundMatch = false; } if (!foundMatch) { var key = new CatchBlockDescription(flow.ProgramEnd, new GenericQualifiedName(new QualifiedName(new Name(""))), new VariableIdentifier("")); if (!result.ContainsKey(key)) { result[key] = new List <Value>(); } result[key].Add(value); } } List <ThrowInfo> res = new List <ThrowInfo>(); foreach (var entry in result) { res.Add(new ThrowInfo(entry.Key, new MemoryEntry(entry.Value))); } if (numberOfWarnings >= throwedValue.Count) { fatalError(flow, true); } else if (numberOfWarnings > 0) { fatalError(flow, false); } return(res); }
/// <summary> /// Execute the static analysis and print results /// </summary> /// <param name="filenames">List of file name patterns from command line</param> /// <param name="memoryModel">The memory model used for analysis</param> private static void RunStaticAnalysis(string[] filenames, MemoryModels.MemoryModelFactory memoryModel, bool displayTaintFlows) { var console = new ConsoleOutput(); console.CommentLine("Using " + memoryModel.ToString()); console.CommentLine(""); foreach (var argument in filenames) { var filesInfo = Analyzer.GetFileNames(argument); if (filesInfo == null) { Console.WriteLine("Path \"{0}\" cannot be recognized", argument); Console.WriteLine(); continue; } else if (filesInfo.Length <= 0) { Console.WriteLine("Path pattern \"{0}\" does not match any file", argument); Console.WriteLine(); continue; } foreach (var fileInfo in filesInfo) { // This is for time consumption analyzing only // Analyze twice - because of omitting .NET initialization we get better analysis time //Analyzer.Run(fileInfo, memoryModel); #if TEST // Process analysis // First phase var watch = System.Diagnostics.Stopwatch.StartNew(); var ppGraph = Analyzer.Run(fileInfo, memoryModel); watch.Stop(); // Second phase var watch2 = System.Diagnostics.Stopwatch.StartNew(); var nextPhase = new TaintForwardAnalysis(ppGraph); nextPhase.Analyse(); watch2.Stop(); // Build output console.CommentLine(string.Format("File path: {0}\n", fileInfo.FullName)); var graphWalker = new GraphWalking.CallGraphPrinter(ppGraph); console.CommentLine(string.Format("Analysis completed in: {0}ms\n", watch.ElapsedMilliseconds)); //graphWalker.Run(console); console.Warnings(AnalysisWarningHandler.GetWarnings(), AnalysisWarningHandler.GetSecurityWarnings()); console.CommentLine(string.Format("Analysis completed in: {0}ms\n", watch.ElapsedMilliseconds)); console.CommentLine(string.Format("The number of nodes in the application is: {0}\n", numProgramPoints(new HashSet <ProgramPointGraph>(), new Dictionary <string, HashSet <int> >(), ppGraph))); //printIncludes(console, ppGraph); //console.CommentLine(string.Format("Analysis in the second phase completed in: {0}ms\n", watch2.ElapsedMilliseconds)); //console.WarningsTaint(nextPhase.analysisTaintWarnings); if (ppGraph.End.OutSet != null) { console.CommentLine(string.Format("The number of memory locations is: {0}\n", ppGraph.End.OutSnapshot.NumMemoryLocations())); int[] statistics = ppGraph.End.OutSnapshot.GetStatistics().GetStatisticsValues(); console.CommentLine(string.Format("The number of memory entry assigns is: {0}\n", statistics[(int)Statistic.MemoryEntryAssigns])); console.CommentLine(string.Format("The number of value reads is: {0}\n", statistics[(int)Statistic.ValueReads])); console.CommentLine(string.Format("The number of memory entry merges is: {0}\n", statistics[(int)Statistic.MemoryEntryMerges])); console.CommentLine(string.Format("The number of index reads is: {0}\n", statistics[(int)Statistic.IndexReads])); console.CommentLine(string.Format("The number of value reads is: {0}\n", statistics[(int)Statistic.ValueReads])); } else { console.CommentLine(string.Format("Snapshot statistics are not available, because end point was not reached")); } #else console.CommentLine(string.Format("File path: {0}\n", fileInfo.FullName)); TaintForwardAnalysis nextPhase = null; System.Diagnostics.Stopwatch watch = null; try { watch = System.Diagnostics.Stopwatch.StartNew(); var ppGraph = Analyzer.Run(fileInfo, memoryModel); watch.Stop(); if (ppGraph.End.OutSet != null) { //console.ProgramPointInfo("End point", ppGraph.End); } else { //console.Error("End point was not reached"); } console.CommentLine(string.Format("First phase of the analysis completed in: {0} seconds\n", watch.ElapsedMilliseconds / 1000)); nextPhase = new TaintForwardAnalysis(ppGraph); nextPhase.Analyse(); } catch (OutOfMemoryException) { watch.Stop(); console.Error(string.Format("The analyser ran out of memory after {0} seconds, terminating the analysis.\n", watch.ElapsedMilliseconds / 1000)); } catch (Exception e) { console.Error("Analyser crashed (" + e.Message + ")."); } finally { console.Warnings(AnalysisWarningHandler.GetWarnings(), nextPhase != null ? nextPhase.analysisTaintWarnings : new List <AnalysisTaintWarning>(), displayTaintFlows); } #endif } //Console.ReadKey(); Console.WriteLine(); } }
private static void RunStaticAnalysis(string[] filenames, MemoryModels.MemoryModelFactory memoryModel) { var bigWatch = System.Diagnostics.Stopwatch.StartNew(); var console = new ConsoleOutput(); foreach (var argument in filenames) { var filesInfo = Analyzer.GetFileNames(argument); if (filesInfo == null) { fileOutput.WriteLine("Path \"{0}\" cannot be recognized", argument); fileOutput.WriteLine(); continue; } else if (filesInfo.Length <= 0) { fileOutput.WriteLine("Path pattern \"{0}\" does not match any file", argument); fileOutput.WriteLine(); } foreach (var fileInfo in filesInfo) { console.CommentLine(string.Format("File path: {0}\n", fileInfo.FullName)); //try { var watch = System.Diagnostics.Stopwatch.StartNew(); var ppGraph = Analyzer.Run(fileInfo, memoryModel); watch.Stop(); GC.Collect(); GC.WaitForPendingFinalizers(); var watch2 = System.Diagnostics.Stopwatch.StartNew(); var nextPhase = new TaintForwardAnalysis(ppGraph); nextPhase.analysisTaintWarnings = new List <AnalysisTaintWarning>(); if (SECOND_PHASE) { nextPhase.Analyse(); } watch2.Stop(); fileOutput.WriteLine("Analysis warnings:"); var firstPhaseWarnings = AnalysisWarningHandler.GetWarnings(); //PrintWarnings(new List<AnalysisWarning>()); PrintWarnings(firstPhaseWarnings); var firstPhaseSecurityWarnings = new List <AnalysisSecurityWarning>(); if (!SECOND_PHASE) { firstPhaseSecurityWarnings = AnalysisWarningHandler.GetSecurityWarnings(); PrintSecurityWarnings(firstPhaseSecurityWarnings); } //fileOutput.WriteLine("Security warnings with taint flow:"); if (SECOND_PHASE) { PrintTaintWarnings(nextPhase.analysisTaintWarnings); } fileOutput.WriteLine("Variables:"); var processedPPGraphs = new HashSet <ProgramPointGraph>(); var processedPPoints = new HashSet <ProgramPointBase>(); writeAll(ppGraph, ref processedPPGraphs, ref processedPPoints); bigWatch.Stop(); fileOutput.WriteLine("Overview:"); fileOutput.WriteLine("Total number of warnings: " + (firstPhaseWarnings.Count + firstPhaseSecurityWarnings.Count + nextPhase.analysisTaintWarnings.Count)); fileOutput.WriteLine("Number of warnings in the first phase: " + firstPhaseWarnings.Count); fileOutput.WriteLine("Number of warnings in the second phase: " + nextPhase.analysisTaintWarnings.Count); fileOutput.WriteLine("Weverca analyzer time consumption: " + bigWatch.ElapsedMilliseconds); fileOutput.WriteLine("First phase time consumption: " + watch.ElapsedMilliseconds); fileOutput.WriteLine("Second phase time consumption: " + watch2.ElapsedMilliseconds); var programLines = new Dictionary <string, HashSet <int> > (); fileOutput.WriteLine("The number of nodes in the application is: " + Program.numProgramPoints(new HashSet <ProgramPointGraph>(), programLines, ppGraph)); var programLinesNum = 0; foreach (var script in programLines.Values) { programLinesNum += script.Count; } fileOutput.WriteLine("The number of processed lines of code is: " + programLinesNum); } /* * catch (Exception e) * { * fileOutput.WriteLine("error"); * //console.Error(e.Message); * fileOutput.WriteLine (e.Message); * }*/ } } }
/// <inheritdoc /> public override void Eval(FlowController flow, MemoryEntry code) { var flags = FlagsHandler.GetFlags(code.PossibleValues); if (flags.isDirty(FlagType.FilePathDirty) || flags.isDirty(FlagType.SQLDirty) || flags.isDirty(FlagType.FilePathDirty)) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisSecurityWarning(flow.CurrentScript.FullName, "Eval shoudn't contain anything from user input", flow.CurrentPartial, flow.CurrentProgramPoint, FlagType.HTMLDirty)); } double evalDepth = 0; var maxValue = new MaxValueVisitor(flow.OutSet); evalDepth = maxValue.Evaluate(flow.OutSet.GetControlVariable(FunctionResolver.evalDepth).ReadMemory(flow.OutSet.Snapshot)); if (evalDepth > 3) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, @"Eval cannot be called in ""eval recursion"" more than 3 times", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.TOO_DEEP_EVAL_RECURSION)); return; } StringConverter converter = new StringConverter(); converter.SetContext(flow); bool isAllwasConcrete = true; var codes = new HashSet <string>(); foreach (StringValue possibleFile in converter.Evaluate(code, out isAllwasConcrete)) { codes.Add(string.Format("<? {0}; ?>", possibleFile.Value)); } if (isAllwasConcrete == false) { AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Couldn't resolve all possible evals", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.COULDNT_RESOLVE_ALL_EVALS)); } foreach (var branchKey in flow.ExtensionKeys) { if (branchKey is string) { if (!codes.Remove(branchKey as string)) { //this eval is now not resolved as possible eval branch flow.RemoveExtension(branchKey); } } } int numberOfWarnings = 0; foreach (var sourceCode in codes) { try { var cfg = ControlFlowGraph.ControlFlowGraph.FromSource(sourceCode, flow.CurrentScript.FullName); var ppGraph = ProgramPointGraph.FromSource(cfg); flow.AddExtension(sourceCode, ppGraph, ExtensionType.ParallelEval); } catch (ControlFlowGraph.ControlFlowException) { numberOfWarnings++; AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Control flow graph creation error", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.CFG_EXCEPTION_IN_INCLUDE_OR_EVAL)); } catch (Parsers.ParserException) { numberOfWarnings++; AnalysisWarningHandler.SetWarning(flow.OutSet, new AnalysisWarning(flow.CurrentScript.FullName, "Parser error", flow.CurrentPartial, flow.CurrentProgramPoint, AnalysisWarningCause.PARSER_EXCEPTION_IN_INCLUDE_OR_EVAL)); } } if (numberOfWarnings > 0) { if (numberOfWarnings == codes.Count && isAllwasConcrete == true) { fatalError(flow, true); } else { fatalError(flow, false); } } }