protected override void Free() { _labelsDefined.Free(); _labelsUsed.Free(); _usingDeclarations.Free(); base.Free(); }
protected bool _convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = false; // By default, just let the original exception to bubble up. protected override void Free() { _labelsDefined.Free(); _labelsUsed.Free(); base.Free(); }
public void Free() { MethodsConvertedToDelegates.Free(); ScopesThatCantBeStructs.Free(); NeedsParentFrame.Free(); ScopeTree.Free(); }
public void Free() { foreach (var item in ThrowLocations) { item.Value.Free(); } ThrowLocations.Free(); CatchBlockUsed.Free(); }
private void ExecuteCodeBlockActions(PooledHashSet <CodeBlockAnalyzerAction> blockActions, SyntaxNode declaredNode, ISymbol declaredSymbol, SemanticModel semanticModel) { foreach (var blockAction in blockActions) { ExecuteAndCatchIfThrows(blockAction.Analyzer, () => blockAction.Action(new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, _analyzerOptions, _addDiagnostic, d => IsSupportedDiagnostic(blockAction.Analyzer, d), _cancellationToken))); } blockActions.Free(); }
private static void SetKnownToHaveNoDeclaredBaseCycles(ref PooledHashSet <NamedTypeSymbol> visited) { if (visited != null) { foreach (var v in visited) { v.SetKnownToHaveNoDeclaredBaseCycles(); } visited.Free(); visited = null; } }
public ImmutableArray <S> SelectDistinct <S>(Func <T, S> selector) { ArrayBuilder <S> result = ArrayBuilder <S> .GetInstance(Count); PooledHashSet <S> set = PooledHashSet <S> .GetInstance(); foreach (T item in this) { S selected = selector(item); if (set.Add(selected)) { result.Add(selected); } } set.Free(); return(result.ToImmutableAndFree()); }
public void RemoveDuplicates() { PooledHashSet <T> set = PooledHashSet <T> .GetInstance(); int j = 0; for (int i = 0; i < Count; i++) { if (set.Add(this[i])) { this[j] = this[i]; j++; } } Clip(j); set.Free(); }
private static ISet <string> GetLanguageCodesForSupportedCountries( IEnumerable <string> countries) { PooledHashSet <string> instance = PooledHashSet <string> .GetInstance(); try { foreach (string country in countries) { instance.UnionWith(EmailAndPhoneNoMustNotBePresentInTheSource.GetSupportedLocales(country)); } return((ISet <string>)instance.ToImmutableHashSet <string>()); } finally { instance.Free(); } }
// Determine if "type" inherits from "baseType", ignoring constructed types, and dealing // only with original types. private static bool InheritsFromIgnoringConstruction( this TypeSymbol type, NamedTypeSymbol baseType, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <Symbol> basesBeingResolved = null) { Debug.Assert(type.IsDefinition); Debug.Assert(baseType.IsDefinition); PooledHashSet <NamedTypeSymbol> visited = null; var current = type; bool result = false; while ((object)current != null) { if (current.Equals(baseType)) { result = true; break; } // NOTE(cyrusn): The base type of an 'original' type may not be 'original'. i.e. // "class Foo : IBar<int>". We must map it back to the 'original' when as we walk up // the base type hierarchy. var next = current.GetNextBaseTypeNoUseSiteDiagnostics(basesBeingResolved, compilation, ref visited); if ((object)next == null) { current = null; } else { current = (TypeSymbol)next.OriginalDefinition; current.AddUseSiteDiagnostics(ref useSiteDiagnostics); } } if (visited != null) { visited.Free(); } return(result); }
private void ReportInitializedNotUsedNotInitializedUsedLocalVars( CodeBlockAnalysisContext context) { PooledHashSet <IdentifierNameSyntax> instance1 = PooledHashSet <IdentifierNameSyntax> .GetInstance(); PooledHashSet <IdentifierNameSyntax> instance2 = PooledHashSet <IdentifierNameSyntax> .GetInstance(); try { this.CollectInitializedNotUsedNotInitializedUsedLocalVars((HashSet <IdentifierNameSyntax>)instance1, (HashSet <IdentifierNameSyntax>)instance2); VariableInitializationUsageAnalyzer.ReportInitializedNotUsedVariables(new Action <Diagnostic>(context.ReportDiagnostic), instance1); VariableInitializationUsageAnalyzer.ReportNotInitializedVariables(new Action <Diagnostic>(context.ReportDiagnostic), instance2); } finally { instance1.Free(); instance2.Free(); } }
private void ExecuteCodeBlockActions( PooledHashSet <CodeBlockAnalyzerAction> blockActions, SyntaxNode declaredNode, ISymbol declaredSymbol, SemanticModel semanticModel, Action <Diagnostic> addDiagnostic, CodeBlockAnalyzerStateData analyzerStateOpt) { foreach (var blockAction in blockActions) { if (ShouldExecuteAction(analyzerStateOpt, blockAction)) { ExecuteAndCatchIfThrows(blockAction.Analyzer, () => blockAction.Action(new CodeBlockAnalysisContext(declaredNode, declaredSymbol, semanticModel, _analyzerOptions, addDiagnostic, d => IsSupportedDiagnostic(blockAction.Analyzer, d), _cancellationToken))); analyzerStateOpt?.ProcessedActions.Add(blockAction); } } blockActions.Free(); }
private static void ReportInitializedNotUsedNotInitializedUsedVars( SyntaxNodeAnalysisContext context, Dictionary <string, IdentifierNameSyntax> firstGlobalVarInitializerSyntax, Dictionary <string, IdentifierNameSyntax> firstGlobalVarUsageSyntax, Dictionary <string, VariableDeclarationBaseSyntax> globalVariables) { PooledHashSet <IdentifierNameSyntax> instance1 = PooledHashSet <IdentifierNameSyntax> .GetInstance(); PooledHashSet <IdentifierNameSyntax> instance2 = PooledHashSet <IdentifierNameSyntax> .GetInstance(); try { VariableInitializationUsageAnalyzer.CollectInitializedNotUsedNotInitializedUsedGlobalVars((HashSet <IdentifierNameSyntax>)instance2, (HashSet <IdentifierNameSyntax>)instance1, firstGlobalVarInitializerSyntax, firstGlobalVarUsageSyntax, globalVariables); VariableInitializationUsageAnalyzer.ReportInitializedNotUsedVariables(new Action <Diagnostic>(context.ReportDiagnostic), instance1); VariableInitializationUsageAnalyzer.ReportNotInitializedVariables(new Action <Diagnostic>(context.ReportDiagnostic), instance2); } finally { instance1.Free(); instance2.Free(); } }
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); } }); }); }); }
public void Free() { DeclaredLocals.Free(); }
/// <summary> /// Determine if "type" inherits from or implements "baseType", ignoring constructed types, and dealing /// only with original types. /// </summary> private static bool InheritsFromOrImplementsIgnoringConstruction( this TypeSymbol type, NamedTypeSymbol baseType, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics, ConsList <TypeSymbol> basesBeingResolved = null) { Debug.Assert(type.IsDefinition); Debug.Assert(baseType.IsDefinition); PooledHashSet <NamedTypeSymbol> interfacesLookedAt = null; ArrayBuilder <NamedTypeSymbol> baseInterfaces = null; bool baseTypeIsInterface = baseType.IsInterface; if (baseTypeIsInterface) { interfacesLookedAt = PooledHashSet <NamedTypeSymbol> .GetInstance(); baseInterfaces = ArrayBuilder <NamedTypeSymbol> .GetInstance(); } PooledHashSet <NamedTypeSymbol> visited = null; var current = type; bool result = false; while ((object)current != null) { Debug.Assert(current.IsDefinition); if (baseTypeIsInterface == current.IsInterfaceType() && current == (object)baseType) { result = true; break; } if (baseTypeIsInterface) { getBaseInterfaces(current, baseInterfaces, interfacesLookedAt, basesBeingResolved); } // NOTE(cyrusn): The base type of an 'original' type may not be 'original'. i.e. // "class Goo : IBar<int>". We must map it back to the 'original' when as we walk up // the base type hierarchy. var next = current.GetNextBaseTypeNoUseSiteDiagnostics(basesBeingResolved, compilation, ref visited); if ((object)next == null) { current = null; } else { current = (TypeSymbol)next.OriginalDefinition; current.AddUseSiteDiagnostics(ref useSiteDiagnostics); } } visited?.Free(); if (!result && baseTypeIsInterface) { Debug.Assert(!result); while (baseInterfaces.Count != 0) { NamedTypeSymbol currentBase = baseInterfaces.Pop(); if (!currentBase.IsInterface) { continue; } Debug.Assert(currentBase.IsDefinition); if (currentBase == (object)baseType) { result = true; break; } getBaseInterfaces(currentBase, baseInterfaces, interfacesLookedAt, basesBeingResolved); } if (!result) { foreach (var candidate in interfacesLookedAt) { candidate.AddUseSiteDiagnostics(ref useSiteDiagnostics); } } } interfacesLookedAt?.Free(); baseInterfaces?.Free(); return(result);
private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalidOperation) { // We bail out reporting diagnostics for named types which have any invalid operations, i.e. erroneous code. // We do so to ensure that we don't report false positives during editing scenarios in the IDE, where the user // is still editing code and fixing unresolved references to symbols, such as overload resolution errors. if (hasInvalidOperation) { return; } // Report diagnostics for unused candidate members. var first = true; PooledHashSet <ISymbol> symbolsReferencedInDocComments = null; try { var namedType = (INamedTypeSymbol)symbolEndContext.Symbol; foreach (var member in namedType.GetMembers()) { // Check if the underlying member is neither read nor a readable reference to the member is taken. // If so, we flag the member as either unused (never written) or unread (written but not read). if (TryRemove(member, out var valueUsageInfo) && !valueUsageInfo.ContainsReadOrReadableRef()) { Debug.Assert(IsCandidateSymbol(member)); Debug.Assert(!member.IsImplicitlyDeclared); if (first) { // Bail out if there are syntax errors in any of the declarations of the containing type. // Note that we check this only for the first time that we report an unused or unread member for the containing type. if (HasSyntaxErrors(namedType, symbolEndContext.CancellationToken)) { return; } // Compute the set of candidate symbols referenced in all the documentation comments within the named type declarations. // This set is computed once and used for all the iterations of the loop. symbolsReferencedInDocComments = GetCandidateSymbolsReferencedInDocComments(namedType, symbolEndContext.Compilation, symbolEndContext.CancellationToken); first = false; } // Report IDE0051 or IDE0052 based on whether the underlying member has any Write/WritableRef/NonReadWriteRef references or not. var rule = !valueUsageInfo.ContainsWriteOrWritableRef() && !valueUsageInfo.ContainsNonReadWriteRef() && !symbolsReferencedInDocComments.Contains(member) ? s_removeUnusedMembersWithFadingRule : s_removeUnreadMembersWithFadingRule; var effectiveSeverity = rule.GetEffectiveSeverity(symbolEndContext.Compilation.Options); // Most of the members should have a single location, except for partial methods. // We report the diagnostic on the first location of the member. var diagnostic = DiagnosticHelper.Create( rule, member.Locations[0], effectiveSeverity, additionalLocations: null, properties: null, member.ContainingType.Name, member.Name); symbolEndContext.ReportDiagnostic(diagnostic); } } } finally { symbolsReferencedInDocComments?.Free(); } return; }
private static void AnalyzeSymbols(SymbolAnalysisContext ctx) { PooledHashSet <ISymbol> instance1 = PooledHashSet <ISymbol> .GetInstance(); PooledHashSet <ISymbol> instance2 = PooledHashSet <ISymbol> .GetInstance(); PooledHashSet <ISymbol> instance3 = PooledHashSet <ISymbol> .GetInstance(); PooledHashSet <ISymbol> instance4 = PooledHashSet <ISymbol> .GetInstance(); PooledHashSet <ISymbol> instance5 = PooledHashSet <ISymbol> .GetInstance(); PooledHashSet <ISymbol> instance6 = PooledHashSet <ISymbol> .GetInstance(); ImmutableArray <ISymbol> members = ((IContainerSymbol)ctx.Symbol).GetMembers(); try { ImmutableArray <ISymbol> .Enumerator enumerator1 = members.GetEnumerator(); while (enumerator1.MoveNext()) { ISymbol current1 = enumerator1.Current; switch (current1.Kind) { case SymbolKind.GlobalVariable: instance1.ConcurrentAdd <ISymbol>(current1); continue; case SymbolKind.Method: instance2.ConcurrentAdd <ISymbol>(current1); foreach (IVariableSymbol localVariable in ((IMethodSymbol)current1).LocalVariables) { instance3.ConcurrentAdd <ISymbol>((ISymbol)localVariable); } continue; case SymbolKind.Field: instance4.ConcurrentAdd <ISymbol>(current1); continue; case SymbolKind.Control: Rule198GlobalLocalVariablesShouldNotHaveSameName.AnalyzeControls((IControlSymbol)current1, instance6); continue; case SymbolKind.Action: Rule198GlobalLocalVariablesShouldNotHaveSameName.AnalyzeActions((IActionSymbol)current1, instance5); continue; case SymbolKind.Change: IEnumerable <IControlSymbol> flattenedSymbolsOfKind1 = Rule198GlobalLocalVariablesShouldNotHaveSameName.GetFlattenedSymbolsOfKind <IControlSymbol>((IContainerSymbol)current1, SymbolKind.Control); IEnumerable <IActionSymbol> flattenedSymbolsOfKind2 = Rule198GlobalLocalVariablesShouldNotHaveSameName.GetFlattenedSymbolsOfKind <IActionSymbol>((IContainerSymbol)current1, SymbolKind.Action); foreach (IControlSymbol controlSymbol in flattenedSymbolsOfKind1) { instance6.ConcurrentAdd <ISymbol>((ISymbol)controlSymbol); } using (IEnumerator <IActionSymbol> enumerator2 = flattenedSymbolsOfKind2.GetEnumerator()) { while (enumerator2.MoveNext()) { IActionSymbol current2 = enumerator2.Current; instance5.ConcurrentAdd <ISymbol>((ISymbol)current2); } continue; } case SymbolKind.QueryDataItem: foreach (IQueryColumnSymbol flattenedQueryColumn in ((IQueryDataItemSymbol)current1).FlattenedQueryColumns) { if (flattenedQueryColumn.Kind == SymbolKind.QueryColumn) { instance4.ConcurrentAdd <ISymbol>((ISymbol)flattenedQueryColumn); } } continue; case SymbolKind.RequestPage: foreach (IControlSymbol flattenedControl in ((IPageBaseTypeSymbol)current1).FlattenedControls) { Rule198GlobalLocalVariablesShouldNotHaveSameName.AnalyzeControls(flattenedControl, instance4); } foreach (IActionSymbol flattenedAction in ((IPageBaseTypeSymbol)current1).FlattenedActions) { instance5.ConcurrentAdd <ISymbol>((ISymbol)flattenedAction); } continue; case SymbolKind.XmlPortNode: Rule198GlobalLocalVariablesShouldNotHaveSameName.AnalyzeXmlNode((IXmlPortNodeSymbol)current1, instance4); continue; default: continue; } } ImmutableHashSet <ISymbol> immutableHashSet1 = instance1.ToImmutableHashSet <ISymbol>((IEqualityComparer <ISymbol>)SemanticFacts.SymbolNameEqualityComparer); ImmutableHashSet <ISymbol> immutableHashSet2 = instance2.ToImmutableHashSet <ISymbol>((IEqualityComparer <ISymbol>)SemanticFacts.SymbolNameEqualityComparer); ImmutableHashSet <ISymbol> immutableHashSet3 = instance3.ToImmutableHashSet <ISymbol>(); ImmutableHashSet <ISymbol> immutableHashSet4 = instance4.ToImmutableHashSet <ISymbol>((IEqualityComparer <ISymbol>)SemanticFacts.SymbolNameEqualityComparer); ImmutableHashSet <ISymbol> immutableHashSet5 = instance5.ToImmutableHashSet <ISymbol>((IEqualityComparer <ISymbol>)SemanticFacts.SymbolNameEqualityComparer); ImmutableHashSet <ISymbol> immutableHashSet6 = instance6.ToImmutableHashSet <ISymbol>((IEqualityComparer <ISymbol>)SemanticFacts.SymbolNameEqualityComparer); foreach (ISymbol symbol in immutableHashSet3) { if (immutableHashSet1.Contains(symbol)) { Rule198GlobalLocalVariablesShouldNotHaveSameName.ReportDiagnostic(ctx, DiagnosticDescriptors.Rule022GlobalLocalVariablesShouldNotHaveSameName, symbol); } if (immutableHashSet2.Contains(symbol) || immutableHashSet4.Contains(symbol) || (immutableHashSet5.Contains(symbol) || immutableHashSet6.Contains(symbol))) { Rule198GlobalLocalVariablesShouldNotHaveSameName.ReportDiagnostic(ctx, DiagnosticDescriptors.Rule023DoNotNameLocalVarAsFieldOrMethod, symbol); } } foreach (ISymbol symbol in immutableHashSet2) { if (immutableHashSet4.Contains(symbol) || immutableHashSet5.Contains(symbol) || immutableHashSet6.Contains(symbol)) { Rule198GlobalLocalVariablesShouldNotHaveSameName.ReportDiagnostic(ctx, DiagnosticDescriptors.Rule024DoNotNameMethodAsField, symbol); } } foreach (ISymbol symbol in immutableHashSet1) { if (immutableHashSet4.Contains(symbol) || immutableHashSet2.Contains(symbol) || immutableHashSet5.Contains(symbol)) { Rule198GlobalLocalVariablesShouldNotHaveSameName.ReportDiagnostic(ctx, DiagnosticDescriptors.Rule025DoNotNameGlobalVarAsFieldOrMethod, symbol); } else { ISymbol actualValue; if (immutableHashSet6.Contains(symbol) && immutableHashSet6.TryGetValue(symbol, out actualValue) && actualValue.Kind != SymbolKind.Control) { Rule198GlobalLocalVariablesShouldNotHaveSameName.ReportDiagnostic(ctx, DiagnosticDescriptors.Rule025DoNotNameGlobalVarAsFieldOrMethod, symbol); } } } } finally { instance1.Free(); instance2.Free(); instance3.Free(); instance4.Free(); instance5.Free(); instance6.Free(); } }
private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalidOrDynamicOperation) { // We bail out reporting diagnostics for named types if it contains following kind of operations: // 1. Invalid operations, i.e. erroneous code: // We do so to ensure that we don't report false positives during editing scenarios in the IDE, where the user // is still editing code and fixing unresolved references to symbols, such as overload resolution errors. // 2. Dynamic operations, where we do not know the exact member being referenced at compile time. if (hasInvalidOrDynamicOperation) { return; } if (symbolEndContext.Symbol.GetAttributes().Any(a => a.AttributeClass == _structLayoutAttributeType)) { // Bail out for types with 'StructLayoutAttribute' as the ordering of the members is critical, // and removal of unused members might break semantics. return; } // Report diagnostics for unused candidate members. var first = true; PooledHashSet <ISymbol> symbolsReferencedInDocComments = null; ArrayBuilder <string> debuggerDisplayAttributeArguments = null; try { var namedType = (INamedTypeSymbol)symbolEndContext.Symbol; foreach (var member in namedType.GetMembers()) { // Check if the underlying member is neither read nor a readable reference to the member is taken. // If so, we flag the member as either unused (never written) or unread (written but not read). if (TryRemove(member, out var valueUsageInfo) && !valueUsageInfo.IsReadFrom()) { Debug.Assert(IsCandidateSymbol(member)); Debug.Assert(!member.IsImplicitlyDeclared); if (first) { // Bail out if there are syntax errors in any of the declarations of the containing type. // Note that we check this only for the first time that we report an unused or unread member for the containing type. if (HasSyntaxErrors(namedType, symbolEndContext.CancellationToken)) { return; } // Compute the set of candidate symbols referenced in all the documentation comments within the named type declarations. // This set is computed once and used for all the iterations of the loop. symbolsReferencedInDocComments = GetCandidateSymbolsReferencedInDocComments(namedType, symbolEndContext.Compilation, symbolEndContext.CancellationToken); // Compute the set of string arguments to DebuggerDisplay attributes applied to any symbol within the named type declaration. // These strings may have an embedded reference to the symbol. // This set is computed once and used for all the iterations of the loop. debuggerDisplayAttributeArguments = GetDebuggerDisplayAttributeArguments(namedType); first = false; } // Simple heuristic for members referenced in DebuggerDisplayAttribute's string argument: // bail out if any of the DebuggerDisplay string arguments contains the member name. // In future, we can consider improving this heuristic to parse the embedded expression // and resolve symbol references. if (debuggerDisplayAttributeArguments.Any(arg => arg.Contains(member.Name))) { continue; } // Report IDE0051 or IDE0052 based on whether the underlying member has any Write/WritableRef/NonReadWriteRef references or not. var rule = !valueUsageInfo.IsWrittenTo() && !valueUsageInfo.IsNameOnly() && !symbolsReferencedInDocComments.Contains(member) ? s_removeUnusedMembersRule : s_removeUnreadMembersRule; // Do not flag write-only properties that are not read. // Write-only properties are assumed to have side effects // visible through other means than a property getter. if (rule == s_removeUnreadMembersRule && member is IPropertySymbol property && property.IsWriteOnly) { continue; } // Most of the members should have a single location, except for partial methods. // We report the diagnostic on the first location of the member. var diagnostic = DiagnosticHelper.CreateWithMessage( rule, member.Locations[0], rule.GetEffectiveSeverity(symbolEndContext.Compilation.Options), additionalLocations: null, properties: null, GetMessage(rule, member)); symbolEndContext.ReportDiagnostic(diagnostic); } } } finally { symbolsReferencedInDocComments?.Free(); debuggerDisplayAttributeArguments?.Free(); } return; }
private static void SetKnownToHaveNoDeclaredBaseCycles(ref PooledHashSet<NamedTypeSymbol> visited) { if (visited != null) { foreach (var v in visited) { v.SetKnownToHaveNoDeclaredBaseCycles(); } visited.Free(); visited = null; } }
internal static TResult CompileWithRetry <TResult>( ImmutableArray <MetadataBlock> metadataBlocks, DiagnosticFormatter formatter, CreateContextDelegate createContext, CompileDelegate <TResult> compile, DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr, out string errorMessage) { TResult compileResult; PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null; bool tryAgain; var linqLibrary = EvaluationContextBase.SystemLinqIdentity; do { errorMessage = null; var context = createContext(metadataBlocks, useReferencedModulesOnly: false); var diagnostics = DiagnosticBag.GetInstance(); compileResult = compile(context, diagnostics); tryAgain = false; if (diagnostics.HasAnyErrors()) { bool useReferencedModulesOnly; ImmutableArray <AssemblyIdentity> missingAssemblyIdentities; errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities( diagnostics, formatter, preferredUICulture: null, linqLibrary: linqLibrary, useReferencedModulesOnly: out useReferencedModulesOnly, missingAssemblyIdentities: out missingAssemblyIdentities); // If there were LINQ-related errors, we'll initially add System.Linq (set above). // If that doesn't work, we'll fall back to System.Core for subsequent retries. linqLibrary = EvaluationContextBase.SystemCoreIdentity; // Can we remove the `useReferencedModulesOnly` attempt if we're only using // modules reachable from the current module? In short, can we avoid retrying? if (useReferencedModulesOnly) { Debug.Assert(missingAssemblyIdentities.IsEmpty); var otherContext = createContext(metadataBlocks, useReferencedModulesOnly: true); var otherDiagnostics = DiagnosticBag.GetInstance(); var otherResult = compile(otherContext, otherDiagnostics); if (!otherDiagnostics.HasAnyErrors()) { errorMessage = null; compileResult = otherResult; } otherDiagnostics.Free(); } else { if (!missingAssemblyIdentities.IsEmpty) { if (assembliesLoadedInRetryLoop == null) { assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance(); } // If any identities failed to add (they were already in the list), then don't retry. if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities)) { tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks); } } } } diagnostics.Free(); } while (tryAgain); assembliesLoadedInRetryLoop?.Free(); return(compileResult); }
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(); } }); }); }); }
internal static TResult CompileWithRetry <TResult>( ImmutableArray <MetadataBlock> metadataBlocks, DiagnosticFormatter formatter, CreateContextDelegate createContext, CompileDelegate <TResult> compile, DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr, out string errorMessage) { TResult compileResult; PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null; bool tryAgain; do { errorMessage = null; var context = createContext(metadataBlocks, useReferencedModulesOnly: false); var diagnostics = DiagnosticBag.GetInstance(); compileResult = compile(context, diagnostics); tryAgain = false; if (diagnostics.HasAnyErrors()) { bool useReferencedModulesOnly; ImmutableArray <AssemblyIdentity> missingAssemblyIdentities; errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities( diagnostics, formatter, preferredUICulture: null, useReferencedModulesOnly: out useReferencedModulesOnly, missingAssemblyIdentities: out missingAssemblyIdentities); if (useReferencedModulesOnly) { Debug.Assert(missingAssemblyIdentities.IsEmpty); var otherContext = createContext(metadataBlocks, useReferencedModulesOnly: true); var otherDiagnostics = DiagnosticBag.GetInstance(); var otherResult = compile(otherContext, otherDiagnostics); if (!otherDiagnostics.HasAnyErrors()) { errorMessage = null; compileResult = otherResult; } otherDiagnostics.Free(); } else { if (!missingAssemblyIdentities.IsEmpty) { if (assembliesLoadedInRetryLoop == null) { assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance(); } // If any identities failed to add (they were already in the list), then don't retry. if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities)) { tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks); } } } } diagnostics.Free(); } while (tryAgain); assembliesLoadedInRetryLoop?.Free(); return(compileResult); }
internal void ValidateParameterNameConflicts( ImmutableArray <TypeParameterSymbol> typeParameters, ImmutableArray <ParameterSymbol> parameters, bool allowShadowingNames, DiagnosticBag diagnostics) { PooledHashSet <string>?tpNames = null; if (!typeParameters.IsDefaultOrEmpty) { tpNames = PooledHashSet <string> .GetInstance(); foreach (var tp in typeParameters) { var name = tp.Name; if (string.IsNullOrEmpty(name)) { continue; } if (!tpNames.Add(name)) { // Type parameter declaration name conflicts are detected elsewhere } else if (!allowShadowingNames) { ValidateDeclarationNameConflictsInScope(tp, diagnostics); } } } PooledHashSet <string>?pNames = null; if (!parameters.IsDefaultOrEmpty) { pNames = PooledHashSet <string> .GetInstance(); foreach (var p in parameters) { var name = p.Name; if (string.IsNullOrEmpty(name)) { continue; } if (tpNames != null && tpNames.Contains(name)) { // CS0412: 'X': a parameter or local variable cannot have the same name as a method type parameter diagnostics.Add(ErrorCode.ERR_LocalSameNameAsTypeParam, GetLocation(p), name); } if (!pNames.Add(name)) { // The parameter name '{0}' is a duplicate diagnostics.Add(ErrorCode.ERR_DuplicateParamName, GetLocation(p), name); } else if (!allowShadowingNames) { ValidateDeclarationNameConflictsInScope(p, diagnostics); } } } tpNames?.Free(); pNames?.Free(); }
public void Free() { MethodsConvertedToDelegates.Free(); ScopeTree.Free(); }
public void Dispose() => _usedNames.Free();
public void Free() { CapturedVariables.Free(); CapturedEnvironments.Free(); }
public sealed override void Initialize(AnalysisContext context) { ImmutableHashSet <string> cachedDeserializationMethodNames = this.DeserializationMethodNames; Debug.Assert(!String.IsNullOrWhiteSpace(this.DeserializerTypeMetadataName)); Debug.Assert(!String.IsNullOrWhiteSpace(this.SerializationBinderPropertyMetadataName)); Debug.Assert(cachedDeserializationMethodNames != null); Debug.Assert(!cachedDeserializationMethodNames.IsEmpty); Debug.Assert(this.BinderDefinitelyNotSetDescriptor != null); Debug.Assert(this.BinderMaybeNotSetDescriptor != null); context.EnableConcurrentExecution(); // Security analyzer - analyze and report diagnostics on generated code. context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); // For PropertySetAnalysis dataflow analysis. PropertyMapperCollection propertyMappers = new PropertyMapperCollection( new PropertyMapper( this.SerializationBinderPropertyMetadataName, (NullAbstractValue nullAbstractValue) => { // A null SerializationBinder is what we want to flag as hazardous. switch (nullAbstractValue) { case NullAbstractValue.Null: return(PropertySetAbstractValueKind.Flagged); case NullAbstractValue.NotNull: return(PropertySetAbstractValueKind.Unflagged); default: return(PropertySetAbstractValueKind.MaybeFlagged); } })); HazardousUsageEvaluatorCollection hazardousUsageEvaluators = new HazardousUsageEvaluatorCollection( cachedDeserializationMethodNames.Select( methodName => new HazardousUsageEvaluator(methodName, DoNotUseInsecureDeserializerWithoutBinderBase.HazardousIfNull))); context.RegisterCompilationStartAction( (CompilationStartAnalysisContext compilationStartAnalysisContext) => { WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilationStartAnalysisContext.Compilation); if (!wellKnownTypeProvider.TryGetTypeByMetadataName( this.DeserializerTypeMetadataName, out INamedTypeSymbol deserializerTypeSymbol)) { return; } compilationStartAnalysisContext.RegisterOperationBlockStartAction( (OperationBlockStartAnalysisContext operationBlockStartAnalysisContext) => { PooledHashSet <IOperation> rootOperationsNeedingAnalysis = PooledHashSet <IOperation> .GetInstance(); operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IInvocationOperation invocationOperation = (IInvocationOperation)operationAnalysisContext.Operation; if (invocationOperation.Instance?.Type == deserializerTypeSymbol && cachedDeserializationMethodNames.Contains(invocationOperation.TargetMethod.Name)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } } }, OperationKind.Invocation); operationBlockStartAnalysisContext.RegisterOperationAction( (OperationAnalysisContext operationAnalysisContext) => { IMethodReferenceOperation methodReferenceOperation = (IMethodReferenceOperation)operationAnalysisContext.Operation; if (methodReferenceOperation.Instance?.Type == deserializerTypeSymbol && cachedDeserializationMethodNames.Contains( methodReferenceOperation.Method.MetadataName)) { lock (rootOperationsNeedingAnalysis) { rootOperationsNeedingAnalysis.Add(operationAnalysisContext.Operation.GetRoot()); } } }, OperationKind.MethodReference); operationBlockStartAnalysisContext.RegisterOperationBlockEndAction( (OperationBlockAnalysisContext operationBlockAnalysisContext) => { PooledDictionary <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> allResults = null; try { lock (rootOperationsNeedingAnalysis) { if (!rootOperationsNeedingAnalysis.Any()) { return; } // Only instantiated if there are any results to report. List <ControlFlowGraph> cfgs = new List <ControlFlowGraph>(); var interproceduralAnalysisConfig = InterproceduralAnalysisConfiguration.Create( operationBlockAnalysisContext.Options, SupportedDiagnostics, defaultInterproceduralAnalysisKind: InterproceduralAnalysisKind.None, cancellationToken: operationBlockAnalysisContext.CancellationToken, defaultMaxInterproceduralMethodCallChain: 1); // By default, we only want to track method calls one level down. foreach (IOperation rootOperation in rootOperationsNeedingAnalysis) { ImmutableDictionary <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> dfaResult = PropertySetAnalysis.GetOrComputeHazardousUsages( rootOperation.GetEnclosingControlFlowGraph(), operationBlockAnalysisContext.Compilation, operationBlockAnalysisContext.OwningSymbol, this.DeserializerTypeMetadataName, DoNotUseInsecureDeserializerWithoutBinderBase.ConstructorMapper, propertyMappers, hazardousUsageEvaluators, interproceduralAnalysisConfig); if (dfaResult.IsEmpty) { continue; } if (allResults == null) { allResults = PooledDictionary <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> .GetInstance(); } foreach (KeyValuePair <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> kvp in dfaResult) { allResults.Add(kvp.Key, kvp.Value); } } } if (allResults == null) { return; } foreach (KeyValuePair <(Location Location, IMethodSymbol Method), HazardousUsageEvaluationResult> kvp in allResults) { DiagnosticDescriptor descriptor; switch (kvp.Value) { case HazardousUsageEvaluationResult.Flagged: descriptor = this.BinderDefinitelyNotSetDescriptor; break; case HazardousUsageEvaluationResult.MaybeFlagged: descriptor = this.BinderMaybeNotSetDescriptor; break; default: Debug.Fail($"Unhandled result value {kvp.Value}"); continue; } operationBlockAnalysisContext.ReportDiagnostic( Diagnostic.Create( descriptor, kvp.Key.Location, kvp.Key.Method.ToDisplayString( SymbolDisplayFormat.MinimallyQualifiedFormat))); } } finally { rootOperationsNeedingAnalysis.Free(); allResults?.Free(); } }); }); }); }
private void DefineNamespaceScopes(IMethodBody methodBody) { var module = Module; bool isVisualBasic = module.GenerateVisualBasicStylePdb; IMethodDefinition method = methodBody.MethodDefinition; var namespaceScopes = methodBody.ImportScope; // NOTE: All extern aliases are stored on the outermost namespace scope. PooledHashSet <string> lazyDeclaredExternAliases = null; if (!isVisualBasic) { foreach (var import in GetLastScope(namespaceScopes).GetUsedNamespaces(Context)) { if (import.TargetNamespaceOpt == null && import.TargetTypeOpt == null) { Debug.Assert(import.AliasOpt != null); Debug.Assert(import.TargetAssemblyOpt == null); if (lazyDeclaredExternAliases == null) { lazyDeclaredExternAliases = PooledHashSet <string> .GetInstance(); } lazyDeclaredExternAliases.Add(import.AliasOpt); } } } // file and namespace level for (IImportScope scope = namespaceScopes; scope != null; scope = scope.Parent) { foreach (UsedNamespaceOrType import in scope.GetUsedNamespaces(Context)) { var importString = TryEncodeImport(import, lazyDeclaredExternAliases, isProjectLevel: false); if (importString != null) { UsingNamespace(importString, method); } } } lazyDeclaredExternAliases?.Free(); // project level if (isVisualBasic) { string defaultNamespace = module.DefaultNamespace; if (defaultNamespace != null) { // VB marks the default/root namespace with an asterisk UsingNamespace("*" + defaultNamespace, module); } foreach (string assemblyName in module.LinkedAssembliesDebugInfo) { UsingNamespace("&" + assemblyName, module); } foreach (UsedNamespaceOrType import in module.GetImports(Context)) { var importString = TryEncodeImport(import, null, isProjectLevel: true); if (importString != null) { UsingNamespace(importString, method); } } // VB current namespace -- VB appends the namespace of the container without prefixes UsingNamespace(GetOrCreateSerializedNamespaceName(method.ContainingNamespace), method); } }
public override TaintedDataAbstractValue VisitInvocation_NonLambdaOrDelegateOrLocalFunction( IMethodSymbol method, IOperation visitedInstance, ImmutableArray <IArgumentOperation> visitedArguments, bool invokedAsDelegate, IOperation originalOperation, TaintedDataAbstractValue defaultValue) { // Always invoke base visit. TaintedDataAbstractValue result = base.VisitInvocation_NonLambdaOrDelegateOrLocalFunction( method, visitedInstance, visitedArguments, invokedAsDelegate, originalOperation, defaultValue); IEnumerable <IArgumentOperation> taintedArguments = GetTaintedArguments(visitedArguments); if (taintedArguments.Any()) { ProcessTaintedDataEnteringInvocationOrCreation(method, taintedArguments, originalOperation); } PooledHashSet <string> taintedTargets = null; PooledHashSet <(string, string)> taintedParameterPairs = null; try { if (this.IsSanitizingMethod(method)) { result = TaintedDataAbstractValue.NotTainted; } else if (visitedInstance != null && this.IsSanitizingInstanceMethod(method)) { result = TaintedDataAbstractValue.NotTainted; SetTaintedForEntity(visitedInstance, result); } else if (this.DataFlowAnalysisContext.SourceInfos.IsSourceMethod( method, visitedArguments, new Lazy <PointsToAnalysisResult>(() => DataFlowAnalysisContext.PointsToAnalysisResultOpt), new Lazy <ValueContentAnalysisResult>(() => DataFlowAnalysisContext.ValueContentAnalysisResultOpt), out taintedTargets)) { foreach (string taintedTarget in taintedTargets) { if (taintedTarget != TaintedTargetValue.Return) { IArgumentOperation argumentOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == taintedTarget); if (argumentOperation != null) { this.CacheAbstractValue(argumentOperation, TaintedDataAbstractValue.CreateTainted(argumentOperation.Parameter, argumentOperation.Syntax, method)); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } else { result = TaintedDataAbstractValue.CreateTainted(method, originalOperation.Syntax, this.OwningSymbol); } } } if (this.DataFlowAnalysisContext.SourceInfos.IsSourceTransferMethod( method, visitedArguments, visitedArguments .Where(s => this.GetCachedAbstractValue(s).Kind == TaintedDataAbstractValueKind.Tainted) .Select(s => s.Parameter.Name) .ToImmutableArray(), out taintedParameterPairs)) { foreach ((string ifTaintedParameter, string thenTaintedTarget) in taintedParameterPairs) { IArgumentOperation thenTaintedTargetOperation = visitedArguments.FirstOrDefault(o => o.Parameter.Name == thenTaintedTarget); if (thenTaintedTargetOperation != null) { SetTaintedForEntity( thenTaintedTargetOperation, this.GetCachedAbstractValue( visitedArguments.FirstOrDefault(o => o.Parameter.Name == ifTaintedParameter))); } else { Debug.Fail("Are the tainted data sources misconfigured?"); } } } } finally { taintedTargets?.Free(); taintedParameterPairs?.Free(); } return(result); }
private static void OrderGraph( Dictionary <SourceFieldSymbol, Node <SourceFieldSymbol> > graph, ArrayBuilder <FieldInfo> order) { Debug.Assert(graph.Count > 0); PooledHashSet <SourceFieldSymbol> lastUpdated = null; while (graph.Count > 0) { // Get the set of fields in the graph that have no dependencies. var search = ((IEnumerable <SourceFieldSymbol>)lastUpdated) ?? graph.Keys; var set = ArrayBuilder <SourceFieldSymbol> .GetInstance(); foreach (var field in search) { Node <SourceFieldSymbol> node; if (graph.TryGetValue(field, out node)) { if (node.Dependencies.Count == 0) { set.Add(field); } } } if (lastUpdated != null) { lastUpdated.Free(); lastUpdated = null; } if (set.Count > 0) { var updated = PooledHashSet <SourceFieldSymbol> .GetInstance(); // Remove fields with no dependencies from the graph. foreach (var field in set) { var node = graph[field]; // Remove the field from the Dependencies // of each field that depends on it. foreach (var dependedOnBy in node.DependedOnBy) { var n = graph[dependedOnBy]; n.Dependencies = n.Dependencies.Remove(field); graph[dependedOnBy] = n; updated.Add(dependedOnBy); } graph.Remove(field); } CheckGraph(graph); // Add the set to the ordered list. foreach (var item in set) { order.Add(new FieldInfo(item, startsCycle: false)); } lastUpdated = updated; } else { // All fields have dependencies which means all fields are involved // in cycles. Break the first cycle found. (Note some fields may have // dependencies but are not strictly part of any cycle. For instance, // B and C in: "enum E { A = A | B, B = C, C = D, D = D }"). var field = GetStartOfFirstCycle(graph); // Break the dependencies. var node = graph[field]; // Remove the field from the DependedOnBy // of each field it has as a dependency. foreach (var dependency in node.Dependencies) { var n = graph[dependency]; n.DependedOnBy = n.DependedOnBy.Remove(field); graph[dependency] = n; } node = graph[field]; node.Dependencies = ImmutableHashSet <SourceFieldSymbol> .Empty; if (node.DependedOnBy.Count == 0) { graph.Remove(field); } else { graph[field] = node; } CheckGraph(graph); // Add the start of the cycle to the ordered list. order.Add(new FieldInfo(field, startsCycle: true)); // Need to search the entire graph the next time // through the loop so lastUpdated is not set. } set.Free(); } if (lastUpdated != null) { lastUpdated.Free(); } }