public ImmutableDictionary <TKey, TValue> ToImmutableDictionary() { Debug.Assert(!IsDisposed); return(_coreAnalysisData.ToImmutableDictionary()); }
private static TaintedDataConfig Create(Compilation compilation) { WellKnownTypeProvider wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation); using PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SourceInfo> > > sourceSymbolMapBuilder = PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SourceInfo> > > .GetInstance(); using PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > sanitizerSymbolMapBuilder = PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > .GetInstance(); using PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SinkInfo> > > sinkSymbolMapBuilder = PooledDictionary <SinkKind, Lazy <TaintedDataSymbolMap <SinkInfo> > > .GetInstance(); // For tainted data rules with the same set of sources, we'll reuse the same TaintedDataSymbolMap<SourceInfo> instance. // Same for sanitizers. using PooledDictionary <ImmutableHashSet <SourceInfo>, Lazy <TaintedDataSymbolMap <SourceInfo> > > sourcesToSymbolMap = PooledDictionary <ImmutableHashSet <SourceInfo>, Lazy <TaintedDataSymbolMap <SourceInfo> > > .GetInstance(); using PooledDictionary <ImmutableHashSet <SanitizerInfo>, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > sanitizersToSymbolMap = PooledDictionary <ImmutableHashSet <SanitizerInfo>, Lazy <TaintedDataSymbolMap <SanitizerInfo> > > .GetInstance(); // Build a mapping of (sourceSet, sanitizerSet) -> (sinkKinds, sinkSet), so we'll reuse the same TaintedDataSymbolMap<SinkInfo> instance. using PooledDictionary <(ImmutableHashSet <SourceInfo> SourceInfos, ImmutableHashSet <SanitizerInfo> SanitizerInfos), (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)> sourceSanitizersToSinks = PooledDictionary <(ImmutableHashSet <SourceInfo> SourceInfos, ImmutableHashSet <SanitizerInfo> SanitizerInfos), (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)> .GetInstance(); // Using LazyThreadSafetyMode.ExecutionAndPublication to avoid instantiating multiple times. foreach (SinkKind sinkKind in Enum.GetValues(typeof(SinkKind))) { ImmutableHashSet <SourceInfo> sources = GetSourceInfos(sinkKind); if (!sourcesToSymbolMap.TryGetValue(sources, out Lazy <TaintedDataSymbolMap <SourceInfo> > lazySourceSymbolMap)) { lazySourceSymbolMap = new Lazy <TaintedDataSymbolMap <SourceInfo> >( () => { return(new TaintedDataSymbolMap <SourceInfo>(wellKnownTypeProvider, sources)); }, LazyThreadSafetyMode.ExecutionAndPublication); sourcesToSymbolMap.Add(sources, lazySourceSymbolMap); } sourceSymbolMapBuilder.Add(sinkKind, lazySourceSymbolMap); ImmutableHashSet <SanitizerInfo> sanitizers = GetSanitizerInfos(sinkKind); if (!sanitizersToSymbolMap.TryGetValue(sanitizers, out Lazy <TaintedDataSymbolMap <SanitizerInfo> > lazySanitizerSymbolMap)) { lazySanitizerSymbolMap = new Lazy <TaintedDataSymbolMap <SanitizerInfo> >( () => { return(new TaintedDataSymbolMap <SanitizerInfo>(wellKnownTypeProvider, sanitizers)); }, LazyThreadSafetyMode.ExecutionAndPublication); sanitizersToSymbolMap.Add(sanitizers, lazySanitizerSymbolMap); } sanitizerSymbolMapBuilder.Add(sinkKind, lazySanitizerSymbolMap); ImmutableHashSet <SinkInfo> sinks = GetSinkInfos(sinkKind); if (!sourceSanitizersToSinks.TryGetValue((sources, sanitizers), out (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)sinksPair)) { sinksPair = (ImmutableHashSet.CreateBuilder <SinkKind>(), ImmutableHashSet.CreateBuilder <SinkInfo>()); sourceSanitizersToSinks.Add((sources, sanitizers), sinksPair); } sinksPair.SinkKinds.Add(sinkKind); sinksPair.SinkInfos.UnionWith(sinks); } foreach (KeyValuePair <(ImmutableHashSet <SourceInfo> SourceInfos, ImmutableHashSet <SanitizerInfo> SanitizerInfos), (ImmutableHashSet <SinkKind> .Builder SinkKinds, ImmutableHashSet <SinkInfo> .Builder SinkInfos)> kvp in sourceSanitizersToSinks) { ImmutableHashSet <SinkInfo> sinks = kvp.Value.SinkInfos.ToImmutable(); Lazy <TaintedDataSymbolMap <SinkInfo> > lazySinkSymbolMap = new Lazy <TaintedDataSymbolMap <SinkInfo> >( () => { return(new TaintedDataSymbolMap <SinkInfo>(wellKnownTypeProvider, sinks)); }, LazyThreadSafetyMode.ExecutionAndPublication); foreach (SinkKind sinkKind in kvp.Value.SinkKinds) { sinkSymbolMapBuilder.Add(sinkKind, lazySinkSymbolMap); } } return(new TaintedDataConfig( wellKnownTypeProvider, sourceSymbolMapBuilder.ToImmutableDictionary(), sanitizerSymbolMapBuilder.ToImmutableDictionary(), sinkSymbolMapBuilder.ToImmutableDictionary())); }