Пример #1
0
        public ResultDiffingVisitor(SarifLog sarifLog)
        {
            this.AbsentResults = new HashSet<Result>(Result.ValueComparer);
            this.SharedResults = new HashSet<Result>(Result.ValueComparer);
            this.NewResults = new HashSet<Result>(Result.ValueComparer);

            VisitSarifLog(sarifLog);
        }
        public void ResultDiffingVisitor_DetectsAbsentAndNewResults()
        {
            var result1 = new Result { RuleId = "TST0001" };
            var result2 = new Result { RuleId = "TST0002" };
            var result3 = new Result { RuleId = "TST0003" };

            var sarifLog = new SarifLog
            {
                Runs = new[]
                {
                    new Run
                    {
                        Results = new List<Result>
                        {
                            result1,
                            result2
                        }
                    }
                }
            };

            var visitor = new ResultDiffingVisitor(sarifLog);

            result2 = new Result { RuleId = "TST0002" };
            result3 = new Result { RuleId = "TST0003" };

            var newResults = new Result[]
            {
                result2,
                result3
            };

            visitor.Diff(newResults);

            Assert.AreEqual(visitor.AbsentResults.Count, 1);
            Assert.AreEqual(visitor.AbsentResults.First().RuleId, result1.RuleId);

            Assert.AreEqual(visitor.NewResults.Count, 1);
            Assert.AreEqual(visitor.NewResults.First().RuleId, result3.RuleId);
        }
Пример #3
0
        public MultipleRunsPerSarifTests()
        {
            var testLog = new SarifLog
            {
                Runs = new List <Run>
                {
                    new Run
                    {
                        Tool = new Tool
                        {
                            Name            = "Test",
                            SemanticVersion = "1.0"
                        },
                        Results = new List <Result>
                        {
                            new Result
                            {
                                RuleId    = "C0001",
                                Message   = "Error 1",
                                Locations = new List <Location>
                                {
                                    new Location
                                    {
                                        AnalysisTarget = new PhysicalLocation
                                        {
                                            Uri = new Uri("file:///item1.cpp")
                                        }
                                    }
                                }
                            }
                        }
                    },
                    new Run
                    {
                        Tool = new Tool
                        {
                            Name            = "Test",
                            SemanticVersion = "1.0"
                        },
                        Results = new List <Result>
                        {
                            new Result
                            {
                                RuleId    = "C0002",
                                Message   = "Error 2",
                                Locations = new List <Location>
                                {
                                    new Location
                                    {
                                        AnalysisTarget = new PhysicalLocation
                                        {
                                            Uri = new Uri("file:///item2.cpp")
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            };

            TestUtilities.InitializeTestEnvironment(testLog);
        }
Пример #4
0
 private static SarifLog Baseline(SarifLog baseline, SarifLog current)
 {
     return(matcher.Match(new[] { baseline }, new[] { current }).FirstOrDefault());
 }
        public static async Task InitializeTestEnvironmentAsync(SarifLog sarifLog)
        {
            InitializeTestEnvironment();

            await ErrorListService.ProcessSarifLogAsync(sarifLog, string.Empty, cleanErrors : true, openInEditor : false);
        }
Пример #6
0
        private void RunConverter(StringBuilder sb, string toolFormat, string inputFileName, TestMode testMode)
        {
            string expectedFileName  = inputFileName + ".sarif";
            string generatedFileName = inputFileName + ".actual.sarif";

            try
            {
                this.converter.ConvertToStandardFormat(toolFormat, inputFileName, generatedFileName, LoggingOptions.OverwriteExistingOutputFile | LoggingOptions.PrettyPrint);
            }
            catch (Exception ex)
            {
                sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "The converter {0} threw an exception for input \"{1}\".", toolFormat, inputFileName));
                sb.AppendLine(ex.ToString());
                return;
            }

            string expectedSarif = File.ReadAllText(expectedFileName);
            string actualSarif   = File.ReadAllText(generatedFileName);

            if (expectedSarif == actualSarif)
            {
                JsonSerializerSettings settings = new JsonSerializerSettings()
                {
                    ContractResolver = SarifContractResolver.Instance,
                    Formatting       = Formatting.Indented
                };

                // Make sure we can successfully deserialize what was just generated
                SarifLog actualLog = JsonConvert.DeserializeObject <SarifLog>(actualSarif, settings);

                actualSarif = JsonConvert.SerializeObject(actualLog, settings);

                bool success;
                switch (testMode)
                {
                case TestMode.CompareFileContents:
                    success = expectedSarif == actualSarif;
                    break;

                case TestMode.CompareObjectModels:
                    SarifLog expectedLog = JsonConvert.DeserializeObject <SarifLog>(expectedSarif, settings);
                    success = SarifLogEqualityComparer.Instance.Equals(expectedLog, actualLog);
                    break;

                default:
                    throw new ArgumentException($"Invalid test mode: {testMode}", nameof(testMode));
                }

                if (success)
                {
                    return;
                }
                else
                {
                    File.WriteAllText(generatedFileName, actualSarif);
                }
            }

            string errorMessage = "The output of the {0} converter did not match for input {1}.";

            sb.AppendLine(string.Format(CultureInfo.CurrentCulture, errorMessage, toolFormat, inputFileName));
            sb.AppendLine("Check differences with:");
            sb.AppendLine(GenerateDiffCommand(expectedFileName, generatedFileName));
        }
Пример #7
0
        public int Run(FileWorkItemsOptions options, IFileSystem fileSystem)
        {
            using (var filingContext = new SarifWorkItemContext())
            {
                if (!string.IsNullOrEmpty(options.ConfigurationFilePath))
                {
                    filingContext.LoadFromXml(options.ConfigurationFilePath);
                }

                if (!ValidateOptions(options, filingContext, fileSystem))
                {
                    return(FAILURE);
                }

                // For unit tests: allow us to just validate the options and return.
                if (s_validateOptionsOnly)
                {
                    return(SUCCESS);
                }

                string logFileContents = fileSystem.ReadAllText(options.InputFilePath);
                EnsureValidSarifLogFile(logFileContents, options.InputFilePath);

                if (options.SplittingStrategy != SplittingStrategy.None)
                {
                    filingContext.SplittingStrategy = options.SplittingStrategy;
                }

                if (options.ShouldFileUnchanged != null)
                {
                    filingContext.ShouldFileUnchanged = options.ShouldFileUnchanged.Value;
                }

                if (options.DataToRemove.ToFlags() != OptionallyEmittedData.None)
                {
                    filingContext.DataToRemove = options.DataToRemove.ToFlags();
                }

                if (options.DataToInsert.ToFlags() != OptionallyEmittedData.None)
                {
                    filingContext.DataToInsert = options.DataToInsert.ToFlags();
                }

                SarifLog sarifLog = null;
                using (var filer = new SarifWorkItemFiler(filingContext.HostUri, filingContext))
                {
                    sarifLog = filer.FileWorkItems(logFileContents);
                }

                // By the time we're here, we have updated options.OutputFilePath with the
                // options.InputFilePath argument (in the presence of --inline) and validated
                // that we can write to this location with one exception: we do not currently
                // handle inlining to a read-only location.
                string outputFilePath = options.OutputFilePath;
                if (!string.IsNullOrEmpty(outputFilePath))
                {
                    Formatting formatting = options.PrettyPrint ? Formatting.Indented : Formatting.None;

                    string sarifLogText = JsonConvert.SerializeObject(sarifLog, formatting);

                    fileSystem.WriteAllText(outputFilePath, sarifLogText);
                }
            }

            return(SUCCESS);
        }
Пример #8
0
        private SarifLog CreatePartitionLog(T partitionValue)
        {
            SarifLog partitionLog;

            if (deepClone)
            {
                // Save time and space by not cloning the runs unless and until necessary. We will
                // only need to clone the runs that have results in this partition.
                IList <Run> originalRuns = originalLog.Runs;
                originalLog.Runs = null;

                partitionLog = originalLog.DeepClone();

                originalLog.Runs = originalRuns;
            }
            else
            {
                partitionLog = new SarifLog(originalLog)
                {
                    Runs = null
                };
            }

            partitionLog.Runs = new List <Run>();
            partitionLog.SetProperty(PartitionValuePropertyName, partitionValue);

            var artifactIndexRemappingDictionaries = new List <Dictionary <int, int> >();

            for (int iOriginalRun = 0; iOriginalRun < partitionRunInfos.Count; ++iOriginalRun)
            {
                // Are there results for this run in this partition?
                if (partitionRunInfos[iOriginalRun].ResultDictionary.TryGetValue(partitionValue, out List <Result> results))
                {
                    // Yes, so we'll need a copy of the original run in which the results, and
                    // certain run-level collections such as Run.Artifacts, have been replaced.
                    Run originalRun = originalLog.Runs[iOriginalRun];
                    Run partitionRun;
                    if (deepClone)
                    {
                        // Save time and space by only cloning the necessary results and associated
                        // collection elements. We already cloned the relevant results in VisitResult.
                        IList <Result>   originalResults   = originalRun.Results;
                        IList <Artifact> originalArtifacts = originalRun.Artifacts;
                        originalRun.Results   = null;
                        originalRun.Artifacts = null;

                        partitionRun = originalRun.DeepClone();

                        originalRun.Results   = originalResults;
                        originalRun.Artifacts = originalArtifacts;
                    }
                    else
                    {
                        partitionRun = new Run(originalRun)
                        {
                            Results   = null,
                            Artifacts = null
                        };
                    }

                    partitionRun.Results = results;

                    // Construct a mapping from the indices in the original run to the indices
                    // in the partition run. This includes both the indices relevant to the
                    // results in this partition, and indices that appear in all partitions
                    // because they are mentioned outside of any result (we refer to these as
                    // "global" indices).
                    IEnumerable <int> allPartitionArtifactIndices = partitionRunInfos[iOriginalRun].GlobalArtifactIndices;

                    if (partitionRunInfos[iOriginalRun].ArtifactIndicesDictionary.TryGetValue(partitionValue, out HashSet <int> partitionResultArtifactIndices))
                    {
                        allPartitionArtifactIndices = allPartitionArtifactIndices.Union(partitionResultArtifactIndices);
                    }

                    var partitionArtifactIndexRemappingDictionary = new Dictionary <int, int>();
                    artifactIndexRemappingDictionaries.Add(partitionArtifactIndexRemappingDictionary);

                    List <int> allPartitionArtifactIndicesList = allPartitionArtifactIndices
                                                                 .OrderBy(index => index)
                                                                 .ToList();

                    int numPartitionIndices = 0;
                    foreach (int originalIndex in allPartitionArtifactIndicesList)
                    {
                        partitionArtifactIndexRemappingDictionary.Add(originalIndex, numPartitionIndices++);
                    }

                    // Copy the artifacts corresponding to the complete set of indices.
                    var artifacts = new List <Artifact>();
                    foreach (int originalIndex in allPartitionArtifactIndicesList)
                    {
                        Artifact originalArtifact  = originalRun.Artifacts[originalIndex];
                        Artifact partitionArtifact = deepClone
                            ? originalArtifact.DeepClone()
                            : new Artifact(originalArtifact);

                        artifacts.Add(partitionArtifact);
                    }

                    if (artifacts.Any())
                    {
                        partitionRun.Artifacts = artifacts;
                    }

                    partitionLog.Runs.Add(partitionRun);
                }
            }

            // Traverse the entire log, fixing the index mappings for indices that appear
            // in the remapping dictionaries.
            var remappingVisitor = new PartitionedIndexRemappingVisitor(artifactIndexRemappingDictionaries);

            remappingVisitor.VisitSarifLog(partitionLog);

            return(partitionLog);
        }
Пример #9
0
 private static void SaveLogFile(string filePath, SarifLog log)
 {
     SaveLogFile(filePath, JsonConvert.SerializeObject(log));
 }
Пример #10
0
        // The sarifLog parameter contains exactly a set of results that are intended to be filed as a single work item
        // and this log will be attached to the work item.
        public SarifWorkItemModel(SarifLog sarifLog, SarifWorkItemContext context = null, Guid guid = default(Guid))
        {
            if (sarifLog == null)
            {
                throw new ArgumentNullException(nameof(sarifLog));
            }

            this.SarifLog = sarifLog;
            this.Context  = context ?? new SarifWorkItemContext();

            this.Guid = (guid == default(Guid)) ? Guid.NewGuid() : guid;

            var visitor = new ExtractAllArtifactLocationsVisitor();

            visitor.VisitSarifLog(sarifLog);

            foreach (ArtifactLocation location in visitor.AllArtifactLocations)
            {
                if (location?.Uri != null)
                {
                    LocationUris ??= new List <Uri>();
                    LocationUris.Add(location.Uri);
                }
            }

            // Shared GitHub/Azure DevOps concepts

            this.LabelsOrTags = new List <string>();

            foreach (string tag in context.AdditionalTags)
            {
                this.LabelsOrTags.Add(tag);
            }

            // Note that we provide a simple file name here. The filers will
            // add a prefix to the file name that includes other details,
            // such as the id of the filed item.
            this.Attachment = new Microsoft.WorkItems.Attachment
            {
                Name = "ScanResults.sarif",
                Text = JsonConvert.SerializeObject(sarifLog, Formatting.Indented),
            };

            this.Title = sarifLog.Runs?[0]?.CreateWorkItemTitle(this.Context.ShouldFileUnchanged);

            // TODO: Provide a useful SARIF-derived discussion entry
            //       for the preliminary filing operation.
            //
            //       https://github.com/microsoft/sarif-sdk/issues/1756
            //
            this.CommentOrDiscussion = $"Default {nameof(this.CommentOrDiscussion)}";

            string descriptionFooter = this.Context.DescriptionFooter;

            this.BodyOrDescription =
                Environment.NewLine +
                sarifLog.CreateWorkItemDescription(this.Context, LocationUris) +
                descriptionFooter;

            // These properties are Azure DevOps-specific. All ADO work item board
            // area paths are rooted by the project name, as are iterations.
            this.Area      = this.RepositoryOrProject;
            this.Iteration = this.RepositoryOrProject;

            // Milestone is a shared concept between GitHub and AzureDevOps. For both
            // environments this field is an open-ended text field. As such, there is
            // no useful default. An empty string here will prompt filers to skip
            // updating this field.
            this.Milestone = string.Empty;

            // No defaults are provided for custom fields. This dictionary is used
            // to provide values for non-standard fields as defined in an Azure
            // DevOps work item template. Because this data by definition addresses
            // non-generalized needs, there are no useful defaults we can provide.
            //
            // this.CustomFields
        }
Пример #11
0
        private static void Main(string[] args)
        {
            bool   deferred = bool.Parse(args[0]);
            string filePath = args[1];

            SarifLog log = null;

            Console.WriteLine($"Loading {filePath}{(deferred ? " (deferred)" : "")}...");

            Measure(() =>
            {
                // Use 'SarifDeferredContractResolver' and 'JsonPositionedTextReader' to load a deferred version of the same object graph.
                JsonSerializer serializer = new JsonSerializer();

                if (deferred)
                {
                    serializer.ContractResolver = SarifDeferredContractResolver.Instance;
                }

                using (JsonTextReader reader = (deferred ? new JsonPositionedTextReader(filePath) : new JsonTextReader(new StreamReader(filePath))))
                {
                    log = serializer.Deserialize <SarifLog>(reader);
                }

                return($"Loaded {filePath} ({(new FileInfo(filePath).Length / BytesPerMB):n1} MB)");
            });

            // Enumerate collections as normal. Enumeration is efficient. Indexing to items works, but is slower, as a file seek is required per item read.
            Run run = log.Runs[0];

            Measure(() =>
            {
                int messageLengthTotal = 0;

                // Fastest: Enumerate
                foreach (Result result in run.Results)
                {
                    messageLengthTotal += result?.Message?.Text?.Length ?? 0;
                }

                // Slower: Count and indexer
                //int messageCount = run.Results.Count;
                //for (int i = 0; i < messageCount; ++i)
                //{
                //    Result result = run.Results[i];
                //    messageLengthTotal += result?.Message?.Text?.Length ?? 0;
                //}

                return($"Enumerated {run.Results.Count:n0} Results message total {messageLengthTotal / BytesPerMB:n0}MB");
            });

            Measure(() =>
            {
                int fileCount      = 0;
                int uriLengthTotal = 0;

                if (run.Artifacts != null)
                {
                    // Fastest: Enumerate
                    foreach (Artifact artifact in run.Artifacts)
                    {
                        uriLengthTotal += artifact?.Location?.Uri?.OriginalString?.Length ?? 0;
                        fileCount++;
                    }

                    // Slower: Keys and indexer
                    //foreach (var key in run.Files.Keys)
                    //{
                    //    FileData file = run.Files[key];
                    //    uriLengthTotal += file?.ArtifactLocation?.Uri?.OriginalString?.Length ?? 0;
                    //    fileCount++;
                    //}
                }

                return($"Enumerated {fileCount:n0} Files, URI total {uriLengthTotal / BytesPerMB:n0}MB.");
            });

            GC.KeepAlive(log);
        }
Пример #12
0
        public static bool AreSufficientlySimiliar(SarifLog baseline, string baselineResultGuid, SarifLog current, string currentResultGuid)
        {
            Result bResult = baseline.FindByGuid(baselineResultGuid);
            Result cResult = current.FindByGuid(currentResultGuid);

            if (bResult == null || cResult == null)
            {
                return(false);
            }

            ExtractedResult bExtractedResult = new ExtractedResult(bResult, bResult.Run);
            ExtractedResult cExtractedResult = new ExtractedResult(cResult, cResult.Run);

            bool outcome = bExtractedResult.IsSufficientlySimilarTo(cExtractedResult);

            return(outcome);
        }
Пример #13
0
 public LogInSeries(SarifLog log, int logIndex, string filePath)
 {
     Log      = log;
     LogIndex = logIndex;
     FilePath = filePath;
 }
Пример #14
0
        private int WriteRunToErrorList(Run run, string logFilePath, SarifLog sarifLog)
        {
            if (!SarifViewerPackage.IsUnitTesting)
            {
#pragma warning disable VSTHRD108 // Assert thread affinity unconditionally
                ThreadHelper.ThrowIfNotOnUIThread();
#pragma warning restore VSTHRD108
            }

            int runIndex  = CodeAnalysisResultManager.Instance.GetNextRunIndex();
            var dataCache = new RunDataCache(runIndex, logFilePath, sarifLog);
            CodeAnalysisResultManager.Instance.RunIndexToRunDataCache.Add(runIndex, dataCache);
            CodeAnalysisResultManager.Instance.CacheUriBasePaths(run);
            var sarifErrors = new List <SarifErrorListItem>();

            var dte = Package.GetGlobalService(typeof(DTE)) as DTE2;

            var projectNameCache = new ProjectNameCache(dte?.Solution);

            this.StoreFileDetails(run.Artifacts);

            if (run.Results != null)
            {
                foreach (Result result in run.Results)
                {
                    result.Run = run;
                    var sarifError = new SarifErrorListItem(run, runIndex, result, logFilePath, projectNameCache);
                    sarifErrors.Add(sarifError);
                }
            }

            if (run.Invocations != null)
            {
                foreach (Invocation invocation in run.Invocations)
                {
                    if (invocation.ToolConfigurationNotifications != null)
                    {
                        foreach (Notification configurationNotification in invocation.ToolConfigurationNotifications)
                        {
                            var sarifError = new SarifErrorListItem(run, runIndex, configurationNotification, logFilePath, projectNameCache);
                            sarifErrors.Add(sarifError);
                        }
                    }

                    if (invocation.ToolExecutionNotifications != null)
                    {
                        foreach (Notification toolNotification in invocation.ToolExecutionNotifications)
                        {
                            if (toolNotification.Level != FailureLevel.Note)
                            {
                                var sarifError = new SarifErrorListItem(run, runIndex, toolNotification, logFilePath, projectNameCache);
                                sarifErrors.Add(sarifError);
                            }
                        }
                    }
                }
            }

            if (run.HasAbsentResults())
            {
                this.ShowFilteredCategoryColumn();
            }

            if (run.HasSuppressedResults())
            {
                this.ShowFilteredSuppressionStateColumn();
            }

            (dataCache.SarifErrors as List <SarifErrorListItem>).AddRange(sarifErrors);
            SarifTableDataSource.Instance.AddErrors(sarifErrors);

            // This causes already open "text views" to be tagged when SARIF logs are processed after a view is opened.
            SarifLocationTagHelpers.RefreshTags();

            return(sarifErrors.Count);
        }
Пример #15
0
        internal static async Task ProcessSarifLogAsync(SarifLog sarifLog, string logFilePath, bool cleanErrors, bool openInEditor)
        {
            // The creation of the data models must be done on the UI thread (for now).
            // VS's table data source constructs are indeed thread safe.
            // The object model (which is eventually handed to WPF\XAML) could also
            // be constructed on any thread as well.
            // However the current implementation of the data model and
            // the "run data cache" have not been augmented to support this
            // and are not thread safe.
            // This work could be done in the future to do even less work on the UI
            // thread if needed.
            if (!SarifViewerPackage.IsUnitTesting)
            {
                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
            }

            // Clear previous data
            if (cleanErrors)
            {
                CleanAllErrors();
            }

            bool hasResults = false;

            foreach (Run run in sarifLog.Runs)
            {
                // run.tool is required, add one if it's missing
                if (run.Tool == null)
                {
                    run.Tool = new Tool
                    {
                        Driver = new ToolComponent
                        {
                            Name = Resources.UnknownToolName,
                        },
                    };
                }

                if (Instance.WriteRunToErrorList(run, logFilePath, sarifLog) > 0)
                {
                    hasResults = true;
                }
            }

            if (openInEditor && !SarifViewerPackage.IsUnitTesting)
            {
                SdkUIUtilities.OpenDocument(ServiceProvider.GlobalProvider, logFilePath, usePreviewPane: false);
            }

            if (hasResults)
            {
                if (!SarifViewerPackage.IsUnitTesting)
                {
                    // We cannot show UI during unit-tests.
                    SdkUIUtilities.ShowToolWindowAsync(new Guid(ToolWindowGuids80.ErrorList), activate: false).FileAndForget(Constants.FileAndForgetFaultEventNames.ShowErrorList);
                }
            }

            SarifLogsMonitor.Instance.StartWatch(logFilePath);

            RaiseLogProcessed(ExceptionalConditionsCalculator.Calculate(sarifLog));
        }
Пример #16
0
        public static async Task ProcessLogFileCoreAsync(string filePath, string toolFormat, bool promptOnLogConversions, bool cleanErrors, bool openInEditor)
        {
            SarifLog log            = null;
            string   logText        = null;
            string   outputPath     = null;
            bool     saveOutputFile = true;

            if (toolFormat.MatchesToolFormat(ToolFormat.None))
            {
                await RetryInvokeAsync(
                    async() =>
                {
                    using (var logStreamReader = new StreamReader(filePath, Encoding.UTF8))
                    {
                        logText = await logStreamReader.ReadToEndAsync().ConfigureAwait(continueOnCapturedContext: false);
                    }
                },
                    retryInterval : TimeSpan.FromMilliseconds(300),
                    maxAttemptCount : 5);

                Match match = MatchVersionProperty(logText);
                if (match.Success)
                {
                    string inputVersion = match.Groups["version"].Value;

                    if (inputVersion == SarifUtilities.V1_0_0)
                    {
                        // They're opening a v1 log, so we need to transform it.
                        // Ask if they'd like to save the v2 log.
                        MessageDialogCommand response = promptOnLogConversions ?
                                                        await PromptToSaveProcessedLogAsync(Resources.TransformV1_DialogMessage).ConfigureAwait(continueOnCapturedContext: false) :
                                                        MessageDialogCommand.No;

                        if (response == MessageDialogCommand.Cancel)
                        {
                            return;
                        }

                        var settingsV1 = new JsonSerializerSettings()
                        {
                            ContractResolver = SarifContractResolverVersionOne.Instance,
                        };

                        SarifLogVersionOne v1Log = JsonConvert.DeserializeObject <SarifLogVersionOne>(logText, settingsV1);
                        var transformer          = new SarifVersionOneToCurrentVisitor();
                        transformer.VisitSarifLogVersionOne(v1Log);
                        log = transformer.SarifLog;

                        if (response == MessageDialogCommand.Yes)
                        {
                            // Prompt for a location to save the transformed log.
                            outputPath = await PromptForFileSaveLocationAsync(Resources.SaveTransformedV1Log_DialogTitle, filePath).ConfigureAwait(continueOnCapturedContext: false);

                            if (string.IsNullOrEmpty(outputPath))
                            {
                                return;
                            }
                        }

                        logText = JsonConvert.SerializeObject(log);
                    }
                    else if (inputVersion != VersionConstants.StableSarifVersion)
                    {
                        // It's an older v2 version, so send it through the pre-release compat transformer.
                        // Ask if they'd like to save the transformed log.
                        MessageDialogCommand response = promptOnLogConversions ?
                                                        await PromptToSaveProcessedLogAsync(string.Format(Resources.TransformPrereleaseV2_DialogMessage, VersionConstants.StableSarifVersion)).ConfigureAwait(continueOnCapturedContext: false) :
                                                        MessageDialogCommand.No;

                        if (response == MessageDialogCommand.Cancel)
                        {
                            return;
                        }

                        log = PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(logText, Formatting.Indented, out logText);

                        if (response == MessageDialogCommand.Yes)
                        {
                            // Prompt for a location to save the transformed log.
                            outputPath = await PromptForFileSaveLocationAsync(Resources.SaveTransformedPrereleaseV2Log_DialogTitle, filePath).ConfigureAwait(continueOnCapturedContext: false);

                            if (string.IsNullOrEmpty(outputPath))
                            {
                                return;
                            }
                        }
                    }
                    else
                    {
                        // Since we didn't do any pre-processing, we don't need to write to a temp location.
                        outputPath     = filePath;
                        saveOutputFile = false;
                    }
                }
                else
                {
                    await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

                    // The version property wasn't found within the first 100 characters.
                    // Per the spec, it should appear first in the sarifLog object.
                    VsShellUtilities.ShowMessageBox(ServiceProvider.GlobalProvider,
                                                    Resources.VersionPropertyNotFound_DialogTitle,
                                                    null, // title
                                                    OLEMSGICON.OLEMSGICON_QUERY,
                                                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                    return;
                }
            }
            else
            {
                // They're opening a non-SARIF log, so we need to convert it.
                // Ask if they'd like to save the converted log.
                MessageDialogCommand response = promptOnLogConversions ?
                                                await PromptToSaveProcessedLogAsync(Resources.ConvertNonSarifLog_DialogMessage).ConfigureAwait(continueOnCapturedContext: false) :
                                                MessageDialogCommand.No;

                if (response == MessageDialogCommand.Cancel)
                {
                    return;
                }

                // The converter doesn't have async methods, so spin
                // up a task to do this.
                await System.Threading.Tasks.Task.Run(() =>
                {
                    var sb = new StringBuilder();
                    using (FileStream fileStream = File.OpenRead(filePath))
                    {
                        using (var outputTextWriter = new StringWriter(sb))
                            using (var outputJson = new JsonTextWriter(outputTextWriter))
                                using (var output = new ResultLogJsonWriter(outputJson))
                                {
                                    var converter = new ToolFormatConverter();
                                    converter.ConvertToStandardFormat(toolFormat, fileStream, output);
                                }

                        logText = sb.ToString();

                        if (response == MessageDialogCommand.Yes)
                        {
                            // Prompt for a location to save the converted log.
                            outputPath = PromptForFileSaveLocationAsync(Resources.SaveConvertedLog_DialogTitle, filePath).Result;
                        }
                    }
                }).ConfigureAwait(continueOnCapturedContext: false);
            }

            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = Path.GetTempFileName() + ".sarif";
            }

            if (saveOutputFile)
            {
                await SaveLogFileAsync(outputPath, logText).ConfigureAwait(continueOnCapturedContext: false);
            }

            if (log == null)
            {
                log = JsonConvert.DeserializeObject <SarifLog>(logText);
            }

            await ProcessSarifLogAsync(log, outputPath, cleanErrors : cleanErrors, openInEditor : openInEditor).ConfigureAwait(continueOnCapturedContext: false);
        }
Пример #17
0
        protected override string ConstructTestOutputFromInputResource(string inputResourceName, object parameter)
        {
            string v2LogText = GetResourceText(inputResourceName);

            string inputLogDirectory = this.OutputFolderPath;
            string inputLogFileName  = Path.GetFileName(inputResourceName);
            string inputLogFilePath  = Path.Combine(this.OutputFolderPath, inputLogFileName);

            string actualLogFilePath = Guid.NewGuid().ToString();

            string ruleUnderTest = Path.GetFileNameWithoutExtension(inputLogFilePath).Split('.')[1];

            // All SARIF rule prefixes require update to current release.
            // All rules with JSON prefix are low level syntax/deserialization checks.
            // We can't transform these test inputs as that operation fixes up errors in the file.
            // Also, don't transform the tests for SARIF1011 or SARIF2008, because these rules
            // examine the actual contents of the $schema property.

            string[] shouldNotTransform = { "SARIF1011", "SARIF2008" };

            bool updateInputsToCurrentSarif = IsSarifRule(ruleUnderTest) &&
                                              !shouldNotTransform.Contains(ruleUnderTest);

            var validateOptions = new ValidateOptions
            {
                SarifOutputVersion   = SarifVersion.Current,
                TargetFileSpecifiers = new[] { inputLogFilePath },
                OutputFilePath       = actualLogFilePath,
                Quiet = true,
                UpdateInputsToCurrentSarif = updateInputsToCurrentSarif,
                PrettyPrint = true,
                Optimize    = true,
                Verbose     = true // Turn on note-level rules.
            };

            var mockFileSystem = new Mock <IFileSystem>();

            mockFileSystem.Setup(x => x.DirectoryExists(inputLogDirectory)).Returns(true);
            mockFileSystem.Setup(x => x.DirectoryGetDirectories(It.IsAny <string>())).Returns(new string[0]);
            mockFileSystem.Setup(x => x.DirectoryGetFiles(inputLogDirectory, inputLogFileName)).Returns(new string[] { inputLogFilePath });
            mockFileSystem.Setup(x => x.FileReadAllText(inputLogFilePath)).Returns(v2LogText);
            mockFileSystem.Setup(x => x.FileReadAllText(It.IsNotIn <string>(inputLogFilePath))).Returns <string>(path => File.ReadAllText(path));
            mockFileSystem.Setup(x => x.FileWriteAllText(It.IsAny <string>(), It.IsAny <string>()));

            // Some rules are disabled by default, so create a configuration file that explicitly
            // enables the rule under test.
            using (TempFile configFile = CreateTempConfigFile(ruleUnderTest, parameter))
            {
                validateOptions.ConfigurationFilePath = configFile.Name;
                mockFileSystem.Setup(x => x.FileExists(validateOptions.ConfigurationFilePath)).Returns(true);

                var validateCommand = new ValidateCommand(mockFileSystem.Object);

                int returnCode = validateCommand.Run(validateOptions);

                if (validateCommand.ExecutionException != null)
                {
                    Console.WriteLine(validateCommand.ExecutionException.ToString());
                }

                returnCode.Should().Be(0);
            }

            string   actualLogFileContents = File.ReadAllText(actualLogFilePath);
            SarifLog actualLog             = JsonConvert.DeserializeObject <SarifLog>(actualLogFileContents);
            Run      run = actualLog.Runs[0];

            // First, we'll strip any validation results that don't originate with the rule under test.
            // But leave the results that originate from JSchema! Also, be careful because output files
            // from "valid" test cases don't have any results.
            run.Results = run.Results
                          ?.Where(r => IsRelevant(r.RuleId, ruleUnderTest))
                          ?.ToList();

            // Next, remove any rule metadata for those rules. The output files from "valid" test
            // cases don't have any rules.
            run.Tool.Driver.Rules = run.Tool.Driver.Rules
                                    ?.Where(r => IsRelevant(r.Id, ruleUnderTest))
                                    ?.ToList();

            // Since there's only one rule in the metadata, the ruleIndex for all remaining results
            // must be 0.
            foreach (Result result in run.Results)
            {
                result.RuleIndex = 0;
            }

            // Next, we'll remove non-deterministic information, most notably, timestamps emitted for the invocation data.
            var removeTimestampsVisitor = new RemoveOptionalDataVisitor(OptionallyEmittedData.NondeterministicProperties);

            removeTimestampsVisitor.Visit(actualLog);

            // Finally, we'll elide non-deterministic build root details
            var rebaseUrisVisitor = new RebaseUriVisitor("TEST_DIR", new Uri(inputLogDirectory));

            rebaseUrisVisitor.Visit(actualLog);

            // There are differences in log file output depending on whether we are invoking xunit
            // from within Visual Studio or at the command-line via xunit.exe. We elide these differences.

            ToolComponent driver = actualLog.Runs[0].Tool.Driver;

            driver.Name                  = "SARIF Functional Testing";
            driver.Version               = null;
            driver.FullName              = null;
            driver.SemanticVersion       = null;
            driver.DottedQuadFileVersion = null;
            driver.Product               = null;
            driver.Organization          = null;
            driver.Properties?.Clear();
            actualLog.Runs[0].OriginalUriBaseIds = null;

            return(JsonConvert.SerializeObject(actualLog, Formatting.Indented));
        }
Пример #18
0
        public static void ProcessLogFile(string filePath, Solution solution, string toolFormat = ToolFormat.None, bool promptOnLogConversions = true)
        {
            SarifLog log = null;

            string logText;
            string outputPath     = null;
            bool   saveOutputFile = true;

            if (toolFormat.MatchesToolFormat(ToolFormat.None))
            {
                logText = File.ReadAllText(filePath);

                Match match = MatchVersionProperty(logText);
                if (match.Success)
                {
                    string inputVersion = match.Groups["version"].Value;

                    if (inputVersion == SarifUtilities.V1_0_0)
                    {
                        // They're opening a v1 log, so we need to transform it.
                        // Ask if they'd like to save the v2 log.
                        MessageDialogCommand response = promptOnLogConversions ? PromptToSaveProcessedLog(Resources.TransformV1_DialogMessage) : MessageDialogCommand.No;

                        if (response == MessageDialogCommand.Cancel)
                        {
                            return;
                        }

                        JsonSerializerSettings settingsV1 = new JsonSerializerSettings()
                        {
                            ContractResolver = SarifContractResolverVersionOne.Instance
                        };

                        SarifLogVersionOne v1Log = JsonConvert.DeserializeObject <SarifLogVersionOne>(logText, settingsV1);
                        var transformer          = new SarifVersionOneToCurrentVisitor();
                        transformer.VisitSarifLogVersionOne(v1Log);
                        log = transformer.SarifLog;

                        if (response == MessageDialogCommand.Yes)
                        {
                            // Prompt for a location to save the transformed log.
                            outputPath = PromptForFileSaveLocation(Resources.SaveTransformedV1Log_DialogTitle, filePath);

                            if (string.IsNullOrEmpty(outputPath))
                            {
                                return;
                            }
                        }

                        logText = JsonConvert.SerializeObject(log);
                    }
                    else if (inputVersion != VersionConstants.StableSarifVersion)
                    {
                        // It's an older v2 version, so send it through the pre-release compat transformer.
                        // Ask if they'd like to save the transformed log.
                        MessageDialogCommand response = promptOnLogConversions ? PromptToSaveProcessedLog(string.Format(Resources.TransformPrereleaseV2_DialogMessage, VersionConstants.StableSarifVersion)) : MessageDialogCommand.No;

                        if (response == MessageDialogCommand.Cancel)
                        {
                            return;
                        }

                        log = PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(logText, Formatting.Indented, out logText);

                        if (response == MessageDialogCommand.Yes)
                        {
                            // Prompt for a location to save the transformed log.
                            outputPath = PromptForFileSaveLocation(Resources.SaveTransformedPrereleaseV2Log_DialogTitle, filePath);

                            if (string.IsNullOrEmpty(outputPath))
                            {
                                return;
                            }
                        }
                    }
                    else
                    {
                        // Since we didn't do any pre-processing, we don't need to write to a temp location.
                        outputPath     = filePath;
                        saveOutputFile = false;
                    }
                }
                else
                {
                    // The version property wasn't found within the first 100 characters.
                    // Per the spec, it should appear first in the sarifLog object.
                    VsShellUtilities.ShowMessageBox(SarifViewerPackage.ServiceProvider,
                                                    Resources.VersionPropertyNotFound_DialogTitle,
                                                    null, // title
                                                    OLEMSGICON.OLEMSGICON_QUERY,
                                                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                    return;
                }
            }
            else
            {
                // They're opening a non-SARIF log, so we need to convert it.
                // Ask if they'd like to save the converted log.
                MessageDialogCommand response = promptOnLogConversions ? PromptToSaveProcessedLog(Resources.ConvertNonSarifLog_DialogMessage) : MessageDialogCommand.No;

                if (response == MessageDialogCommand.Cancel)
                {
                    return;
                }

                var converter = new ToolFormatConverter();
                var sb        = new StringBuilder();

                using (var input = new MemoryStream(File.ReadAllBytes(filePath)))
                {
                    var outputTextWriter = new StringWriter(sb);
                    var outputJson       = new JsonTextWriter(outputTextWriter);
                    var output           = new ResultLogJsonWriter(outputJson);

                    input.Seek(0, SeekOrigin.Begin);
                    converter.ConvertToStandardFormat(toolFormat, input, output);

                    // This is serving as a flush mechanism.
                    output.Dispose();

                    logText = sb.ToString();

                    if (response == MessageDialogCommand.Yes)
                    {
                        // Prompt for a location to save the converted log.
                        outputPath = PromptForFileSaveLocation(Resources.SaveConvertedLog_DialogTitle, filePath);
                    }
                }
            }

            if (string.IsNullOrEmpty(outputPath))
            {
                outputPath = Path.GetTempFileName() + ".sarif";
            }

            if (saveOutputFile)
            {
                SaveLogFile(outputPath, logText);
            }

            if (log == null)
            {
                log = JsonConvert.DeserializeObject <SarifLog>(logText);
            }

            ProcessSarifLog(log, outputPath, solution, showMessageOnNoResults: promptOnLogConversions);

            SarifTableDataSource.Instance.BringToFront();
        }
Пример #19
0
 protected override void Analyze(SarifLog log, string logPointer)
 {
     AnalyzeSchema(log.SchemaUri, logPointer);
 }
Пример #20
0
        private SarifLog CreatePartitionLog(T partitionValue)
        {
            SarifLog partitionLog;

            if (deepClone)
            {
                // Save time and space by not cloning the runs unless and until necessary. We will
                // only need to clone the runs that have results in this partition.
                IList <Run> originalRuns = originalLog.Runs;
                originalLog.Runs = null;

                partitionLog = originalLog.DeepClone();

                originalLog.Runs = originalRuns;
            }
            else
            {
                partitionLog = new SarifLog(originalLog.SchemaUri,
                                            originalLog.Version,
                                            runs: null,
                                            originalLog.InlineExternalProperties,
                                            originalLog.Properties);
            }

            partitionLog.Runs = new List <Run>();
            partitionLog.SetProperty(PartitionValuePropertyName, partitionValue);

            var artifactIndexRemappingDictionaries = new List <Dictionary <int, int> >();

            for (int iOriginalRun = 0; iOriginalRun < partitionRunInfos.Count; ++iOriginalRun)
            {
                // Are there results for this run in this partition?
                if (partitionRunInfos[iOriginalRun].ResultDictionary.TryGetValue(partitionValue, out List <Result> results))
                {
                    // Yes, so we'll need a copy of the original run in which the results, and
                    // certain run-level collections such as Run.Artifacts, have been replaced.
                    Run originalRun = originalLog.Runs[iOriginalRun];
                    Run partitionRun;
                    if (deepClone)
                    {
                        // Save time and space by only cloning the necessary results and associated
                        // collection elements. We already cloned the relevant results in VisitResult.
                        IList <Result>   originalResults   = originalRun.Results;
                        IList <Artifact> originalArtifacts = originalRun.Artifacts;
                        originalRun.Results   = null;
                        originalRun.Artifacts = null;

                        partitionRun = originalRun.DeepClone();

                        originalRun.Results   = originalResults;
                        originalRun.Artifacts = originalArtifacts;
                    }
                    else
                    {
                        partitionRun = new Run(originalRun.Tool,
                                               originalRun.Invocations,
                                               originalRun.Conversion,
                                               originalRun.Language,
                                               originalRun.VersionControlProvenance,
                                               originalRun.OriginalUriBaseIds,
                                               artifacts: null,
                                               originalRun.LogicalLocations,
                                               originalRun.Graphs,
                                               results: null,
                                               originalRun.AutomationDetails,
                                               originalRun.RunAggregates,
                                               originalRun.BaselineGuid,
                                               originalRun.RedactionTokens,
                                               originalRun.DefaultEncoding,
                                               originalRun.DefaultSourceLanguage,
                                               originalRun.NewlineSequences,
                                               originalRun.ColumnKind,
                                               originalRun.ExternalPropertyFileReferences,
                                               originalRun.ThreadFlowLocations,
                                               originalRun.Taxonomies,
                                               originalRun.Addresses,
                                               originalRun.Translations,
                                               originalRun.Policies,
                                               originalRun.WebRequests,
                                               originalRun.WebResponses,
                                               originalRun.SpecialLocations,
                                               originalRun.Properties);
                    }

                    partitionRun.Results = results;

                    // Construct a mapping from the indices in the original run to the indices
                    // in the partition run. This includes both the indices relevant to the
                    // results in this partition, and indices that appear in all partitions
                    // because they are mentioned outside of any result (we refer to these as
                    // "global" indices).
                    IEnumerable <int> allPartitionArtifactIndices = partitionRunInfos[iOriginalRun].GlobalArtifactIndices;

                    if (partitionRunInfos[iOriginalRun].ArtifactIndicesDictionary.TryGetValue(partitionValue, out HashSet <int> partitionResultArtifactIndices))
                    {
                        allPartitionArtifactIndices = allPartitionArtifactIndices.Union(partitionResultArtifactIndices);
                    }

                    var partitionArtifactIndexRemappingDictionary = new Dictionary <int, int>();
                    artifactIndexRemappingDictionaries.Add(partitionArtifactIndexRemappingDictionary);

                    List <int> allPartitionArtifactIndicesList = allPartitionArtifactIndices
                                                                 .OrderBy(index => index)
                                                                 .ToList();

                    int numPartitionIndices = 0;
                    foreach (int originalIndex in allPartitionArtifactIndicesList)
                    {
                        partitionArtifactIndexRemappingDictionary.Add(originalIndex, numPartitionIndices++);
                    }

                    // Copy the artifacts corresponding to the complete set of indices.
                    var artifacts = new List <Artifact>();
                    foreach (int originalIndex in allPartitionArtifactIndicesList)
                    {
                        Artifact originalArtifact  = originalRun.Artifacts[originalIndex];
                        Artifact partitionArtifact = deepClone
                            ? originalArtifact.DeepClone()
                            : new Artifact(originalArtifact);

                        artifacts.Add(partitionArtifact);
                    }

                    if (artifacts.Any())
                    {
                        partitionRun.Artifacts = artifacts;
                    }

                    partitionLog.Runs.Add(partitionRun);
                }
            }

            // Traverse the entire log, fixing the index mappings for indices that appear
            // in the remapping dictionaries.
            var remappingVisitor = new PartitionedIndexRemappingVisitor(artifactIndexRemappingDictionaries);

            remappingVisitor.VisitSarifLog(partitionLog);

            return(partitionLog);
        }
 protected override void Analyze(SarifLog log, string logPointer)
 {
     AnalyzeUri(log.SchemaUri, logPointer.AtProperty(SarifPropertyName.Schema));
 }
Пример #22
0
        private void TestWorkItemFiler(SarifLog sarifLog, SarifWorkItemContext context, bool adoClient)
        {
            // ONE. Create test data that the low-level ADO client mocks
            //      will flow back to the SARIF work item filer.
            var attachmentReference = new AttachmentReference()
            {
                Id  = Guid.NewGuid(),
                Url = Guid.NewGuid().ToString()
            };

            var workItem = new WorkItem
            {
                Id    = DateTime.UtcNow.Millisecond,
                Links = new ReferenceLinks()
            };

            // The fake URI to the filed item that we'll expect the filer to receive
            string bugUriText     = "https://example.com/" + Guid.NewGuid().ToString();
            string bugHtmlUriText = "https://example.com/" + Guid.NewGuid().ToString();

            Uri bugUri     = new Uri(bugUriText, UriKind.RelativeOrAbsolute);
            Uri bugHtmlUri = new Uri(bugHtmlUriText, UriKind.RelativeOrAbsolute);

            workItem.Url = bugUriText;
            workItem.Links.AddLink("html", bugHtmlUriText);

            // TWO. Reset variables to capture whether we enter all expected client methods.
            ConnectCalled        = false;
            CreateWorkItemCalled = CreateAttachmentCount = UpdateIssueCount = 0;

            // THREE. Create a default mock SARIF filer and client.
            SarifWorkItemFiler filer = CreateMockSarifWorkItemFiler(context).Object;

            // FOUR. Based on which client we are using (ADO or GitHub), create the correct context.
            //       This implies created both the connection mocks and the mocks for filing, updating, and attaching work items.
            //       We are required to put this mock behind an interface due to an inability to mock these types directly.

            FilingClient filingClient;

            if (adoClient == true)
            {
                filingClient = CreateAdoMocksAndFilingClient(attachmentReference, workItem, filer);
            }
            else
            {
                filingClient = CreateGitHubMocksAndFilingClient(bugUriText, bugHtmlUriText, filer);
            }

            string   sarifLogText    = JsonConvert.SerializeObject(sarifLog);
            SarifLog updatedSarifLog = filer.FileWorkItems(sarifLogText);

            // Did we see all the execution we expected?
            ConnectCalled.Should().BeTrue();

            int expectedWorkItemsCount = context.GetProperty(ExpectedWorkItemsCount);

            CreateWorkItemCalled.Should().Be(expectedWorkItemsCount);
            CreateAttachmentCount.Should().Be(adoClient ? expectedWorkItemsCount : 0);

            // This property is a naive mechanism to ensure that the code
            // executed comprehensively (i.e., that execution was not limited
            // due to unhandled exceptions). This is required because we have
            // not really implemented a proper async API with appropriate handling
            // for exceptions and other negative conditions. I wouldn't expect this
            // little helper to survive but it closes the loop for the current
            // rudimentary in-flight implementation.
            filer.FilingResult.Should().Be(FilingResult.Succeeded);

            filer.FiledWorkItems.Count.Should().Be(expectedWorkItemsCount);

            foreach (WorkItemModel filedWorkItem in filer.FiledWorkItems)
            {
                // Finally, make sure that our test data flows back properly through the filer.

                filedWorkItem.Attachment.Should().NotBeNull();
                JsonConvert.SerializeObject(filedWorkItem.Attachment.Text).Should().NotBeNull();

                filedWorkItem.Uri.Should().Be(bugUri);
                filedWorkItem.HtmlUri.Should().Be(bugHtmlUri);
            }

            // Validate that we updated the SARIF log with work itme URIs.
            //
            updatedSarifLog.Should().NotBeEquivalentTo(sarifLog);

            foreach (Run run in updatedSarifLog.Runs)
            {
                foreach (Result result in run.Results)
                {
                    result.WorkItemUris.Should().NotBeNull();
                    result.WorkItemUris.Count.Should().Be(1);
                    result.WorkItemUris[0].Should().Be(bugHtmlUri);

                    result.TryGetProperty(SarifWorkItemFiler.PROGRAMMABLE_URIS_PROPERTY_NAME, out List <Uri> programmableUris)
                    .Should().BeTrue();

                    programmableUris.Should().NotBeNull();
                    programmableUris.Count.Should().Be(1);
                    programmableUris[0].Should().Be(bugUri);
                }
            }
        }
Пример #23
0
        private static void WriteResultToSarifLog(string inputPath, StreamWriter outputStream, SarifLog log, MethodDefinition moveNextMethod, DependencyPTGDomain depAnalysisResult,
                                                  SongTaoDependencyAnalysis dependencyAnalysis, IDictionary <string, ClassDefinition> processorMap)
        {
            var results = new List <Result>();

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


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

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

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

            AddRunToSarifOutput(log, inputPath, id, results);
        }
Пример #24
0
        public int Run(ResultMatchSetOptions options)
        {
            int returnCode = SUCCESS;

            options.OutputFolderPath = options.OutputFolderPath ?? Path.Combine(options.FolderPath, "Out");

            ISarifLogMatcher matcher    = ResultMatchingBaselinerFactory.GetDefaultResultMatchingBaseliner();
            Formatting       formatting = options.PrettyPrint ? Formatting.Indented : Formatting.None;

            // Remove previous results.
            if (_fileSystem.DirectoryExists(options.OutputFolderPath) && options.Force)
            {
                _fileSystem.DeleteDirectory(options.OutputFolderPath, true);
            }

            // Create output folder.
            _fileSystem.CreateDirectory(options.OutputFolderPath);

            string   previousFileName = "";
            string   previousGroup = "";
            SarifLog previousLog = null, currentLog = null;

            foreach (string filePath in Directory.GetFiles(options.FolderPath, "*.sarif"))
            {
                string fileName     = Path.GetFileName(filePath);
                string currentGroup = GetGroupName(fileName);

                try
                {
                    currentLog = ReadSarifFile <SarifLog>(_fileSystem, filePath);

                    // Compare each log with the previous one in the same group.
                    if (currentGroup.Equals(previousGroup) && currentLog?.Runs?[0]?.Results.Count != 0 && previousLog?.Runs?[0]?.Results.Count != 0)
                    {
                        Console.WriteLine();
                        Console.WriteLine($"{previousFileName} -> {fileName}:");
                        SarifLog mergedLog = matcher.Match(new[] { previousLog }, new[] { currentLog }).First();

                        // Write the same and different count and different IDs.
                        WriteDifferences(mergedLog);

                        // Write the log, if there were any changed results
                        if (mergedLog.Runs[0].Results.Any(r => r.BaselineState != BaselineState.Unchanged))
                        {
                            string outputFilePath = Path.Combine(options.OutputFolderPath, fileName);

                            if (DriverUtilities.ReportWhetherOutputFileCanBeCreated(outputFilePath, options.Force, _fileSystem))
                            {
                                WriteSarifFile(_fileSystem, mergedLog, outputFilePath, formatting);
                            }
                            else
                            {
                                returnCode = FAILURE;
                            }
                        }
                    }
                }
                catch (Exception ex) when(!Debugger.IsAttached)
                {
                    Console.WriteLine(ex.ToString());
                    returnCode = FAILURE;
                }

                previousFileName = fileName;
                previousGroup    = currentGroup;
                previousLog      = currentLog;
            }

            return(returnCode);
        }
Пример #25
0
 public OverallBaseliningTests()
 {
     SampleLog = GetLogFromResource(SampleFilePath);
 }
 public FeedbackModel(string ruleId, string toolName, string toolVersion, IEnumerable <string> snippets, FeedbackType feedbackType, string summary, SarifLog log)
 {
     this.RuleId       = ruleId;
     this.ToolName     = toolName;
     this.ToolVersion  = toolVersion;
     this.SendSnippet  = true;
     this.Snippets     = snippets;
     this.Comment      = string.Empty;
     this.FeedbackType = feedbackType;
     this.Summary      = summary;
     this.SarifLog     = log;
 }
Пример #27
0
        public void Overall_Identical()
        {
            SarifLog output = Baseline(SampleLog.DeepClone(), SampleLog.DeepClone());

            output.Runs[0].Results.Where(result => result.BaselineState != BaselineState.Unchanged).Should().BeEmpty();
        }
Пример #28
0
 protected virtual void Analyze(SarifLog log, string logPointer)
 {
 }
        protected override string ConstructTestOutputFromInputResource(string inputResourceName, object parameter)
        {
            PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(
                GetResourceText(inputResourceName),
                formatting: Formatting.Indented,
                out string transformedLog);

            SarifLog actualLog = PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(transformedLog, formatting: Formatting.None, out transformedLog);

            // For CoreTests only - this code rewrites the log persisted URI to match the test environment
            if (inputResourceName == "Inputs.CoreTests-Relative.sarif")
            {
                Uri    originalUri = actualLog.Runs[0].OriginalUriBaseIds["TESTROOT"].Uri;
                string uriString   = originalUri.ToString();

                string currentDirectory = Environment.CurrentDirectory;
                currentDirectory = currentDirectory.Substring(0, currentDirectory.IndexOf(@"\bld\"));
                uriString        = uriString.Replace("REPLACED_AT_TEST_RUNTIME", currentDirectory);

                actualLog.Runs[0].OriginalUriBaseIds["TESTROOT"] = new ArtifactLocation {
                    Uri = new Uri(uriString, UriKind.Absolute)
                };

                var visitor = new InsertOptionalDataVisitor(_currentOptionallyEmittedData);
                visitor.Visit(actualLog.Runs[0]);

                // Restore the remanufactured URI so that file diffing matches
                actualLog.Runs[0].OriginalUriBaseIds["TESTROOT"] = new ArtifactLocation {
                    Uri = originalUri
                };
            }
            else if (inputResourceName == "Inputs.CoreTests-Absolute.sarif")
            {
                Uri    originalUri = actualLog.Runs[0].Artifacts[0].Location.Uri;
                string uriString   = originalUri.ToString();

                string currentDirectory = Environment.CurrentDirectory;
                currentDirectory = currentDirectory.Substring(0, currentDirectory.IndexOf(@"\bld\"));
                uriString        = uriString.Replace("REPLACED_AT_TEST_RUNTIME", currentDirectory);

                actualLog.Runs[0].Artifacts[0].Location = new ArtifactLocation {
                    Uri = new Uri(uriString, UriKind.Absolute)
                };

                var visitor = new InsertOptionalDataVisitor(_currentOptionallyEmittedData);
                visitor.Visit(actualLog.Runs[0]);

                // Restore the remanufactured URI so that file diffing matches
                actualLog.Runs[0].Artifacts[0].Location = new ArtifactLocation {
                    Uri = originalUri
                };
            }
            else
            {
                var visitor = new InsertOptionalDataVisitor(_currentOptionallyEmittedData);
                visitor.Visit(actualLog.Runs[0]);
            }

            // Verify and remove Guids, because they'll vary with every run and can't be compared to a fixed expected output
            if (_currentOptionallyEmittedData.HasFlag(OptionallyEmittedData.Guids))
            {
                for (int i = 0; i < actualLog.Runs[0].Results.Count; ++i)
                {
                    Result result = actualLog.Runs[0].Results[i];
                    if (String.IsNullOrEmpty(result.Guid))
                    {
                        Assert.True(false, $"Results[{i}] had no Guid assigned, but OptionallyEmittedData.Guids flag was set.");
                    }

                    result.Guid = null;
                }
            }

            return(JsonConvert.SerializeObject(actualLog, Formatting.Indented));
        }
Пример #30
0
        public int Run(TransformOptions transformOptions)
        {
            try
            {
                if (transformOptions.SarifOutputVersion != SarifVersion.OneZeroZero && transformOptions.SarifOutputVersion != SarifVersion.Current)
                {
                    Console.WriteLine(MultitoolResources.ErrorInvalidTransformTargetVersion);
                    return(1);
                }

                OptionallyEmittedData dataToInsert = transformOptions.DataToInsert.ToFlags();

                // NOTE: we don't actually utilize the dataToInsert command-line data yet...

                string fileName = CommandUtilities.GetTransformedOutputFileName(transformOptions);

                var formatting = transformOptions.PrettyPrint
                    ? Formatting.Indented
                    : Formatting.None;


                string inputFilePath = transformOptions.InputFilePath;
                string inputVersion  = SniffVersion(inputFilePath);

                // If the user wants to transform to current v2, we check to see whether the input
                // file is v2 or pre-release v2. We upgrade both formats to current v2.
                //
                // Correspondingly, if the input file is v2 of any kind, we first ensure that it is
                // current v2, then drop it down to v1.
                //
                // We do not support transforming to any obsoleted pre-release v2 formats.
                if (transformOptions.SarifOutputVersion == SarifVersion.Current)
                {
                    if (inputVersion == "1.0.0")
                    {
                        SarifLogVersionOne actualLog = ReadSarifFile <SarifLogVersionOne>(_fileSystem, transformOptions.InputFilePath, SarifContractResolverVersionOne.Instance);
                        var visitor = new SarifVersionOneToCurrentVisitor();
                        visitor.VisitSarifLogVersionOne(actualLog);
                        WriteSarifFile(_fileSystem, visitor.SarifLog, fileName, formatting);
                    }
                    else
                    {
                        // We have a pre-release v2 file that we should upgrade to current.
                        PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(
                            _fileSystem.ReadAllText(inputFilePath),
                            formatting: formatting,
                            out string sarifText);

                        _fileSystem.WriteAllText(fileName, sarifText);
                    }
                }
                else
                {
                    if (inputVersion == "1.0.0")
                    {
                        SarifLogVersionOne logV1 = ReadSarifFile <SarifLogVersionOne>(_fileSystem, transformOptions.InputFilePath, SarifContractResolverVersionOne.Instance);
                        logV1.SchemaUri = SarifVersion.OneZeroZero.ConvertToSchemaUri();
                        WriteSarifFile(_fileSystem, logV1, fileName, formatting, SarifContractResolverVersionOne.Instance);
                    }
                    else
                    {
                        string currentSarifVersion = SarifUtilities.StableSarifVersion;

                        string   sarifText = _fileSystem.ReadAllText(inputFilePath);
                        SarifLog actualLog = null;

                        if (inputVersion != currentSarifVersion)
                        {
                            // Note that we don't provide formatting here. It is not required to indent the v2 SARIF - it
                            // will be transformed to v1 later, where we should apply the indentation settings.
                            actualLog = PrereleaseCompatibilityTransformer.UpdateToCurrentVersion(
                                sarifText,
                                formatting: Formatting.None,
                                out sarifText);
                        }
                        else
                        {
                            actualLog = JsonConvert.DeserializeObject <SarifLog>(sarifText);
                        }

                        var visitor = new SarifCurrentToVersionOneVisitor();
                        visitor.VisitSarifLog(actualLog);

                        WriteSarifFile(_fileSystem, visitor.SarifLogVersionOne, fileName, formatting, SarifContractResolverVersionOne.Instance);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return(1);
            }

            return(0);
        }
Пример #31
0
 /// <summary>
 /// Helper function that accepts a single baseline and current SARIF log and matches them.
 /// </summary>
 /// <param name="previousLog">Array of SARIF logs representing the baseline run</param>
 /// <param name="currentLog">Array of SARIF logs representing the current run</param>
 /// <returns>A SARIF log with the merged set of results.</returns>
 public SarifLog Match(SarifLog previousLog, SarifLog currentLog)
 {
     return(Match(previousLogs: new[] { previousLog }, currentLogs: new[] { currentLog }).FirstOrDefault());
 }
Пример #32
0
        public void ExtractAllArtifactLocationsVisitor_ExtractsMultipleLocations()
        {
            var sarifLog = new SarifLog
            {
                Runs = new[]
                {
                    new Run
                    {
                        Results = new[]
                        {
                            new Result
                            {
                                RuleId        = TestData.RuleIds.Rule1,
                                BaselineState = BaselineState.New,
                                Locations     = new []
                                {
                                    new Location
                                    {
                                        PhysicalLocation = new PhysicalLocation
                                        {
                                            ArtifactLocation = new ArtifactLocation
                                            {
                                                Uri = new Uri(TestData.FileLocations.Location1),
                                            }
                                        }
                                    }
                                }
                            },

                            new Result
                            {
                                RuleId        = TestData.RuleIds.Rule2,
                                BaselineState = BaselineState.Updated,
                                Locations     = new []
                                {
                                    new Location
                                    {
                                        PhysicalLocation = new PhysicalLocation
                                        {
                                            ArtifactLocation = new ArtifactLocation
                                            {
                                                Uri = new Uri(TestData.FileLocations.Location2),
                                            }
                                        }
                                    }
                                }
                            },

                            new Result
                            {
                                RuleId        = TestData.RuleIds.Rule2,
                                BaselineState = BaselineState.New,
                                Locations     = new []
                                {
                                    new Location
                                    {
                                        PhysicalLocation = new PhysicalLocation
                                        {
                                            ArtifactLocation = new ArtifactLocation
                                            {
                                                Uri = new Uri(TestData.FileLocations.Location3),
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            };

            var visitor = new ExtractAllArtifactLocationsVisitor();

            visitor.VisitSarifLog(sarifLog);
            visitor.AllArtifactLocations.Count.Should().Be(3);

            foreach (Result result in sarifLog.Runs[0].Results)
            {
                visitor.AllArtifactLocations.Contains(result.Locations[0].PhysicalLocation.ArtifactLocation).Should().BeTrue();
            }
        }