public bool TryGetOrComputeResult( ImmutableArray <IOperation> operationBlocks, IMethodSymbol containingMethod, bool trackInstanceFields, out DataFlowAnalysisResult <DisposeBlockAnalysisResult, DisposeAbstractValue> disposeAnalysisResult, out DataFlowAnalysisResult <PointsToBlockAnalysisResult, PointsToAbstractValue> pointsToAnalysisResult, out ImmutableDictionary <IFieldSymbol, PointsToAbstractValue> trackedInstanceFieldPointsToMap) { foreach (var operationRoot in operationBlocks) { IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null) { var cfg = ControlFlowGraph.Create(topmostBlock); // Invoking an instance method may likely invalidate all the instance field analysis state, i.e. // reference type fields might be re-assigned to point to different objects in the called method. // An optimistic points to analysis assumes that the points to values of instance fields don't change on invoking an instance method. // A pessimistic points to analysis resets all the instance state and assumes the instance field might point to any object, hence has unknown state. // For dispose analysis, we want to perform an optimistic points to analysis as we assume a disposable field is not likely to be re-assigned to a separate object in helper method invocations in Dispose. pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, _wellKnownTypeProvider, pessimisticAnalysis: false); disposeAnalysisResult = DisposeAnalysis.GetOrComputeResult(cfg, containingMethod, _wellKnownTypeProvider, _disposeOwnershipTransferLikelyTypes, pointsToAnalysisResult, trackInstanceFields, out trackedInstanceFieldPointsToMap); return(true); } } disposeAnalysisResult = null; pointsToAnalysisResult = null; trackedInstanceFieldPointsToMap = null; return(false); }
private static TaintedDataAnalysisResult GetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol containingMethod, TaintedDataSymbolMap <SourceInfo> taintedSourceInfos, TaintedDataSymbolMap <SanitizerInfo> taintedSanitizerInfos, TaintedDataSymbolMap <SinkInfo> taintedSinkInfos, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig) { WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); PointsToAnalysisResult pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult( cfg, containingMethod, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis: true, performCopyAnalysis: false); TaintedDataAnalysisContext analysisContext = TaintedDataAnalysisContext.Create( TaintedDataAbstractValueDomain.Default, wellKnownTypeProvider, cfg, containingMethod, interproceduralAnalysisConfig, pessimisticAnalysis: false, pointsToAnalysisResult: pointsToAnalysisResult, getOrComputeAnalysisResult: GetOrComputeResultForAnalysisContext, taintedSourceInfos: taintedSourceInfos, taintedSanitizerInfos: taintedSanitizerInfos, taintedSinkInfos: taintedSinkInfos); return(GetOrComputeResultForAnalysisContext(analysisContext)); }
public void GeneratePTG(MethodDefinition method) { var methodInfo = programInfo.GetOrAdd(method); //GenerateIL(method); //GenerateTAC(method); //GenerateCFG(method); //GenerateWebs(method); GenerateSSA(method); if (!methodInfo.Contains("PTG_TEXT")) { var cfg = methodInfo.Get <ControlFlowGraph>("CFG"); // Points-to var pointsTo = new PointsToAnalysis(cfg, method); var result = pointsTo.Analyze(); var ptg = result[cfg.Exit.Id].Output; //ptg.RemoveVariablesExceptParameters(); //ptg.RemoveTemporalVariables(); var text = DGMLSerializer.Serialize(ptg); methodInfo.Set("PTG_TEXT", text); } }
private static bool ReportDiagnosticIfNecessary(OperationAnalysisContext operationContext, IOperation argumentValue, SyntaxNode syntax, ISymbol invokedSymbol, ISymbol containingMethod) { if (argumentValue.Type.SpecialType != SpecialType.System_String || !argumentValue.ConstantValue.HasValue) { // We have a candidate for diagnostic. perform more precise dataflow analysis. var topmostBlock = argumentValue.GetTopmostParentBlock(); if (topmostBlock != null) { var cfg = ControlFlowGraph.Create(topmostBlock); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationContext.Compilation); var copyAnalysisResult = CopyAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider); var nullAnalysisResult = NullAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider); var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, nullAnalysisResult); var stringContentResult = StringContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, nullAnalysisResult, pointsToAnalysisResult); StringContentAbstractValue value = stringContentResult[argumentValue]; if (value.NonLiteralState == StringContainsNonLiteralState.No) { // The value is a constant literal or default/unitialized, so avoid flagging this usage. return(false); } } // Review if the symbol passed to {invocation} in {method/field/constructor/etc} has user input. operationContext.ReportDiagnostic(syntax.CreateDiagnostic(Rule, invokedSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), containingMethod.Name)); return(true); } return(false); }
public static Set <string> ComputeAnalizableMethods(Node node, PointsToAnalysis ptwe) { AnalyzableMethodFinder amf = new AnalyzableMethodFinder(ptwe); amf.Visit(node); return(amf.analizableMethods); }
public MyCGGenerator(CallGraph cg, Method m, AnalyzableMethodFinder methodsFinder) { this.current = m; this.cg = cg; this.currentPTWE = methodsFinder.ptwe; this.methodsFinder = methodsFinder; }
// Constructor public PointsToAndWriteEffects(Method m, PointsToAnalysis pta) : base(m,pta) { this.writeEffects = new AbstractEffects(); this.allWriteEffects = new AbstractEffects(); this.readEffects = new AbstractEffects(); this.allReadEffects = new AbstractEffects(); this.callToNonAnalyzableMethods = new Dictionary<Label, Set<Method>>(); // this.nonNullState = null; }
public ConsistencyState(Method m, PointsToAnalysis pta) : base(m, pta) { consistency = new Dictionary <IPTAnalysisNode, AbstractValue>(); exposedNodes = new Set <IPTAnalysisNode>(); this.nonNullState = null; }
public static CallGraph ComputeAnalyzableMethods(Node node, PointsToAnalysis ptwe) { Set <AssemblyNode> assemblies = new Set <AssemblyNode>(); // AnalyzableMethodFinder amf = new AnalyzableMethodFinder(node,); AnalyzableMethodFinder amf = new AnalyzableMethodFinder(ptwe); if (node is AssemblyNode) { AssemblyNode assemblyNode = (AssemblyNode)node; amf.assemblies.Add(node); foreach (AssemblyReference reference in assemblyNode.AssemblyReferences) { amf.assemblies.Add(reference.Assembly); } } amf.Visit(node); /* * foreach (AssemblyNode an in amf.assemblies) * { * Console.Out.WriteLine("*ENTRE*"); * amf.Visit(an); * } */ // amf.Visit(node); if (PointsToAnalysis.verbose) { Set <CallGraph> cgs; cgs = new Set <CallGraph>(); cgs.Add(amf.cg); CallGraph.GenerateDotGraph(Console.Out, cgs); } return(amf.cg); }
public ConsistentyElementFactory(PointsToAnalysis pta) : base(pta) { }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze); context.RegisterCompilationStartAction(compilationContext => { if (!DisposeAnalysisHelper.TryGetOrCreate(compilationContext.Compilation, out DisposeAnalysisHelper? disposeAnalysisHelper)) { return; } var fieldDisposeValueMap = new ConcurrentDictionary <IFieldSymbol, /*disposed*/ bool>(); void addOrUpdateFieldDisposedValue(IFieldSymbol field, bool disposed) { Debug.Assert(!field.IsStatic); Debug.Assert(disposeAnalysisHelper !.IsDisposable(field.Type)); fieldDisposeValueMap.AddOrUpdate(field, addValue: disposed, updateValueFactory: (f, currentValue) => currentValue || disposed); }; var hasErrors = false; compilationContext.RegisterOperationAction(_ => hasErrors = true, OperationKind.Invalid); // Disposable fields with initializer at declaration must be disposed. compilationContext.RegisterOperationAction(operationContext => { if (!ShouldAnalyze(operationContext.ContainingSymbol.ContainingType)) { return; } var initializedFields = ((IFieldInitializerOperation)operationContext.Operation).InitializedFields; foreach (var field in initializedFields) { if (!field.IsStatic && disposeAnalysisHelper.GetDisposableFields(field.ContainingType).Contains(field)) { addOrUpdateFieldDisposedValue(field, disposed: false); } } }, OperationKind.FieldInitializer); // Instance fields initialized in constructor/method body with a locally created disposable object must be disposed. compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod) || !ShouldAnalyze(containingMethod.ContainingType)) { return; } if (disposeAnalysisHelper.HasAnyDisposableCreationDescendant(operationBlockStartContext.OperationBlocks, containingMethod)) { PointsToAnalysisResult?lazyPointsToAnalysisResult = null; operationBlockStartContext.RegisterOperationAction(operationContext => { var fieldReference = (IFieldReferenceOperation)operationContext.Operation; var field = fieldReference.Field; // Only track instance fields on the current instance. if (field.IsStatic || fieldReference.Instance?.Kind != OperationKind.InstanceReference) { return; } // Check if this is a Disposable field that is not currently being tracked. if (fieldDisposeValueMap.ContainsKey(field) || !disposeAnalysisHelper.GetDisposableFields(field.ContainingType).Contains(field)) { return; } // We have a field reference for a disposable field. // Check if it is being assigned a locally created disposable object. if (fieldReference.Parent is ISimpleAssignmentOperation simpleAssignmentOperation && simpleAssignmentOperation.Target == fieldReference) { if (lazyPointsToAnalysisResult == null) { var cfg = operationBlockStartContext.OperationBlocks.GetControlFlowGraph(); if (cfg == null) { hasErrors = true; return; } var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationContext.Compilation); var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( operationBlockStartContext.Options, Rule, InterproceduralAnalysisKind.None, operationBlockStartContext.CancellationToken); var pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult(cfg, containingMethod, operationBlockStartContext.Options, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis: false, performCopyAnalysis: false); if (pointsToAnalysisResult == null) { hasErrors = true; return; } Interlocked.CompareExchange(ref lazyPointsToAnalysisResult, pointsToAnalysisResult, null); } PointsToAbstractValue assignedPointsToValue = lazyPointsToAnalysisResult[simpleAssignmentOperation.Value.Kind, simpleAssignmentOperation.Value.Syntax]; foreach (var location in assignedPointsToValue.Locations) { if (disposeAnalysisHelper.IsDisposableCreationOrDisposeOwnershipTransfer(location, containingMethod)) { addOrUpdateFieldDisposedValue(field, disposed: false); break; } } } }, OperationKind.FieldReference); } // Mark fields disposed in Dispose method(s). if (IsDisposeMethod(containingMethod)) { var disposableFields = disposeAnalysisHelper.GetDisposableFields(containingMethod.ContainingType); if (!disposableFields.IsEmpty) { if (disposeAnalysisHelper.TryGetOrComputeResult(operationBlockStartContext.OperationBlocks, containingMethod, operationBlockStartContext.Options, Rule, trackInstanceFields: true, trackExceptionPaths: false, cancellationToken: operationBlockStartContext.CancellationToken, disposeAnalysisResult: out var disposeAnalysisResult, pointsToAnalysisResult: out var pointsToAnalysisResult)) { RoslynDebug.Assert(disposeAnalysisResult.TrackedInstanceFieldPointsToMap != null); BasicBlock exitBlock = disposeAnalysisResult.ControlFlowGraph.GetExit(); foreach (var fieldWithPointsToValue in disposeAnalysisResult.TrackedInstanceFieldPointsToMap) { IFieldSymbol field = fieldWithPointsToValue.Key; PointsToAbstractValue pointsToValue = fieldWithPointsToValue.Value; Debug.Assert(disposeAnalysisHelper.IsDisposable(field.Type)); ImmutableDictionary <AbstractLocation, DisposeAbstractValue> disposeDataAtExit = disposeAnalysisResult.ExitBlockOutput.Data; var disposed = false; foreach (var location in pointsToValue.Locations) { if (disposeDataAtExit.TryGetValue(location, out DisposeAbstractValue disposeValue)) { switch (disposeValue.Kind) { // For MaybeDisposed, conservatively mark the field as disposed as we don't support path sensitive analysis. case DisposeAbstractValueKind.MaybeDisposed: case DisposeAbstractValueKind.Unknown: case DisposeAbstractValueKind.Escaped: case DisposeAbstractValueKind.Disposed: disposed = true; addOrUpdateFieldDisposedValue(field, disposed); break; } } if (disposed) { break; } } } } } } }); compilationContext.RegisterCompilationEndAction(compilationEndContext => { if (hasErrors) { return; } foreach (var kvp in fieldDisposeValueMap) { IFieldSymbol field = kvp.Key; bool disposed = kvp.Value; // Flag non-disposed fields only if the containing type has a Dispose method implementation. if (!disposed && HasDisposeMethod(field.ContainingType)) { // '{0}' contains field '{1}' that is of IDisposable type '{2}', but it is never disposed. Change the Dispose method on '{0}' to call Close or Dispose on this field. var arg1 = field.ContainingType.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg2 = field.Name; var arg3 = field.Type.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var diagnostic = field.CreateDiagnostic(Rule, arg1, arg2, arg3); compilationEndContext.ReportDiagnostic(diagnostic); } } }); return; // Local functions bool ShouldAnalyze(INamedTypeSymbol namedType) { // We only want to analyze types which are disposable (implement System.IDisposable directly or indirectly) // and have at least one disposable field. return(!hasErrors && disposeAnalysisHelper !.IsDisposable(namedType) && !disposeAnalysisHelper.GetDisposableFields(namedType).IsEmpty&& !namedType.IsConfiguredToSkipAnalysis(compilationContext.Options, Rule, compilationContext.Compilation, compilationContext.CancellationToken)); } bool IsDisposeMethod(IMethodSymbol method) => disposeAnalysisHelper !.GetDisposeMethodKind(method) != DisposeMethodKind.None; bool HasDisposeMethod(INamedTypeSymbol namedType) { foreach (var method in namedType.GetMembers().OfType <IMethodSymbol>()) { if (IsDisposeMethod(method)) { return(true); } } return(false); } }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { INamedTypeSymbol localizableStateAttributeSymbol = WellKnownTypes.LocalizableAttribute(compilationContext.Compilation); INamedTypeSymbol conditionalAttributeSymbol = WellKnownTypes.ConditionalAttribute(compilationContext.Compilation); INamedTypeSymbol systemConsoleSymbol = WellKnownTypes.Console(compilationContext.Compilation); ImmutableHashSet <INamedTypeSymbol> typesToIgnore = GetTypesToIgnore(compilationContext.Compilation); compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod)) { return; } var lazyStringContentResult = new Lazy <DataFlowAnalysisResult <StringContentBlockAnalysisResult, StringContentAbstractValue> >( valueFactory: ComputeStringContentAnalysisResult, isThreadSafe: false); operationBlockStartContext.RegisterOperationAction(operationContext => { var argument = (IArgumentOperation)operationContext.Operation; switch (argument.Parent?.Kind) { case OperationKind.Invocation: case OperationKind.ObjectCreation: AnalyzeArgument(argument.Parameter, containingPropertySymbolOpt: null, operation: argument, reportDiagnostic: operationContext.ReportDiagnostic); return; } }, OperationKind.Argument); operationBlockStartContext.RegisterOperationAction(operationContext => { var propertyReference = (IPropertyReferenceOperation)operationContext.Operation; if (propertyReference.Parent is IAssignmentOperation assignment && assignment.Target == propertyReference && !propertyReference.Property.IsIndexer && propertyReference.Property.SetMethod?.Parameters.Length == 1) { IParameterSymbol valueSetterParam = propertyReference.Property.SetMethod.Parameters[0]; AnalyzeArgument(valueSetterParam, propertyReference.Property, assignment, operationContext.ReportDiagnostic); } }, OperationKind.PropertyReference); void AnalyzeArgument(IParameterSymbol parameter, IPropertySymbol containingPropertySymbolOpt, IOperation operation, Action <Diagnostic> reportDiagnostic) { if (ShouldBeLocalized(parameter, containingPropertySymbolOpt, localizableStateAttributeSymbol, conditionalAttributeSymbol, systemConsoleSymbol, typesToIgnore)) { StringContentAbstractValue stringContentValue = lazyStringContentResult.Value[operation]; if (stringContentValue.IsLiteralState) { Debug.Assert(stringContentValue.LiteralValues.Count > 0); // FxCop compat: Do not fire if the literal value came from a default parameter value if (stringContentValue.LiteralValues.Count == 1 && parameter.IsOptional && parameter.ExplicitDefaultValue is string defaultValue && defaultValue == stringContentValue.LiteralValues.Single()) { return; } // FxCop compat: Do not fire if none of the string literals have any non-control character. if (!LiteralValuesHaveNonControlCharacters(stringContentValue.LiteralValues)) { return; } // FxCop compat: Filter out xml string literals. var filteredStrings = stringContentValue.LiteralValues.Where(literal => !LooksLikeXmlTag(literal)); if (filteredStrings.Any()) { // Method '{0}' passes a literal string as parameter '{1}' of a call to '{2}'. Retrieve the following string(s) from a resource table instead: "{3}". var arg1 = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg2 = parameter.Name; var arg3 = parameter.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg4 = FormatLiteralValues(filteredStrings); var diagnostic = operation.CreateDiagnostic(Rule, arg1, arg2, arg3, arg4); reportDiagnostic(diagnostic); } } } } DataFlowAnalysisResult <StringContentBlockAnalysisResult, StringContentAbstractValue> ComputeStringContentAnalysisResult() { foreach (var operationRoot in operationBlockStartContext.OperationBlocks) { IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null) { var cfg = ControlFlowGraph.Create(topmostBlock); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationBlockStartContext.Compilation); var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider); var copyAnalysisResult = CopyAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, pointsToAnalysisResultOpt: pointsToAnalysisResult); // Do another analysis pass to improve the results from PointsTo and Copy analysis. pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, pointsToAnalysisResult, copyAnalysisResult); return(StringContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, pointsToAnalysisResult)); } } return(null); } }); }); }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { var iDisposable = WellKnownTypes.IDisposable(compilationContext.Compilation); if (iDisposable == null) { return; } var iCollection = WellKnownTypes.ICollection(compilationContext.Compilation); var genericICollection = WellKnownTypes.GenericICollection(compilationContext.Compilation); var disposeOwnershipTransferLikelyTypes = GetDisposeOwnershipTransferLikelyTypes(compilationContext.Compilation); compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { bool hasDisposableCreation = false; operationBlockStartContext.RegisterOperationAction(operationContext => { if (!hasDisposableCreation && operationContext.Operation.Type.IsDisposable(iDisposable)) { hasDisposableCreation = true; } }, OperationKind.ObjectCreation, OperationKind.TypeParameterObjectCreation, OperationKind.DynamicObjectCreation, OperationKind.Invocation); operationBlockStartContext.RegisterOperationBlockEndAction(operationBlockEndContext => { if (!hasDisposableCreation || !(operationBlockEndContext.OwningSymbol is IMethodSymbol containingMethod)) { return; } foreach (var operationRoot in operationBlockEndContext.OperationBlocks) { IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null) { var cfg = ControlFlowGraph.Create(topmostBlock); var nullAnalysisResult = NullAnalysis.GetOrComputeResult(cfg, containingMethod.ContainingType); var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod.ContainingType, nullAnalysisResult); var disposeAnalysisResult = DisposeAnalysis.GetOrComputeResult(cfg, iDisposable, iCollection, genericICollection, disposeOwnershipTransferLikelyTypes, containingMethod.ContainingType, pointsToAnalysisResult, nullAnalysisResult); ImmutableDictionary <AbstractLocation, DisposeAbstractValue> disposeDataAtExit = disposeAnalysisResult[cfg.Exit].InputData; foreach (var kvp in disposeDataAtExit) { AbstractLocation location = kvp.Key; DisposeAbstractValue disposeValue = kvp.Value; if (disposeValue.Kind == DisposeAbstractValueKind.NotDisposed || ((disposeValue.Kind == DisposeAbstractValueKind.Disposed || disposeValue.Kind == DisposeAbstractValueKind.MaybeDisposed) && disposeValue.DisposingOperations.Count > 0 && disposeValue.DisposingOperations.All(d => d.IsInsideCatchClause()))) { Debug.Assert(location.CreationOpt != null); // CA2000: In method '{0}', call System.IDisposable.Dispose on object created by '{1}' before all references to it are out of scope. var arg1 = containingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat); var arg2 = location.CreationOpt.Syntax.ToString(); var diagnostic = location.CreationOpt.Syntax.CreateDiagnostic(Rule, arg1, arg2); operationBlockEndContext.ReportDiagnostic(diagnostic); } } break; } } }); }); }); }
/// <summary> /// Analyzers should use <see cref="BatchGetOrComputeHazardousUsages"/> instead. Gets hazardous usages of an object based on a set of its properties. /// </summary> /// <param name="cfg">Control flow graph of the code.</param> /// <param name="compilation">Compilation containing the code.</param> /// <param name="owningSymbol">Symbol of the code to examine.</param> /// <param name="typeToTrackMetadataName">Name of the type to track.</param> /// <param name="constructorMapper">How constructor invocations map to <see cref="PropertySetAbstractValueKind"/>s.</param> /// <param name="propertyMappers">How property assignments map to <see cref="PropertySetAbstractValueKind"/>.</param> /// <param name="hazardousUsageEvaluators">When and how to evaluate <see cref="PropertySetAbstractValueKind"/>s to for hazardous usages.</param> /// <param name="interproceduralAnalysisConfig">Interprocedural dataflow analysis configuration.</param> /// <param name="pessimisticAnalysis">Whether to be pessimistic.</param> /// <returns>Property set analysis result.</returns> internal static PropertySetAnalysisResult GetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol owningSymbol, AnalyzerOptions analyzerOptions, string typeToTrackMetadataName, ConstructorMapper constructorMapper, PropertyMapperCollection propertyMappers, HazardousUsageEvaluatorCollection hazardousUsageEvaluators, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig, bool pessimisticAnalysis = false) { if (constructorMapper == null) { throw new ArgumentNullException(nameof(constructorMapper)); } if (propertyMappers == null) { throw new ArgumentNullException(nameof(propertyMappers)); } if (hazardousUsageEvaluators == null) { throw new ArgumentNullException(nameof(hazardousUsageEvaluators)); } constructorMapper.Validate(propertyMappers.PropertyValuesCount); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); PointsToAnalysisResult pointsToAnalysisResult; ValueContentAnalysisResult valueContentAnalysisResultOpt; if (!constructorMapper.RequiresValueContentAnalysis && !propertyMappers.RequiresValueContentAnalysis) { pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, interproceduralAnalysisPredicateOpt: null, pessimisticAnalysis, performCopyAnalysis: false); if (pointsToAnalysisResult == null) { return(null); } valueContentAnalysisResultOpt = null; } else { valueContentAnalysisResultOpt = ValueContentAnalysis.TryGetOrComputeResult( cfg, owningSymbol, analyzerOptions, wellKnownTypeProvider, interproceduralAnalysisConfig, out var copyAnalysisResult, out pointsToAnalysisResult, pessimisticAnalysis, performCopyAnalysis: false); if (valueContentAnalysisResultOpt == null) { return(null); } } var analysisContext = PropertySetAnalysisContext.Create( PropertySetAbstractValueDomain.Default, wellKnownTypeProvider, cfg, owningSymbol, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis, pointsToAnalysisResult, valueContentAnalysisResultOpt, TryGetOrComputeResultForAnalysisContext, typeToTrackMetadataName, constructorMapper, propertyMappers, hazardousUsageEvaluators); var result = TryGetOrComputeResultForAnalysisContext(analysisContext); return(result); }
/// <summary> /// Constructor /// </summary> /// <param name="t"></param> /// <param name="pta"></param> public PointsToInferer(TypeSystem t, PointsToAnalysis pta) { this.pointsToStateAnalysys = pta; typeSystem = t; iVisitor = GetInstructionVisitor(this); }
// Constructor public PointsToState(Method m, PointsToAnalysis pta) { this.pta = pta; this.pointsToGraph = new PTGraph(m); // this.callToNonAnalyzableMethods = new Dictionary<Label, Set<Method>>(); this.method = m; // this.exceptions = new Set<TypeNode>(); this.currentException = null; this.methodAssumptions = new Set<Method>(); this.isDefault = true; }
public MyCGGenerator(CallGraph cg, Method m, PointsToAnalysis currentPTWE) { this.current = m; this.cg = cg; this.currentPTWE = currentPTWE; }
public AnalyzableMethodFinder(PointsToAnalysis ptwe) { this.ptwe = ptwe; this.unitUnderAnalysis = ptwe.unitUnderAnalysis; cg = new CallGraph(); }
public ExposureElementFactory(PointsToAnalysis pta) : base(pta) { }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction(compilationContext => { compilationContext.RegisterOperationBlockStartAction(operationBlockStartContext => { if (!(operationBlockStartContext.OwningSymbol is IMethodSymbol containingMethod)) { return; } foreach (var operationRoot in operationBlockStartContext.OperationBlocks) { IBlockOperation topmostBlock = operationRoot.GetTopmostParentBlock(); if (topmostBlock != null && topmostBlock.HasAnyOperationDescendant(op => (op as IBinaryOperation)?.IsComparisonOperator() == true || op.Kind == OperationKind.Coalesce || op.Kind == OperationKind.ConditionalAccess)) { var cfg = ControlFlowGraph.Create(topmostBlock); var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(operationBlockStartContext.Compilation); var nullAnalysisResult = NullAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider); var pointsToAnalysisResult = PointsToAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, nullAnalysisResult); var copyAnalysisResult = CopyAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, nullAnalysisResultOpt: nullAnalysisResult, pointsToAnalysisResultOpt: pointsToAnalysisResult); // Do another null analysis pass to improve the results from PointsTo and Copy analysis. nullAnalysisResult = NullAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, pointsToAnalysisResultOpt: pointsToAnalysisResult); var stringContentAnalysisResult = StringContentAnalysis.GetOrComputeResult(cfg, containingMethod, wellKnownTypeProvider, copyAnalysisResult, nullAnalysisResult, pointsToAnalysisResult); operationBlockStartContext.RegisterOperationAction(operationContext => { PredicateValueKind GetPredicateKind(IBinaryOperation operation) { if (operation.IsComparisonOperator()) { PredicateValueKind binaryPredicateKind = nullAnalysisResult.GetPredicateKind(operation); if (binaryPredicateKind != PredicateValueKind.Unknown) { return(binaryPredicateKind); } binaryPredicateKind = copyAnalysisResult.GetPredicateKind(operation); if (binaryPredicateKind != PredicateValueKind.Unknown) { return(binaryPredicateKind); } binaryPredicateKind = stringContentAnalysisResult.GetPredicateKind(operation); if (binaryPredicateKind != PredicateValueKind.Unknown) { return(binaryPredicateKind); } ; } return(PredicateValueKind.Unknown); } var binaryOperation = (IBinaryOperation)operationContext.Operation; PredicateValueKind predicateKind = GetPredicateKind(binaryOperation); if (predicateKind != PredicateValueKind.Unknown && (!(binaryOperation.LeftOperand is IBinaryOperation leftBinary) || GetPredicateKind(leftBinary) == PredicateValueKind.Unknown) && (!(binaryOperation.RightOperand is IBinaryOperation rightBinary) || GetPredicateKind(rightBinary) == PredicateValueKind.Unknown)) { // '{0}' is always '{1}'. Remove or refactor the condition(s) to avoid dead code. var arg1 = binaryOperation.Syntax.ToString(); var arg2 = predicateKind == PredicateValueKind.AlwaysTrue ? (binaryOperation.Language == LanguageNames.VisualBasic ? "True" : "true") : (binaryOperation.Language == LanguageNames.VisualBasic ? "False" : "false"); var diagnostic = binaryOperation.CreateDiagnostic(AlwaysTrueFalseOrNullRule, arg1, arg2); operationContext.ReportDiagnostic(diagnostic); } }, OperationKind.BinaryOperator); operationBlockStartContext.RegisterOperationAction(operationContext => { IOperation nullCheckedOperation = operationContext.Operation.Kind == OperationKind.Coalesce ? ((ICoalesceOperation)operationContext.Operation).Value : ((IConditionalAccessOperation)operationContext.Operation).Operation; // '{0}' is always/never '{1}'. Remove or refactor the condition(s) to avoid dead code. DiagnosticDescriptor rule; switch (nullAnalysisResult[nullCheckedOperation]) { case NullAbstractValue.Null: rule = AlwaysTrueFalseOrNullRule; break; case NullAbstractValue.NotNull: rule = NeverNullRule; break; default: return; } var arg1 = nullCheckedOperation.Syntax.ToString(); var arg2 = nullCheckedOperation.Language == LanguageNames.VisualBasic ? "Nothing" : "null"; var diagnostic = nullCheckedOperation.CreateDiagnostic(rule, arg1, arg2); operationContext.ReportDiagnostic(diagnostic); }, OperationKind.Coalesce, OperationKind.ConditionalAccess); } } }); }); }
public Exposure(Method m, PointsToAnalysis pta) : base(m, pta) { //inconsistentExpr = new Dictionary<Label, Set<VariableEffect>>(); //problems = new Dictionary<Label, string>(); //callsToWarn = new Set<Label>(); }
public override void Initialize(AnalysisContext context) { if (!Debugger.IsAttached) // prefer single thread for debugging in development { context.EnableConcurrentExecution(); } if (context.IsAuditMode()) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); } else { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); } context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationContext) => { var config = Configuration.GetOrCreate(compilationContext); if (config.AuditMode) { TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = config.TaintConfiguration.GetSinkSymbolMap(this.SinkKind); if (sinkInfoSymbolMap.IsEmpty) { return; } Compilation compilation = compilationContext.Compilation; compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; AnalyzerOptions options = operationBlockStartContext.Options; CancellationToken cancellationToken = operationBlockStartContext.CancellationToken; if (options.IsConfiguredToSkipAnalysis(TaintedDataEnteringSinkDescriptor, owningSymbol, compilation, cancellationToken)) { return; } WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); void CreateWarning(OperationAnalysisContext operationAnalysisContext, Location location, ISymbol paramSymbol, ISymbol symbol) { // Something like: // CA3001: Potential SQL injection vulnerability was found where '{0}' in method '{1}' may be tainted by user-controlled data from '{2}' in method '{3}'. Diagnostic diagnostic = Diagnostic.Create( this.TaintedDataEnteringSinkDescriptor, location, additionalLocations: new Location[] { location }, messageArgs: new object[] { paramSymbol.Name, symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) }); operationAnalysisContext.ReportDiagnostic(diagnostic); } bool IsConstant(IOperation operation, IOperation value, OperationAnalysisContext operationAnalysisContext) { if (value.ConstantValue.HasValue || value is ITypeOfOperation) { return(true); } if (!operation.TryGetEnclosingControlFlowGraph(out var cfg)) { return(false); } var valueContentResult = ValueContentAnalysis.TryGetOrComputeResult(cfg, owningSymbol, wellKnownTypeProvider, operationAnalysisContext.Options, TaintedDataEnteringSinkDescriptor, PointsToAnalysisKind.Complete, operationAnalysisContext.CancellationToken); if (valueContentResult == null) { return(false); } ValueContentAbstractValue abstractValue = valueContentResult[value.Kind, value.Syntax]; return(abstractValue.NonLiteralState == ValueContainsNonLiteralState.No); } operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IAssignmentOperation operation = (IAssignmentOperation)operationAnalysisContext.Operation; if (!(operation.Target is IPropertyReferenceOperation propertyReferenceOperation)) { return; } IEnumerable <SinkInfo>?infosForType = sinkInfoSymbolMap.GetInfosForType(propertyReferenceOperation.Member.ContainingType); if (infosForType != null && infosForType.Any(x => x.SinkProperties.Contains(propertyReferenceOperation.Member.MetadataName)) && !IsConstant(operation, operation.Value, operationAnalysisContext)) { CreateWarning( operationAnalysisContext, propertyReferenceOperation.Syntax.GetLocation(), operation.Value.Type, propertyReferenceOperation.Member); } }, OperationKind.SimpleAssignment); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; IEnumerable <SinkInfo>?infosForType = sinkInfoSymbolMap.GetInfosForType(invocationOperation.TargetMethod.ContainingType); if (infosForType == null) { return; } foreach (SinkInfo sinkInfo in infosForType) { foreach (IArgumentOperation taintedArgument in invocationOperation.Arguments.Where(x => !IsConstant(x, x.Value, operationAnalysisContext))) { if (sinkInfo.SinkMethodParameters.TryGetValue(invocationOperation.TargetMethod.MetadataName, out ImmutableHashSet <string> sinkParameters) && sinkParameters.Contains(taintedArgument.Parameter.MetadataName)) { CreateWarning(operationAnalysisContext, invocationOperation.Syntax.GetLocation(), taintedArgument.Parameter, invocationOperation.TargetMethod); return; } } } }, OperationKind.Invocation); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IObjectCreationOperation invocationOperation = (IObjectCreationOperation)operationAnalysisContext.Operation; IEnumerable <SinkInfo>?infosForType = sinkInfoSymbolMap.GetInfosForType(invocationOperation.Constructor.ContainingType); if (infosForType == null) { return; } foreach (SinkInfo sinkInfo in infosForType) { foreach (IArgumentOperation taintedArgument in invocationOperation.Arguments.Where(x => !IsConstant(x, x.Value, operationAnalysisContext))) { if (sinkInfo.IsAnyStringParameterInConstructorASink && taintedArgument.Parameter.Type.SpecialType == SpecialType.System_String) { CreateWarning(operationAnalysisContext, invocationOperation.Syntax.GetLocation(), taintedArgument.Parameter, invocationOperation.Constructor); return; } else if (sinkInfo.SinkMethodParameters.TryGetValue(invocationOperation.Constructor.MetadataName, out ImmutableHashSet <string> sinkParameters) && sinkParameters.Contains(taintedArgument.Parameter.MetadataName)) { CreateWarning(operationAnalysisContext, invocationOperation.Syntax.GetLocation(), taintedArgument.Parameter, invocationOperation.Constructor); return; } } } }, OperationKind.ObjectCreation); }); } else { TaintedDataSymbolMap <SourceInfo> sourceInfoSymbolMap = config.TaintConfiguration.GetSourceSymbolMap(this.SinkKind); if (sourceInfoSymbolMap.IsEmpty) { return; } TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = config.TaintConfiguration.GetSinkSymbolMap(this.SinkKind); if (sinkInfoSymbolMap.IsEmpty) { return; } Compilation compilation = compilationContext.Compilation; compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; AnalyzerOptions options = operationBlockStartContext.Options; CancellationToken cancellationToken = operationBlockStartContext.CancellationToken; if (options.IsConfiguredToSkipAnalysis(TaintedDataEnteringSinkDescriptor, owningSymbol, compilation, cancellationToken)) { return; } WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); Lazy <ControlFlowGraph?> controlFlowGraphFactory = new Lazy <ControlFlowGraph?>( () => operationBlockStartContext.OperationBlocks.GetControlFlowGraph()); Lazy <PointsToAnalysisResult?> pointsToFactory = new Lazy <PointsToAnalysisResult?>( () => { if (controlFlowGraphFactory.Value == null) { return(null); } InterproceduralAnalysisConfiguration interproceduralAnalysisConfiguration = InterproceduralAnalysisConfiguration.Create( options, SupportedDiagnostics, controlFlowGraphFactory.Value, operationBlockStartContext.Compilation, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: cancellationToken, defaultMaxInterproceduralMethodCallChain: config.MaxInterproceduralMethodCallChain, defaultMaxInterproceduralLambdaOrLocalFunctionCallChain: config.MaxInterproceduralLambdaOrLocalFunctionCallChain); return(PointsToAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, owningSymbol, options, wellKnownTypeProvider, PointsToAnalysisKind.Complete, interproceduralAnalysisConfiguration, interproceduralAnalysisPredicate: null)); }); Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)> valueContentFactory = new Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)>( () => { if (controlFlowGraphFactory.Value == null) { return(null, null); } InterproceduralAnalysisConfiguration interproceduralAnalysisConfiguration = InterproceduralAnalysisConfiguration.Create( options, SupportedDiagnostics, controlFlowGraphFactory.Value, operationBlockStartContext.Compilation, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: cancellationToken, defaultMaxInterproceduralMethodCallChain: config.MaxInterproceduralMethodCallChain, defaultMaxInterproceduralLambdaOrLocalFunctionCallChain: config.MaxInterproceduralLambdaOrLocalFunctionCallChain); ValueContentAnalysisResult?valuecontentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, owningSymbol, options, wellKnownTypeProvider, PointsToAnalysisKind.Complete, interproceduralAnalysisConfiguration, out _, out PointsToAnalysisResult? p); return(p, valuecontentAnalysisResult); }); var rootOperationsNeedingAnalysis = PooledHashSet <IOperation> .GetInstance(); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IPropertyReferenceOperation propertyReferenceOperation = (IPropertyReferenceOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceProperty(propertyReferenceOperation.Property)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(propertyReferenceOperation.GetRoot()); } } }, OperationKind.PropertyReference); if (sourceInfoSymbolMap.RequiresFieldReferenceAnalysis) { operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IFieldReferenceOperation fieldReferenceOperation = (IFieldReferenceOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceField(fieldReferenceOperation.Field)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(fieldReferenceOperation.GetRoot()); } } }, OperationKind.FieldReference); } if (sourceInfoSymbolMap.RequiresParameterReferenceAnalysis) { operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IParameterReferenceOperation parameterReferenceOperation = (IParameterReferenceOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceParameter(parameterReferenceOperation.Parameter, wellKnownTypeProvider)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(parameterReferenceOperation.GetRoot()); } } }, OperationKind.ParameterReference); } operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceMethod( invocationOperation.TargetMethod, invocationOperation.Arguments, pointsToFactory, valueContentFactory, out _)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(invocationOperation.GetRoot()); } } }, OperationKind.Invocation); if (config.TaintConfiguration.HasTaintArraySource(SinkKind, config)) { operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IArrayInitializerOperation arrayInitializerOperation = (IArrayInitializerOperation)operationAnalysisContext.Operation; if (arrayInitializerOperation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation)?.Type is IArrayTypeSymbol arrayTypeSymbol && sourceInfoSymbolMap.IsSourceConstantArrayOfType(arrayTypeSymbol, arrayInitializerOperation)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } } }, OperationKind.ArrayInitializer); } operationBlockStartContext.RegisterOperationBlockEndAction( operationBlockAnalysisContext => { try { lock (rootOperationsNeedingAnalysis) { if (!rootOperationsNeedingAnalysis.Any()) { return; } if (controlFlowGraphFactory.Value == null) { return; } foreach (IOperation rootOperation in rootOperationsNeedingAnalysis) { TaintedDataAnalysisResult?taintedDataAnalysisResult = TaintedDataAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, operationBlockAnalysisContext.Compilation, operationBlockAnalysisContext.OwningSymbol, operationBlockAnalysisContext.Options, TaintedDataEnteringSinkDescriptor, sourceInfoSymbolMap, config.TaintConfiguration.GetSanitizerSymbolMap(this.SinkKind), sinkInfoSymbolMap, operationBlockAnalysisContext.CancellationToken, config.MaxInterproceduralMethodCallChain, config.MaxInterproceduralLambdaOrLocalFunctionCallChain); if (taintedDataAnalysisResult == null) { return; } foreach (TaintedDataSourceSink sourceSink in taintedDataAnalysisResult.TaintedDataSourceSinks) { if (!sourceSink.SinkKinds.Contains(this.SinkKind)) { continue; } foreach (SymbolAccess sourceOrigin in sourceSink.SourceOrigins) { // Something like: // CA3001: Potential SQL injection vulnerability was found where '{0}' in method '{1}' may be tainted by user-controlled data from '{2}' in method '{3}'. Diagnostic diagnostic = Diagnostic.Create( this.TaintedDataEnteringSinkDescriptor, sourceSink.Sink.Location, additionalLocations: new Location[] { sourceOrigin.Location }, messageArgs: new object[] { sourceSink.Sink.Symbol.Name, sourceSink.Sink.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) }); operationBlockAnalysisContext.ReportDiagnostic(diagnostic); } } } } } finally { rootOperationsNeedingAnalysis.Free(compilationContext.CancellationToken); } }); }); } }); }
// Copy Constructor public PointsToState(PointsToState cState) { this.pta = cState.pta; pointsToGraph = new PTGraph(cState.pointsToGraph); // callToNonAnalyzableMethods = new Dictionary<Label, Set<Method>>(cState.callToNonAnalyzableMethods); method = cState.method; methodLabel = cState.methodLabel; //exceptions = cState.exceptions; currentException = cState.currentException; methodAssumptions = cState.methodAssumptions; isDefault = cState.isDefault; }
//internal INonNullState nonNullstateForCurrentBlock; public ObjectConsistencyInferer(TypeSystem t, PointsToAnalysis pta) : base(t, pta) { }
public CGGenerator(CallGraph cg, AnalyzableMethodFinder amf) { this.cg = cg; this.ptwe = amf.ptwe; this.amf = amf; }
/// <summary> /// Constructor /// </summary> /// <param name="pta"></param> public PointsToInstructionVisitor(PointsToInferer pta) { this.pta = pta; PointsToAnalysis = this.pta.pointsToStateAnalysys; }
public WriteEffectsElementFactory(PointsToAnalysis pta) : base(pta) { }
public Exposure(Method m,PointsToAnalysis pta): base(m,pta) { //inconsistentExpr = new Dictionary<Label, Set<VariableEffect>>(); //problems = new Dictionary<Label, string>(); //callsToWarn = new Set<Label>(); }
public ElementFactory(PointsToAnalysis pta) { this.pta = pta; }
private static TaintedDataAnalysisResult?TryGetOrComputeResult( ControlFlowGraph cfg, Compilation compilation, ISymbol containingMethod, AnalyzerOptions analyzerOptions, TaintedDataSymbolMap <SourceInfo> taintedSourceInfos, TaintedDataSymbolMap <SanitizerInfo> taintedSanitizerInfos, TaintedDataSymbolMap <SinkInfo> taintedSinkInfos, InterproceduralAnalysisConfiguration interproceduralAnalysisConfig) { if (cfg == null) { Debug.Fail("Expected non-null CFG"); return(null); } WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); ValueContentAnalysisResult?valueContentAnalysisResult = null; CopyAnalysisResult? copyAnalysisResult = null; PointsToAnalysisResult? pointsToAnalysisResult = null; if (taintedSourceInfos.RequiresValueContentAnalysis || taintedSanitizerInfos.RequiresValueContentAnalysis || taintedSinkInfos.RequiresValueContentAnalysis) { valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( cfg, containingMethod, analyzerOptions, wellKnownTypeProvider, PointsToAnalysisKind.Complete, interproceduralAnalysisConfig, out copyAnalysisResult, out pointsToAnalysisResult, pessimisticAnalysis: true, performCopyAnalysis: false); if (valueContentAnalysisResult == null) { return(null); } } else { pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( cfg, containingMethod, analyzerOptions, wellKnownTypeProvider, PointsToAnalysisKind.Complete, interproceduralAnalysisConfig, interproceduralAnalysisPredicate: null, pessimisticAnalysis: true, performCopyAnalysis: false); if (pointsToAnalysisResult == null) { return(null); } } TaintedDataAnalysisContext analysisContext = TaintedDataAnalysisContext.Create( TaintedDataAbstractValueDomain.Default, wellKnownTypeProvider, cfg, containingMethod, analyzerOptions, interproceduralAnalysisConfig, pessimisticAnalysis: false, copyAnalysisResult: copyAnalysisResult, pointsToAnalysisResult: pointsToAnalysisResult, valueContentAnalysisResult: valueContentAnalysisResult, tryGetOrComputeAnalysisResult: TryGetOrComputeResultForAnalysisContext, taintedSourceInfos: taintedSourceInfos, taintedSanitizerInfos: taintedSanitizerInfos, taintedSinkInfos: taintedSinkInfos); return(TryGetOrComputeResultForAnalysisContext(analysisContext)); }
public CGGenerator(CallGraph cg, PointsToAnalysis ptwe) { this.cg = cg; this.ptwe = ptwe; }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationContext) => { TaintedDataConfig taintedDataConfig = TaintedDataConfig.GetOrCreate(compilationContext.Compilation); TaintedDataSymbolMap <SourceInfo> sourceInfoSymbolMap = taintedDataConfig.GetSourceSymbolMap(this.SinkKind); if (sourceInfoSymbolMap.IsEmpty) { return; } TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = taintedDataConfig.GetSinkSymbolMap(this.SinkKind); if (sinkInfoSymbolMap.IsEmpty) { return; } compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; if (owningSymbol.IsConfiguredToSkipAnalysis(operationBlockStartContext.Options, TaintedDataEnteringSinkDescriptor, operationBlockStartContext.Compilation, operationBlockStartContext.CancellationToken)) { return; } PooledHashSet <IOperation> rootOperationsNeedingAnalysis = PooledHashSet <IOperation> .GetInstance(); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IPropertyReferenceOperation propertyReferenceOperation = (IPropertyReferenceOperation)operationAnalysisContext.Operation; IOperation rootOperation = operationAnalysisContext.Operation.GetRoot(); if (sourceInfoSymbolMap.IsSourceProperty(propertyReferenceOperation.Property)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(rootOperation); } } }, OperationKind.PropertyReference); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; IOperation rootOperation = operationAnalysisContext.Operation.GetRoot(); PooledDictionary <PointsToCheck, ImmutableHashSet <string> > evaluateWithPointsToAnalysis = null; PooledDictionary <ValueContentCheck, ImmutableHashSet <string> > evaluateWithValueContentAnalysis = null; PointsToAnalysisResult pointsToAnalysisResult = null; ValueContentAnalysisResult valueContentAnalysisResult = null; if (rootOperation.TryGetEnclosingControlFlowGraph(out ControlFlowGraph cfg)) { pointsToAnalysisResult = PointsToAnalysis.TryGetOrComputeResult( cfg, owningSymbol, operationAnalysisContext.Options, WellKnownTypeProvider.GetOrCreate(operationAnalysisContext.Compilation), InterproceduralAnalysisConfiguration.Create( operationAnalysisContext.Options, SupportedDiagnostics, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: operationAnalysisContext.CancellationToken), interproceduralAnalysisPredicateOpt: null); if (pointsToAnalysisResult == null) { return; } } if (sourceInfoSymbolMap.RequiresValueContentAnalysis) { valueContentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( cfg, owningSymbol, operationAnalysisContext.Options, WellKnownTypeProvider.GetOrCreate(operationAnalysisContext.Compilation), InterproceduralAnalysisConfiguration.Create( operationAnalysisContext.Options, SupportedDiagnostics, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive, cancellationToken: operationAnalysisContext.CancellationToken), out var copyAnalysisResult, out pointsToAnalysisResult); if (valueContentAnalysisResult == null) { return; } } try { if (sourceInfoSymbolMap.IsSourceMethod( invocationOperation.TargetMethod, invocationOperation.Arguments, invocationOperation.Arguments.Select(o => pointsToAnalysisResult[o.Kind, o.Syntax]).ToImmutableArray(), invocationOperation.Arguments.Select(o => valueContentAnalysisResult[o.Kind, o.Syntax]).ToImmutableArray(), out _)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(rootOperation); } } } finally { evaluateWithPointsToAnalysis?.Free(); evaluateWithValueContentAnalysis?.Free(); } }, OperationKind.Invocation); if (taintedDataConfig.HasTaintArraySource(SinkKind)) { operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IArrayInitializerOperation arrayInitializerOperation = (IArrayInitializerOperation)operationAnalysisContext.Operation; if (arrayInitializerOperation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation)?.Type is IArrayTypeSymbol arrayTypeSymbol && sourceInfoSymbolMap.IsSourceConstantArrayOfType(arrayTypeSymbol)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } } }, OperationKind.ArrayInitializer); } operationBlockStartContext.RegisterOperationBlockEndAction( operationBlockAnalysisContext => { try { lock (rootOperationsNeedingAnalysis) { if (!rootOperationsNeedingAnalysis.Any()) { return; } foreach (IOperation rootOperation in rootOperationsNeedingAnalysis) { if (!rootOperation.TryGetEnclosingControlFlowGraph(out var cfg)) { continue; } TaintedDataAnalysisResult taintedDataAnalysisResult = TaintedDataAnalysis.TryGetOrComputeResult( cfg, operationBlockAnalysisContext.Compilation, operationBlockAnalysisContext.OwningSymbol, operationBlockAnalysisContext.Options, TaintedDataEnteringSinkDescriptor, sourceInfoSymbolMap, taintedDataConfig.GetSanitizerSymbolMap(this.SinkKind), sinkInfoSymbolMap, operationBlockAnalysisContext.CancellationToken); if (taintedDataAnalysisResult == null) { return; } foreach (TaintedDataSourceSink sourceSink in taintedDataAnalysisResult.TaintedDataSourceSinks) { if (!sourceSink.SinkKinds.Contains(this.SinkKind)) { continue; } foreach (SymbolAccess sourceOrigin in sourceSink.SourceOrigins) { // Something like: // CA3001: Potential SQL injection vulnerability was found where '{0}' in method '{1}' may be tainted by user-controlled data from '{2}' in method '{3}'. Diagnostic diagnostic = Diagnostic.Create( this.TaintedDataEnteringSinkDescriptor, sourceSink.Sink.Location, additionalLocations: new Location[] { sourceOrigin.Location }, messageArgs: new object[] { sourceSink.Sink.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceSink.Sink.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) }); operationBlockAnalysisContext.ReportDiagnostic(diagnostic); } } } } } finally { rootOperationsNeedingAnalysis.Free(); } }); }); }); }
public ConsistencyState(Method m, PointsToAnalysis pta) : base(m,pta) { consistency = new Dictionary<IPTAnalysisNode, AbstractValue>(); exposedNodes = new Set<IPTAnalysisNode>(); this.nonNullState = null; }
public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationContext) => { Compilation compilation = compilationContext.Compilation; TaintedDataConfig taintedDataConfig = TaintedDataConfig.GetOrCreate(compilation); TaintedDataSymbolMap <SourceInfo> sourceInfoSymbolMap = taintedDataConfig.GetSourceSymbolMap(this.SinkKind); if (sourceInfoSymbolMap.IsEmpty) { return; } TaintedDataSymbolMap <SinkInfo> sinkInfoSymbolMap = taintedDataConfig.GetSinkSymbolMap(this.SinkKind); if (sinkInfoSymbolMap.IsEmpty) { return; } compilationContext.RegisterOperationBlockStartAction( operationBlockStartContext => { ISymbol owningSymbol = operationBlockStartContext.OwningSymbol; AnalyzerOptions options = operationBlockStartContext.Options; CancellationToken cancellationToken = operationBlockStartContext.CancellationToken; if (options.IsConfiguredToSkipAnalysis(TaintedDataEnteringSinkDescriptor, owningSymbol, compilation)) { return; } WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); Lazy <ControlFlowGraph?> controlFlowGraphFactory = new Lazy <ControlFlowGraph?>( () => operationBlockStartContext.OperationBlocks.GetControlFlowGraph()); Lazy <PointsToAnalysisResult?> pointsToFactory = new Lazy <PointsToAnalysisResult?>( () => { if (controlFlowGraphFactory.Value == null) { return(null); } InterproceduralAnalysisConfiguration interproceduralAnalysisConfiguration = InterproceduralAnalysisConfiguration.Create( options, SupportedDiagnostics, controlFlowGraphFactory.Value, operationBlockStartContext.Compilation, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive); return(PointsToAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, owningSymbol, options, wellKnownTypeProvider, PointsToAnalysisKind.Complete, interproceduralAnalysisConfiguration, interproceduralAnalysisPredicate: null)); }); Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)> valueContentFactory = new Lazy <(PointsToAnalysisResult?, ValueContentAnalysisResult?)>( () => { if (controlFlowGraphFactory.Value == null) { return(null, null); } InterproceduralAnalysisConfiguration interproceduralAnalysisConfiguration = InterproceduralAnalysisConfiguration.Create( options, SupportedDiagnostics, controlFlowGraphFactory.Value, operationBlockStartContext.Compilation, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.ContextSensitive); ValueContentAnalysisResult?valuecontentAnalysisResult = ValueContentAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, owningSymbol, options, wellKnownTypeProvider, PointsToAnalysisKind.Complete, interproceduralAnalysisConfiguration, out _, out PointsToAnalysisResult? p); return(p, valuecontentAnalysisResult); }); PooledHashSet <IOperation> rootOperationsNeedingAnalysis = PooledHashSet <IOperation> .GetInstance(); operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IPropertyReferenceOperation propertyReferenceOperation = (IPropertyReferenceOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceProperty(propertyReferenceOperation.Property)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(propertyReferenceOperation.GetRoot()); } } }, OperationKind.PropertyReference); if (sourceInfoSymbolMap.RequiresParameterReferenceAnalysis) { operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IParameterReferenceOperation parameterReferenceOperation = (IParameterReferenceOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceParameter(parameterReferenceOperation.Parameter, wellKnownTypeProvider)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(parameterReferenceOperation.GetRoot()); } } }, OperationKind.ParameterReference); } operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; if (sourceInfoSymbolMap.IsSourceMethod( invocationOperation.TargetMethod, invocationOperation.Arguments, pointsToFactory, valueContentFactory, out _)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(invocationOperation.GetRoot()); } } }, OperationKind.Invocation); if (TaintedDataConfig.HasTaintArraySource(SinkKind)) { operationBlockStartContext.RegisterOperationAction( operationAnalysisContext => { IArrayInitializerOperation arrayInitializerOperation = (IArrayInitializerOperation)operationAnalysisContext.Operation; if (arrayInitializerOperation.GetAncestor <IArrayCreationOperation>(OperationKind.ArrayCreation)?.Type is IArrayTypeSymbol arrayTypeSymbol && sourceInfoSymbolMap.IsSourceConstantArrayOfType(arrayTypeSymbol, arrayInitializerOperation)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } } }, OperationKind.ArrayInitializer); } operationBlockStartContext.RegisterOperationBlockEndAction( operationBlockAnalysisContext => { try { lock (rootOperationsNeedingAnalysis) { if (!rootOperationsNeedingAnalysis.Any()) { return; } if (controlFlowGraphFactory.Value == null) { return; } foreach (IOperation rootOperation in rootOperationsNeedingAnalysis) { TaintedDataAnalysisResult?taintedDataAnalysisResult = TaintedDataAnalysis.TryGetOrComputeResult( controlFlowGraphFactory.Value, operationBlockAnalysisContext.Compilation, operationBlockAnalysisContext.OwningSymbol, operationBlockAnalysisContext.Options, TaintedDataEnteringSinkDescriptor, sourceInfoSymbolMap, taintedDataConfig.GetSanitizerSymbolMap(this.SinkKind), sinkInfoSymbolMap); if (taintedDataAnalysisResult == null) { return; } foreach (TaintedDataSourceSink sourceSink in taintedDataAnalysisResult.TaintedDataSourceSinks) { if (!sourceSink.SinkKinds.Contains(this.SinkKind)) { continue; } foreach (SymbolAccess sourceOrigin in sourceSink.SourceOrigins) { // Something like: // CA3001: Potential SQL injection vulnerability was found where '{0}' in method '{1}' may be tainted by user-controlled data from '{2}' in method '{3}'. Diagnostic diagnostic = Diagnostic.Create( this.TaintedDataEnteringSinkDescriptor, sourceSink.Sink.Location, additionalLocations: new Location[] { sourceOrigin.Location }, messageArgs: new object[] { sourceSink.Sink.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceSink.Sink.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.Symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat), sourceOrigin.AccessingMethod.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat) }); operationBlockAnalysisContext.ReportDiagnostic(diagnostic); } } } } } finally { rootOperationsNeedingAnalysis.Free(compilationContext.CancellationToken); } }); }); }); }