├── .gitignore ├── .nuget └── NuGet.exe ├── BuildAndTest.cmd ├── LICENSE ├── README.md ├── SECURITY.md └── src ├── Nuget └── Sarif.Driver.nuspec ├── Sarif.Driver.UnitTests ├── AnalyzeCommandTests.cs ├── ExceptionCondition.cs ├── ExceptionRaisingRule.cs ├── Properties │ └── AssemblyInfo.cs ├── Sarif.Driver.UnitTests.csproj ├── SarifHelpers.cs ├── TestAnalysisContext.cs ├── TestAnalyzeCommand.cs ├── TestAnalyzeOptions.cs ├── TestMessageLogger.cs └── packages.config ├── Sarif.Driver.sln ├── Sarif.Driver ├── ArgumentSplitter.cs ├── BrandedVersionAttribute.cs ├── Configuration │ ├── ConfigurationBase.cs │ ├── ConfigurationParseContext.cs │ ├── FieldAttribute.cs │ ├── FieldTypes.cs │ └── NoMinusAttribute.cs ├── DisposableEnumerable.cs ├── DisposableEnumerableView.cs ├── DriverResources.resx ├── EnumerableExtensions.cs ├── EnvironmentVariables.cs ├── ExceptionStrings.Designer.cs ├── ExceptionStrings.resx ├── FileSpecifier.cs ├── FileStreamExtensionMethods.cs ├── FileSystem.cs ├── IAppConfig.cs ├── IEnvironmentVariables.cs ├── IFileSystem.cs ├── KeyEventImportance.cs ├── LineInfo.cs ├── MultiplyByPrimesHash.cs ├── MurmurHash.cs ├── NewLineIndex.cs ├── OffsetInfo.cs ├── Pair.cs ├── PathExtensions.cs ├── Properties │ └── AssemblyInfo.cs ├── Ref.cs ├── ReferenceEqualityComparer`1.cs ├── RentalStream.cs ├── Sarif.Driver.csproj ├── Sdk │ ├── AggregatingLogger.cs │ ├── AnalysisApplicability.cs │ ├── AnalyzeCommandBase.cs │ ├── AnalyzeOptionsBase.cs │ ├── CompositionUtilities.cs │ ├── ConsoleLogger.cs │ ├── DriverCommand.cs │ ├── ErrorDescriptors.cs │ ├── ExitApplicationException.cs │ ├── ExitReason.cs │ ├── ExportConfigurationCommandBase.cs │ ├── ExportConfigurationOptions.cs │ ├── ExportRulesMetadataCommandBase.cs │ ├── ExportRulesMetadataOptions.cs │ ├── Hash.cs │ ├── IAnalysisContext.cs │ ├── IAnalyzeOptions.cs │ ├── IOption.cs │ ├── IOptionsProvider.cs │ ├── IResultLogger.cs │ ├── ISkimmer.cs │ ├── IntegerSet.cs │ ├── MessageUtilities.cs │ ├── NoteDescriptors.cs │ ├── PerLanguageOption.cs │ ├── PlugInDriverCommand.cs │ ├── PropertyBag.cs │ ├── PropertyBagExtensionMethods.cs │ ├── ResultLogger.cs │ ├── RuntimeConditions.cs │ ├── SarifLogger.cs │ ├── SdkResources.Designer.cs │ ├── SdkResources.resx │ ├── SkimmerBase.cs │ ├── StatisticsLogger.cs │ ├── StringSet.cs │ └── TypedPropertyBag.cs ├── SemanticVersion.cs ├── StringExtensions.cs ├── TempDirectory.cs ├── TempFile.cs ├── VersionConstants.cs ├── XmlWriterExtensions.cs └── packages.config └── build.props /.gitignore: -------------------------------------------------------------------------------- 1 | *.suo 2 | *.user 3 | *.userosscache 4 | *.sln.docstates 5 | 6 | # Build results 7 | bin/ 8 | obj/ 9 | src/packages/ 10 | src/TestResults -------------------------------------------------------------------------------- /.nuget/NuGet.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/driver-utilities/ca3e55bad0604d8e10a3aaf9a4efa1fc0c2c7d55/.nuget/NuGet.exe -------------------------------------------------------------------------------- /BuildAndTest.cmd: -------------------------------------------------------------------------------- 1 | SETLOCAL 2 | @REM Uncomment this line to update nuget.exe 3 | @REM Doing so can break SLN build (which uses nuget.exe to 4 | @REM create a nuget package for binskim) so must opt-in 5 | @REM %~dp0.nuget\NuGet.exe update -self 6 | 7 | set MAJOR=1 8 | set MINOR=0 9 | set PATCH=9 10 | set PRERELEASE=-beta 11 | 12 | set VERSION_CONSTANTS=src\Sarif.Driver\VersionConstants.cs 13 | 14 | rd /s /q bld 15 | 16 | @REM Rewrite VersionConstants.cs 17 | echo // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT > %VERSION_CONSTANTS% 18 | echo // license. See LICENSE file in the project root for full license information. >> %VERSION_CONSTANTS% 19 | echo namespace Microsoft.CodeAnalysis.Sarif >> %VERSION_CONSTANTS% 20 | echo { >> %VERSION_CONSTANTS% 21 | echo public static class VersionConstants >> %VERSION_CONSTANTS% 22 | echo { >> %VERSION_CONSTANTS% 23 | echo public const string Prerelease = "%PRERELEASE%"; >> %VERSION_CONSTANTS% 24 | echo public const string AssemblyVersion = "%MAJOR%.%MINOR%.%PATCH%"; >> %VERSION_CONSTANTS% 25 | echo public const string FileVersion = AssemblyVersion + ".0"; >> %VERSION_CONSTANTS% 26 | echo public const string Version = AssemblyVersion + Prerelease; >> %VERSION_CONSTANTS% 27 | echo } >> %VERSION_CONSTANTS% 28 | echo } >> %VERSION_CONSTANTS% 29 | 30 | %~dp0.nuget\NuGet.exe restore src\Sarif.Driver.sln 31 | msbuild /verbosity:minimal /target:rebuild src\Sarif.Driver.sln /p:Configuration=Release 32 | 33 | md bld\bin\nuget 34 | 35 | .nuget\NuGet.exe pack .\src\Nuget\Sarif.Driver.nuspec -Symbols -Properties id=Sarif.Driver;major=%MAJOR%;minor=%MINOR%;patch=%PATCH%;prerelease=%PRERELEASE% -Verbosity Quiet -BasePath .\bld\bin\Sarif.Driver\AnyCPU_Release\ -OutputDirectory .\bld\bin\Nuget 36 | 37 | src\packages\xunit.runner.console.2.1.0\tools\xunit.console.x86.exe bld\bin\Sarif.Driver.UnitTests\AnyCPU_Release\Sarif.Driver.UnitTests.dll 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Microsoft Driver Utilities 2 | 3 | Copyright (c) Microsoft Corporation 4 | 5 | All rights reserved. 6 | 7 | MIT License 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ""Software""), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 14 | THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # driver-utilities 2 | Driver utilities for building static analysis and other command-line tools. 3 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/Nuget/Sarif.Driver.nuspec: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $id$ 5 | $major$.$minor$.$patch$$prerelease$ 6 | Microsoft SARIF Driver Framework (includes SARIF SDK) 7 | Microsoft 8 | Michael C. Fanning, Billy O'Neal 9 | false 10 | SARIF-based classes and utilities for building static analysis drivers. Includes the SARIF SDK. 11 | Version $major$.$minor$.$patch$$prerelease$ of the Microsoft SARIF Driver Utilities 12 | Copyright Microsoft 2015 13 | https://github.com/Microsoft/driver-utilities/blob/master/LICENSE 14 | https://github.com/microsoft/driver-utilities 15 | command line driver utilities static analysis sarif framework utils driver.utilities 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/ExceptionCondition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 5 | { 6 | public enum ExceptionCondition 7 | { 8 | None, 9 | AccessingId, 10 | AccessingName, 11 | InvokingConstructor, 12 | InvokingAnalyze, 13 | InvokingCanAnalyze, 14 | InvokingInitialize 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/ExceptionRaisingRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.CodeAnalysis.Sarif.Sdk; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | internal class ExceptionRaisingRule : IRuleDescriptor, ISkimmer 11 | { 12 | internal static ExceptionCondition s_exceptionCondition; 13 | 14 | private ExceptionCondition _exceptionCondition; 15 | 16 | public ExceptionRaisingRule() 17 | { 18 | _exceptionCondition = s_exceptionCondition; 19 | 20 | if (_exceptionCondition == ExceptionCondition.InvokingConstructor) 21 | { 22 | throw new InvalidOperationException(nameof(ExceptionCondition.InvokingConstructor)); 23 | } 24 | } 25 | 26 | public string ExceptionRaisingRuleId = "TEST1001"; 27 | 28 | public string Id 29 | { 30 | get 31 | { 32 | if (_exceptionCondition == ExceptionCondition.AccessingId) 33 | { 34 | throw new InvalidOperationException(nameof(ExceptionCondition.AccessingId)); 35 | } 36 | return ExceptionRaisingRuleId; 37 | } 38 | } 39 | 40 | public string Name 41 | { 42 | get 43 | { 44 | if (_exceptionCondition == ExceptionCondition.AccessingName) 45 | { 46 | throw new InvalidOperationException(nameof(ExceptionCondition.AccessingName)); 47 | } 48 | return nameof(ExceptionRaisingRule); 49 | } 50 | } 51 | 52 | public string FullDescription 53 | { 54 | get { return "Test Rule Description"; } 55 | } 56 | 57 | public string ShortDescription 58 | { 59 | get 60 | { 61 | throw new NotImplementedException(); 62 | } 63 | } 64 | 65 | public Dictionary Options 66 | { 67 | get 68 | { 69 | throw new NotImplementedException(); 70 | } 71 | } 72 | 73 | public Dictionary FormatSpecifiers 74 | { 75 | get 76 | { 77 | throw new NotImplementedException(); 78 | } 79 | } 80 | 81 | public Dictionary Properties 82 | { 83 | get 84 | { 85 | throw new NotImplementedException(); 86 | } 87 | } 88 | 89 | public void Analyze(TestAnalysisContext context) 90 | { 91 | if (_exceptionCondition == ExceptionCondition.InvokingAnalyze) 92 | { 93 | throw new InvalidOperationException(nameof(ExceptionCondition.InvokingAnalyze)); 94 | } 95 | } 96 | 97 | public AnalysisApplicability CanAnalyze(TestAnalysisContext context, out string reasonIfNotApplicable) 98 | { 99 | reasonIfNotApplicable = null; 100 | if (_exceptionCondition == ExceptionCondition.InvokingCanAnalyze) 101 | { 102 | throw new InvalidOperationException(nameof(ExceptionCondition.InvokingCanAnalyze)); 103 | } 104 | return AnalysisApplicability.ApplicableToSpecifiedTarget; 105 | } 106 | 107 | public void Initialize(TestAnalysisContext context) 108 | { 109 | if (_exceptionCondition == ExceptionCondition.InvokingInitialize) 110 | { 111 | throw new InvalidOperationException(nameof(ExceptionCondition.InvokingInitialize)); 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Reflection; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("Sarif Driver Utilities Unit Tests")] 10 | [assembly: AssemblyDescription("Unit tests for the SARIF driver utilities framework")] 11 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/Sarif.Driver.UnitTests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {66915F7B-9872-4390-AFED-DB8DE7B761BE} 6 | 7 | 8 | 9 | 10 | Microsoft.CodeAnalysis.Driver 11 | 12 | 13 | Sarif.Driver.UnitTests 14 | 15 | 16 | Library 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | ..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll 25 | True 26 | 27 | 28 | ..\packages\Sarif.Sdk.1.4.10-beta\lib\net40\Sarif.dll 29 | True 30 | 31 | 32 | 33 | ..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll 34 | True 35 | 36 | 37 | 38 | 39 | 40 | ..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll 41 | True 42 | 43 | 44 | ..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll 45 | True 46 | 47 | 48 | ..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll 49 | True 50 | 51 | 52 | ..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll 53 | True 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | {8ceaea61-b1a2-4777-bcbe-c9a129a5f6c5} 76 | Sarif.Driver 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/SarifHelpers.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.Sdk; 7 | 8 | using Xunit; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 11 | { 12 | internal static class SarifHelpers 13 | { 14 | public static void ValidateRunLog(RunLog runLog, Action resultAction) 15 | { 16 | ValidateToolInfo(runLog.ToolInfo); 17 | 18 | foreach (Result result in runLog.Results) { resultAction(result); } 19 | } 20 | 21 | public static void ValidateToolInfo(ToolInfo toolInfo) 22 | { 23 | Assert.Equal("Sarif.Driver", toolInfo.Name); 24 | // TODO version, etc 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/TestAnalysisContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using Microsoft.CodeAnalysis.Sarif.Sdk; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 8 | { 9 | public class TestAnalysisContext : IAnalysisContext 10 | { 11 | public bool IsValidAnalysisTarget { get; set; } 12 | 13 | public IResultLogger Logger { get; set; } 14 | 15 | public PropertyBag Policy { get; set; } 16 | 17 | public IRuleDescriptor Rule { get; set; } 18 | 19 | public Exception TargetLoadException { get; set; } 20 | 21 | public Uri TargetUri { get; set; } 22 | 23 | public void Dispose() 24 | { 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/TestAnalyzeCommand.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 8 | { 9 | public class TestAnalyzeCommand : AnalyzeCommandBase 10 | { 11 | public override IEnumerable DefaultPlugInAssemblies { get; set; } 12 | 13 | public override string Prerelease { get { return ""; } } 14 | 15 | protected override TestAnalysisContext CreateContext(TestAnalyzeOptions options, IResultLogger logger, PropertyBag policy, string filePath = null) 16 | { 17 | var context = base.CreateContext(options, logger, policy, filePath); 18 | context.IsValidAnalysisTarget = options.RegardAnalysisTargetAsValid; 19 | return context; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/TestAnalyzeOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | public class TestAnalyzeOptions : IAnalyzeOptions 9 | { 10 | public TestAnalyzeOptions() 11 | { 12 | RegardAnalysisTargetAsValid = true; 13 | } 14 | 15 | public bool ComputeTargetsHash { get; set; } 16 | 17 | public string OutputFilePath { get; set; } 18 | 19 | public IList PlugInFilePaths { get; set; } 20 | 21 | 22 | public string PolicyFilePath { get; set; } 23 | 24 | public bool Recurse { get; set; } 25 | 26 | public bool Statistics { get; set; } 27 | 28 | public IEnumerable TargetFileSpecifiers { get; set; } 29 | 30 | public bool Verbose { get; set; } 31 | 32 | public bool RegardAnalysisTargetAsValid { get; set; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/TestMessageLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.CodeAnalysis.Sarif.Sdk; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | internal class TestMessageLogger : IResultLogger 11 | { 12 | public TestMessageLogger() 13 | { 14 | FailTargets = new HashSet(); 15 | PassTargets = new HashSet(); 16 | NotApplicableTargets = new HashSet(); 17 | } 18 | 19 | public HashSet PassTargets { get; set; } 20 | 21 | public HashSet FailTargets { get; set; } 22 | 23 | public HashSet NotApplicableTargets { get; set; } 24 | 25 | public void Log(ResultKind messageKind, IAnalysisContext context, string message) 26 | { 27 | switch (messageKind) 28 | { 29 | case ResultKind.Pass: 30 | { 31 | PassTargets.Add(context.TargetUri.LocalPath); 32 | break; 33 | } 34 | 35 | case ResultKind.Error: 36 | { 37 | FailTargets.Add(context.TargetUri.LocalPath); 38 | break; 39 | } 40 | 41 | case ResultKind.NotApplicable: 42 | { 43 | NotApplicableTargets.Add(context.TargetUri.LocalPath); 44 | break; 45 | } 46 | 47 | case ResultKind.Note: 48 | case ResultKind.InternalError: 49 | case ResultKind.ConfigurationError: 50 | { 51 | throw new NotImplementedException(); 52 | } 53 | default: 54 | { 55 | throw new InvalidOperationException(); 56 | } 57 | } 58 | } 59 | 60 | public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message) 61 | { 62 | throw new NotImplementedException(); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /src/Sarif.Driver.UnitTests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/Sarif.Driver.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sarif.Driver", "Sarif.Driver\Sarif.Driver.csproj", "{8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sarif.Driver.UnitTests", "Sarif.Driver.UnitTests\Sarif.Driver.UnitTests.csproj", "{66915F7B-9872-4390-AFED-DB8DE7B761BE}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|x64 = Debug|x64 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Debug|x64.ActiveCfg = Debug|x64 23 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Debug|x64.Build.0 = Debug|x64 24 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Debug|x86.ActiveCfg = Debug|x86 25 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Debug|x86.Build.0 = Debug|x86 26 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Release|x64.ActiveCfg = Release|x64 29 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Release|x64.Build.0 = Release|x64 30 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Release|x86.ActiveCfg = Release|x86 31 | {8CEAEA61-B1A2-4777-BCBE-C9A129A5F6C5}.Release|x86.Build.0 = Release|x86 32 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Debug|x64.ActiveCfg = Debug|x64 35 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Debug|x64.Build.0 = Debug|x64 36 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Debug|x86.ActiveCfg = Debug|x86 37 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Debug|x86.Build.0 = Debug|x86 38 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Release|x64.ActiveCfg = Release|x64 41 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Release|x64.Build.0 = Release|x64 42 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Release|x86.ActiveCfg = Release|x86 43 | {66915F7B-9872-4390-AFED-DB8DE7B761BE}.Release|x86.Build.0 = Release|x86 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | EnterpriseLibraryConfigurationToolBinariesPathV6 = packages\EnterpriseLibrary.TransientFaultHandling.6.0.1304.0\lib\portable-net45+win+wp8;packages\EnterpriseLibrary.TransientFaultHandling.Data.6.0.1304.1\lib\NET45 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /src/Sarif.Driver/ArgumentSplitter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Text; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver 9 | { 10 | /// This class contains argument splitting functionality. 11 | public static class ArgumentSplitter 12 | { 13 | private enum WhitespaceMode 14 | { 15 | Ignore, 16 | PartOfArgument, 17 | EndArgument 18 | } 19 | 20 | /// 21 | /// Mimics CommandLineToArgvW's argument splitting behavior, plus bug fixes. 22 | /// 23 | /// The command line to split into arguments. 24 | /// The values of the arguments supplied in the input. 25 | public static List CommandLineToArgvW(string input) 26 | { 27 | // This function mimics CommandLineToArgvW's escaping behavior, documented here: 28 | // http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391.aspx 29 | 30 | // 31 | // We used to P/Invoke to the real CommandLineToArgvW, but re-implement it here 32 | // as a workaround for the following: 33 | // 34 | // * CommandLineToArgvW does not treat newlines as whitespace (twcsec-tfs01 bug # 17291) 35 | // * CommandLineToArgvW returns the executable name for the empty string, not the empty set 36 | // * CommandLineToArgvW chokes on leading whitespace (twcsec-tfs01 bug# 17378) 37 | // 38 | // and as a result of the above we expect to find more nasty edge cases in the future. 39 | // 40 | 41 | if (input == null) 42 | { 43 | throw new ArgumentNullException("input"); 44 | } 45 | 46 | WhitespaceMode whitespaceMode = WhitespaceMode.Ignore; 47 | int slashCount = 0; 48 | 49 | var result = new List(); 50 | var sb = new StringBuilder(); 51 | 52 | foreach (char c in input) 53 | { 54 | if (whitespaceMode == WhitespaceMode.Ignore && Char.IsWhiteSpace(c)) 55 | { 56 | // Purposely do nothing 57 | } 58 | else if (whitespaceMode == WhitespaceMode.EndArgument && Char.IsWhiteSpace(c)) 59 | { 60 | AddSlashes(sb, ref slashCount); 61 | EmitArgument(result, sb); 62 | whitespaceMode = WhitespaceMode.Ignore; 63 | } 64 | else if (c == '\\') 65 | { 66 | ++slashCount; 67 | if (whitespaceMode == WhitespaceMode.Ignore) 68 | { 69 | whitespaceMode = WhitespaceMode.EndArgument; 70 | } 71 | } 72 | else if (c == '\"') 73 | { 74 | bool quoteIsEscaped = (slashCount & 1) == 1; 75 | slashCount >>= 1; // Using >> to avoid C# bankers rounding 76 | // 2n backslashes followed by a quotation mark produce n slashes followed by a quotation mark 77 | AddSlashes(sb, ref slashCount); 78 | 79 | if (quoteIsEscaped) 80 | { 81 | sb.Append(c); 82 | } 83 | else if (whitespaceMode == WhitespaceMode.PartOfArgument) 84 | { 85 | whitespaceMode = WhitespaceMode.EndArgument; 86 | } 87 | else 88 | { 89 | whitespaceMode = WhitespaceMode.PartOfArgument; 90 | } 91 | } 92 | else 93 | { 94 | AddSlashes(sb, ref slashCount); 95 | sb.Append(c); 96 | if (whitespaceMode == WhitespaceMode.Ignore) 97 | { 98 | whitespaceMode = WhitespaceMode.EndArgument; 99 | } 100 | } 101 | } 102 | 103 | AddSlashes(sb, ref slashCount); 104 | if (sb.Length != 0) 105 | { 106 | EmitArgument(result, sb); 107 | } 108 | 109 | return result; 110 | } 111 | 112 | private static void EmitArgument(List result, StringBuilder sb) 113 | { 114 | result.Add(sb.ToString()); 115 | sb.Clear(); 116 | } 117 | 118 | private static void AddSlashes(StringBuilder sb, ref int slashCount) 119 | { 120 | sb.Append('\\', slashCount); 121 | slashCount = 0; 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Sarif.Driver/BrandedVersionAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver 7 | { 8 | /// Attribute for branded version information. 9 | /// 10 | [AttributeUsage(AttributeTargets.Assembly)] 11 | public sealed class BrandedVersionAttribute : Attribute 12 | { 13 | /// 14 | /// Initializes a new instance of the class. 15 | /// 16 | /// The branded version. 17 | public BrandedVersionAttribute(string brandedVersion) 18 | { 19 | this.BrandedVersion = brandedVersion; 20 | } 21 | 22 | /// 23 | /// Gets the branded version for the assembly. For example, externally shipping assemblies are 24 | /// typically branded with a year instead of the SDL version. 25 | /// 26 | /// The branded version. 27 | public string BrandedVersion { get; private set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Configuration/ConfigurationParseContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Configuration 10 | { 11 | internal class ConfigurationParseContext 12 | { 13 | public readonly Dictionary> MultipleUseArgumentValues = new Dictionary>(); 14 | public readonly HashSet FlagsSetOnCommandLine = new HashSet(); 15 | public readonly HashSet FlagsSetInConfigurationFile = new HashSet(); 16 | private readonly Dictionary _errors = new Dictionary(StringComparer.OrdinalIgnoreCase); 17 | 18 | public void AddConfigurationError(string argument, string errorCondition) 19 | { 20 | // Configuration errors take lower priority; the console always wins. 21 | if (!_errors.ContainsKey(argument)) 22 | { 23 | _errors.Add(argument, new ErrorEntry { Source = ErrorSource.ConfigurationFile, ErrorText = errorCondition }); 24 | } 25 | } 26 | 27 | public void RemoveConfigurationError(string argument) 28 | { 29 | // This happens when a bad configuration error is overridden by a good command line option. 30 | ErrorEntry configError; 31 | if (_errors.TryGetValue(argument, out configError) && configError.Source == ErrorSource.ConfigurationFile) 32 | { 33 | _errors.Remove(argument); 34 | } 35 | } 36 | 37 | public void AddCommandLineError(string argument, string errorCondition) 38 | { 39 | ErrorEntry configError; 40 | if (!_errors.TryGetValue(argument, out configError)) 41 | { 42 | // No previous error for that argument 43 | _errors.Add(argument, new ErrorEntry { Source = ErrorSource.CommandLine, ErrorText = errorCondition }); 44 | } 45 | else if (configError.Source == ErrorSource.ConfigurationFile) 46 | { 47 | // Previous error for that argument was a configuration file error; 48 | // pave over it 49 | configError.Source = ErrorSource.CommandLine; 50 | configError.ErrorText = errorCondition; 51 | } 52 | // Otherwise there was a previous error with source == CommandLine, so do nothing. 53 | } 54 | 55 | public Dictionary GenerateErrorDictionary() 56 | { 57 | return _errors.ToDictionary(x => x.Key, x => x.Value.ErrorText, StringComparer.OrdinalIgnoreCase); 58 | } 59 | 60 | public void RemoveAllErrors() 61 | { 62 | _errors.Clear(); 63 | } 64 | 65 | private enum ErrorSource 66 | { 67 | CommandLine, 68 | ConfigurationFile 69 | } 70 | 71 | private class ErrorEntry 72 | { 73 | public ErrorSource Source { get; set; } 74 | public string ErrorText { get; set; } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Configuration/FieldAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Configuration 7 | { 8 | /// 9 | /// Attribute for specifying a configuration field. Allows the field to be made required, and allows override of the field name, short name, and validation method. 10 | /// 11 | /// 12 | [AttributeUsage(AttributeTargets.Property)] 13 | public sealed class FieldAttribute : Attribute 14 | { 15 | /// Initializes a new instance of the FieldAttribute class. 16 | public FieldAttribute() 17 | { 18 | } 19 | 20 | /// Gets or sets the name of the field. 21 | /// The name of the field. 22 | public string Name { get; set; } 23 | 24 | /// Gets or sets the short form of the name of the field. 25 | /// The short form of the name of the field. 26 | public string ShortName { get; set; } 27 | 28 | /// Gets or sets the usage, or help text. 29 | /// The usage, or help text. 30 | public string Usage { get; set; } 31 | 32 | /// Gets or sets the type, or option flags, on the field. 33 | /// The type / option flags of the field. 34 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "GetType() is inherited from System.Object and cannot be removed.")] 35 | public FieldTypes Type { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Configuration/FieldTypes.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Configuration 7 | { 8 | /// 9 | /// Specify fields 10 | /// 11 | [Flags] 12 | public enum FieldTypes 13 | { 14 | /// The default, specifies that the given field is optional. 15 | None = 0x00, 16 | Optional = None, 17 | 18 | /// 19 | /// Indicates that this field is required. An error will be displayed 20 | /// if it is not present when parsing arguments. 21 | /// 22 | Required = 0x01, 23 | 24 | /// 25 | /// Default field--if values in command line are not preceded by an arg, they're parsed as this field 26 | /// 27 | Default = 0x02, 28 | 29 | /// 30 | /// This field will not be described in the usage summary. 31 | /// 32 | Hidden = 0x04, 33 | 34 | /// 35 | /// Show the field on the CLI, but do not parse it from or save it to the XML, or place it in the schema. If CliOnly & Required, an error will not be raised if the parameter is missing from an XML config. 36 | /// 37 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Cli", Justification = "This is spelled correctly.")] 38 | CliOnly = 0x08 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Configuration/NoMinusAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Configuration 7 | { 8 | /// 9 | /// This attribute disables the generated "minus" version of a given flag 10 | /// in ConfigurationParser. 11 | /// 12 | /// 13 | [AttributeUsage(AttributeTargets.Property)] 14 | public sealed class NoMinusAttribute : Attribute 15 | { 16 | /// 17 | /// Initializes a new instance of the NoMinusAttribute class. 18 | /// 19 | public NoMinusAttribute() 20 | { 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Sarif.Driver/DisposableEnumerable.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver 9 | { 10 | /// A wrapper for enumerables of disposable objects that ensures that they are 11 | /// destroyed as they are produced. 12 | /// This wrapper breaks several of the built in 13 | /// extension methods that attempt to copy elements into backing collections, such as 14 | /// . Callers must be 15 | /// informed of the consequences of not being able to copy elements or references to elements 16 | /// as usual. 17 | /// Note however that most of these mechanisms are not safe to use if the underlying 18 | /// type is disposable, because they remove elements from the source stream that the caller 19 | /// would need to dispose. 20 | /// Note that this class should only be used for enumerables that "stream" their 21 | /// elements and produce new disposable values when reset or similar. If you create one of 22 | /// these wrappers around a collection that actually owns the disposable item, such as 23 | /// , enumerating the collection will destroy the collection's 24 | /// contents (which is not what the caller expects). 25 | /// The type wrapped in this enumerable. 26 | /// 27 | [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] //Justification: This isn't actually a collection type. 28 | public sealed class DisposableEnumerable : IEnumerable> 29 | where T : IDisposable 30 | { 31 | private readonly IEnumerable _backingEnumerable; 32 | 33 | /// Initializes a new instance of the class. 34 | /// An enumerable implementation that this instance will wrap. 35 | public DisposableEnumerable(IEnumerable backingEnumerable) 36 | { 37 | _backingEnumerable = backingEnumerable; 38 | } 39 | 40 | /// Gets an enumerator to walk a view of the underlying collection. 41 | /// An enumerator that iterates over elements in this collection. 42 | public IEnumerator> GetEnumerator() 43 | { 44 | return new Enumerator(_backingEnumerable.GetEnumerator()); 45 | } 46 | 47 | /// Gets an enumerator to walk a view of the underlying collection. 48 | /// An enumerator that iterates over elements in this collection. 49 | System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 50 | { 51 | return this.GetEnumerator(); 52 | } 53 | 54 | private sealed class Enumerator : IEnumerator> 55 | { 56 | private readonly IEnumerator _backingEnumerator; 57 | private DisposableEnumerableView _current; 58 | 59 | private void DestroyCurrent() 60 | { 61 | if (_current != null) 62 | { 63 | _current.Destroy(); 64 | } 65 | 66 | _current = null; 67 | } 68 | 69 | public Enumerator(IEnumerator backingEnumerator) 70 | { 71 | _backingEnumerator = backingEnumerator; 72 | } 73 | 74 | public DisposableEnumerableView Current 75 | { 76 | get { return _current; } 77 | } 78 | 79 | public void Dispose() 80 | { 81 | this.DestroyCurrent(); 82 | _backingEnumerator.Dispose(); 83 | } 84 | 85 | object System.Collections.IEnumerator.Current 86 | { 87 | get { return _current; } 88 | } 89 | 90 | public bool MoveNext() 91 | { 92 | // The caller may have stashed a reference to the "view" away somewhere, so we need 93 | // to allocate a new view object. 94 | // The common use for this at the moment will be where T is a COM RCW class; and as 95 | // such one would expect construction / destruction of T to dwarf the 24 or 32 bytes 96 | // of GC overhead per element when iterating. (Particularly given that view objects 97 | // should be short lived and stay on ephemeral GC generations) 98 | // If GC profiling shows that DisposableEnumerableView objects are a lot of GC overhead, 99 | // one may need to replace this wrapper with something that sacrifices some amount of 100 | // safety for perf. 101 | 102 | this.DestroyCurrent(); 103 | if (_backingEnumerator.MoveNext()) 104 | { 105 | _current = new DisposableEnumerableView(_backingEnumerator.Current); 106 | return true; 107 | } 108 | 109 | return false; 110 | } 111 | 112 | public void Reset() 113 | { 114 | this.DestroyCurrent(); 115 | _backingEnumerator.Reset(); 116 | } 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Sarif.Driver/DisposableEnumerableView.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver 7 | { 8 | /// A view of a disposable object inside of a collection. 9 | /// The type of disposable object in the collection. 10 | public sealed class DisposableEnumerableView 11 | where T : IDisposable 12 | { 13 | private readonly T _value; 14 | // Using "nonOwning" rather than "owning" so that the default value, false, 15 | // is what we want most of the time. 16 | private bool _nonOwning; 17 | 18 | /// Initializes a new instance of the 19 | /// class that owns a value. 20 | /// The value this view wraps. 21 | public DisposableEnumerableView(T value) 22 | { 23 | _value = value; 24 | } 25 | 26 | /// Gets a non-owning reference to the element stored in this view. 27 | /// The underlying value in this view. 28 | /// Thrown if this view no longer owns 29 | /// the underlying value. 30 | public T Value 31 | { 32 | get 33 | { 34 | if (_nonOwning) 35 | { 36 | throw new InvalidOperationException(ExceptionStrings.NonOwningDisposableViewAccess); 37 | } 38 | 39 | return _value; 40 | } 41 | } 42 | 43 | /// Takes ownership of the underlying element stored in this view. 44 | /// Thrown if this view no longer owns the 45 | /// underlying value. 46 | /// A the underlying value in this view. 47 | public T StealValue() 48 | { 49 | if (_nonOwning) 50 | { 51 | throw new InvalidOperationException(ExceptionStrings.NonOwningDisposableViewAccess); 52 | } 53 | 54 | _nonOwning = true; 55 | return _value; 56 | } 57 | 58 | /// If this instance owns the underlying value, destroys (calls 59 | /// ) on the underlying value. 60 | internal void Destroy() 61 | { 62 | if (!_nonOwning && _value != null) 63 | { 64 | _value.Dispose(); 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Sarif.Driver/DriverResources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | A binary was not analyzed as the it does not appear to be a valid portable executable. 122 | 123 | 124 | No analyzer paths specified 125 | 126 | 127 | Application exited unexpectedly. 128 | 129 | 130 | An exception was raised during analysis: 131 | {0} 132 | 133 | -------------------------------------------------------------------------------- /src/Sarif.Driver/EnvironmentVariables.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver 7 | { 8 | /// 9 | /// A wrapper class for accessing environment variables. 10 | /// 11 | /// 12 | /// Clients should use this class rather than directly using the System.EnvironmentVariable 13 | /// class, so they can mock the IEnvironmentVariables interface in unit tests. 14 | /// 15 | public class EnvironmentVariables : IEnvironmentVariables 16 | { 17 | /// 18 | /// Replaces the name of each environment variable embedded in the specified string with 19 | /// the string equivalent of the value of the variable, then returns the resulting string. 20 | /// 21 | /// 22 | /// A string containing the names of zero or more environment variables. Each environment 23 | /// variable is quoted with the percent sign character (%). 24 | /// 25 | /// 26 | /// A string with each environment variable replaced by its value. 27 | /// 28 | public string ExpandEnvironmentVariables(string name) 29 | { 30 | return Environment.ExpandEnvironmentVariables(name); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Sarif.Driver/ExceptionStrings.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Line number supplied was out of range [1, numberOfLinesInFile + 1) 122 | 123 | 124 | Attempted to access a DisposableEnumerable which is non-owning. 125 | 126 | 127 | Invalid PREfast defect state. 128 | 129 | 130 | PREfast defects require a main SFA where the defect occurs 131 | 132 | 133 | Probability must be between 0.0 and 1.0, inclusive; or be unset. 134 | 135 | 136 | Rank must be between 0 and 10, inclusive; or be unset. 137 | 138 | 139 | PREfast defects require descriptions with content. 140 | 141 | 142 | PREfast defects require content in their defect code. 143 | 144 | 145 | The function line number must be strictly positive; files begin at line 1. 146 | 147 | 148 | KeyEvent ids must be strictly positive. 149 | 150 | 151 | SequenceNumber must be positive, or 0 to disable sequence numbering. 152 | 153 | 154 | The value cannot be negative. 155 | 156 | 157 | The value must be greater than or equal to 1. 158 | 159 | 160 | The local element name was not set. 161 | 162 | 163 | -------------------------------------------------------------------------------- /src/Sarif.Driver/FileSpecifier.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver 9 | { 10 | public class FileSpecifier 11 | { 12 | public FileSpecifier(string specifier, bool recurse = false, string filter = "") 13 | { 14 | _recurse = recurse; 15 | 16 | if (filter != "" && specifier.EndsWith(filter, StringComparison.OrdinalIgnoreCase)) 17 | filter = ""; 18 | 19 | _specifier = Path.Combine(specifier, filter); 20 | } 21 | 22 | private readonly bool _recurse; 23 | private readonly string _specifier; 24 | private List _files; 25 | private List _directories; 26 | 27 | public IList Files 28 | { 29 | get { return _files ?? BuildFiles(); } 30 | } 31 | 32 | public IList Directories 33 | { 34 | get { return _directories ?? BuildDirectories(); } 35 | } 36 | 37 | private List BuildDirectories() 38 | { 39 | BuildFilesAndDirectoriesList(); 40 | return _directories; 41 | } 42 | 43 | private List BuildFiles() 44 | { 45 | BuildFilesAndDirectoriesList(); 46 | return _files; 47 | } 48 | 49 | private void BuildFilesAndDirectoriesList() 50 | { 51 | string expandedSpecifier; 52 | 53 | _files = new List(); 54 | _directories = new List(); 55 | expandedSpecifier = Environment.ExpandEnvironmentVariables(_specifier); 56 | 57 | string computedFilter = Path.GetFileName(expandedSpecifier); 58 | 59 | if (-1 == computedFilter.IndexOf("*")) 60 | { 61 | computedFilter = null; 62 | } 63 | else 64 | { 65 | expandedSpecifier = Path.GetDirectoryName(expandedSpecifier.Substring(0, expandedSpecifier.Length - computedFilter.Length)); 66 | } 67 | 68 | if (File.Exists(expandedSpecifier)) 69 | { 70 | AddFileToList(expandedSpecifier); 71 | } 72 | else 73 | { 74 | string dir; 75 | dir = expandedSpecifier; 76 | 77 | if (!Directory.Exists(expandedSpecifier)) 78 | { 79 | dir = Path.GetDirectoryName(expandedSpecifier); 80 | computedFilter = Path.GetFileName(expandedSpecifier); 81 | } 82 | else 83 | { 84 | _directories.Add(expandedSpecifier); 85 | } 86 | AddFilesFromDirectory(dir, computedFilter); 87 | } 88 | } 89 | 90 | private void AddFilesFromDirectory(string dir, string filter) 91 | { 92 | if (filter == null) 93 | return; 94 | 95 | if (Directory.Exists(dir)) 96 | { 97 | foreach (string file in Directory.GetFiles(dir, filter)) 98 | { 99 | AddFileToList(file); 100 | } 101 | 102 | if (_recurse) 103 | { 104 | try 105 | { 106 | foreach (string subdir in Directory.GetDirectories(dir)) 107 | { 108 | AddFilesFromDirectory(subdir, filter); 109 | } 110 | } 111 | catch (UnauthorizedAccessException) 112 | { 113 | Console.Error.WriteLineAsync("Unauthorized access exception for directory: " + dir); 114 | } 115 | } 116 | } 117 | } 118 | 119 | private void AddFileToList(string expandedSpecifier) 120 | { 121 | _files.Add(Path.GetFullPath(expandedSpecifier)); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/Sarif.Driver/FileStreamExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.IO; 6 | 7 | namespace Microsoft.CodeAnalysisDriver 8 | { 9 | public static class FileStreamExtensionMethods 10 | { 11 | public static string ReadString(this FileStream stream, int padTo) 12 | { 13 | long startPosition = stream.Position; 14 | 15 | int byteRead; 16 | int byteCount = 0; 17 | 18 | while ((byteRead = stream.ReadByte()) > 0) 19 | { 20 | byteCount++; 21 | }; 22 | 23 | stream.Seek(startPosition, SeekOrigin.Begin); 24 | byte[] abString = stream.ReadToArray(byteCount); 25 | 26 | int padding = padTo - (byteCount + 1) % padTo; 27 | if (padding > 0) 28 | { 29 | stream.Seek(padding + 1, SeekOrigin.Current); 30 | } 31 | 32 | return System.Text.Encoding.UTF8.GetString(abString); 33 | } 34 | 35 | public static UInt16 ReadUInt16(this FileStream stream) 36 | { 37 | return BitConverter.ToUInt16(stream.ReadToArray(2), 0); 38 | } 39 | 40 | public static Int32 ReadInt32(this FileStream stream) 41 | { 42 | return BitConverter.ToInt32(stream.ReadToArray(4), 0); 43 | } 44 | 45 | public static Int64 ReadInt64(this FileStream stream) 46 | { 47 | return BitConverter.ToInt64(stream.ReadToArray(8), 0); 48 | } 49 | 50 | public static byte[] ReadToArray(this FileStream stream, int length) 51 | { 52 | byte[] bytes = new byte[length]; 53 | int dataRead = stream.Read(bytes, 0, length); 54 | if (dataRead != length) 55 | { 56 | throw new InvalidDataException("Invalid data length read. Expected " + length + " read " + dataRead); 57 | } 58 | 59 | return bytes; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Sarif.Driver/FileSystem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.IO; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver 7 | { 8 | /// 9 | /// A wrapper class for accessing the file system. 10 | /// 11 | /// 12 | /// Clients should use this class rather directly using the .NET file system classes, so they 13 | /// can mock the IFileSystem interface in unit tests. 14 | /// 15 | public class FileSystem : IFileSystem 16 | { 17 | /// 18 | /// Determines whether the specified file exists. 19 | /// 20 | /// 21 | /// The file to check. 22 | /// 23 | /// 24 | /// true if the caller has the required permissions and path contains the name of an 25 | /// existing file; otherwise, false. 26 | /// 27 | public bool FileExists(string path) 28 | { 29 | return File.Exists(path); 30 | } 31 | 32 | /// 33 | /// Returns the absolute path for the specified path string. 34 | /// 35 | /// 36 | /// The file or directory for which to obtain absolute path information. 37 | /// 38 | /// 39 | /// The fully qualified location of , such as "C:\MyFile.txt". 40 | /// 41 | public string GetFullPath(string path) 42 | { 43 | return Path.GetFullPath(path); 44 | } 45 | 46 | /// 47 | /// Opens a text file, reads all lines of the file, and then closes the file. 48 | /// 49 | /// 50 | /// The file to open for reading. 51 | /// 52 | /// 53 | /// A string array containing all lines of the file. 54 | /// 55 | public string[] ReadAllLines(string path) 56 | { 57 | return File.ReadAllLines(path); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Sarif.Driver/IAppConfig.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.Driver 5 | { 6 | /// 7 | /// An interface for accessing the contents of an application's config file. 8 | /// 9 | /// 10 | /// Clients wishing to access an application's config file should instantiate an 11 | /// AppConfig object, rather than directly using the ConfigurationManager class, 12 | /// so they can mock the IAppConfig interface in unit tests. 13 | /// 14 | public interface IAppConfig 15 | { 16 | /// 17 | /// Gets the specified member of the AppSettings collection. 18 | /// 19 | /// 20 | /// The name of the app setting to return. 21 | /// 22 | /// 23 | /// The string value of the specified app setting, or null if the application's 24 | /// config file does not contain the specified setting. 25 | /// 26 | string GetAppSetting(string name); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Sarif.Driver/IEnvironmentVariables.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.Driver 5 | { 6 | /// 7 | /// An interface for accessing environment variables. 8 | /// 9 | /// 10 | /// Clients wishing to access environment variables should instantiate an EnvironmentVariables 11 | /// object rather than directly using the System.Environment class, so they can mock the 12 | /// IEnvironmentVariables interface in unit tests. 13 | /// 14 | public interface IEnvironmentVariables 15 | { 16 | /// 17 | /// Replaces the name of each environment variable embedded in the specified string with 18 | /// the string equivalent of the value of the variable, then returns the resulting string. 19 | /// 20 | /// 21 | /// A string containing the names of zero or more environment variables. Each environment 22 | /// variable is quoted with the percent sign character (%). 23 | /// 24 | /// 25 | /// A string with each environment variable replaced by its value. 26 | /// 27 | string ExpandEnvironmentVariables(string name); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Sarif.Driver/IFileSystem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.Driver 5 | { 6 | /// 7 | /// An interface for accessing the file system. 8 | /// 9 | /// 10 | /// Clients wishing to access the file system should instantiate a FileSystem object rather 11 | /// than directly using the .NET file system classes, so they can mock the IFileSystem 12 | /// interface in unit tests. 13 | /// 14 | public interface IFileSystem 15 | { 16 | /// 17 | /// Determines whether the specified file exists. 18 | /// 19 | /// 20 | /// The file to check. 21 | /// 22 | /// 23 | /// true if the caller has the required permissions and contains 24 | /// the name of an existing file; otherwise, false. 25 | /// 26 | bool FileExists(string path); 27 | 28 | /// 29 | /// Returns the absolute path for the specified path string. 30 | /// 31 | /// 32 | /// The file or directory for which to obtain absolute path information. 33 | /// 34 | /// 35 | /// The fully qualified location of , such as "C:\MyFile.txt". 36 | /// 37 | string GetFullPath(string path); 38 | 39 | /// 40 | /// Opens a text file, reads all lines of the file, and then closes the file. 41 | /// 42 | /// 43 | /// The file to open for reading. 44 | /// 45 | /// 46 | /// A string array containing all lines of the file. 47 | /// 48 | string[] ReadAllLines(string path); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Sarif.Driver/KeyEventImportance.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.Driver 5 | { 6 | /// Kinds of importance that can be applied to a . 7 | public enum KeyEventImportance 8 | { 9 | /// This (and the SFA to which it is attached) is 10 | /// essential to understand the defect. 11 | Essential, 12 | 13 | /// This describes the defect, but may not be 14 | /// absolutely necessary to understand its impact. 15 | Full 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Sarif.Driver/LineInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Globalization; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.Driver 8 | { 9 | /// Information about a line of text. 10 | public struct LineInfo : IEquatable 11 | { 12 | private readonly int _startOffset; 13 | private readonly int _lineNumber; 14 | 15 | // The Math.Max calls are present because arbitrary bytes can be interpreted as a struct; 16 | // they maintain the invariants that ColumnNumber >= 0, LineNumber >= 1 17 | // 18 | // If profiling indicates that these Max calls are expensive it may make sense to sacrifice 19 | // some safety by turning them into asserts instead. 20 | 21 | /// The zero-based index into a file or string at which a given line starts. 22 | public int StartOffset { get { return Math.Max(_startOffset, 0); } } 23 | 24 | /// The one-based index of the line in the file or string. 25 | public int LineNumber { get { return Math.Max(_lineNumber, 1); } } 26 | 27 | /// Initializes a new instance of the struct. 28 | /// Thrown when is 29 | /// negative or is not at least 1. 30 | /// The zero-based index into a file or string at which a given line 31 | /// starts. 32 | /// The one-based index of the line in the file or string. 33 | public LineInfo(int startOffset, int lineNumber) 34 | { 35 | if (startOffset < 0) 36 | { 37 | throw new ArgumentOutOfRangeException("startOffset", startOffset, ExceptionStrings.ValueCannotBeNegative); 38 | } 39 | 40 | if (lineNumber <= 0) 41 | { 42 | throw new ArgumentOutOfRangeException("lineNumber", lineNumber, ExceptionStrings.ValueMustBeAtLeastOne); 43 | } 44 | 45 | _startOffset = startOffset; 46 | _lineNumber = lineNumber; 47 | } 48 | 49 | /// Tests if this object is considered equal to another. 50 | /// Another object to compare to. 51 | /// true if the objects are considered equal, false if they are not. 52 | public override bool Equals(object obj) 53 | { 54 | LineInfo? other = obj as LineInfo?; 55 | return other != null 56 | && this.Equals(other.Value); 57 | } 58 | 59 | /// Tests if this is considered equal to another. 60 | /// Another object to compare to. 61 | /// true if the objects are considered equal, false if they are not. 62 | public bool Equals(LineInfo other) 63 | { 64 | return this.LineNumber == other.LineNumber 65 | && this.StartOffset == other.StartOffset; 66 | } 67 | 68 | /// Returns a hash code for this object. 69 | /// A hash code for this object. 70 | public override int GetHashCode() 71 | { 72 | var hash = new MultiplyByPrimesHash(); 73 | hash.Add(this.LineNumber); 74 | hash.Add(this.StartOffset); 75 | return hash.GetHashCode(); 76 | } 77 | 78 | /// Convert this object into a string representation. 79 | /// A string that represents this object. 80 | public override string ToString() 81 | { 82 | return String.Format(CultureInfo.InvariantCulture, "Line {0} starting at {1}", this.LineNumber, this.StartOffset); 83 | } 84 | 85 | /// Equality operator. 86 | /// The left hand side. 87 | /// The right hand side. 88 | /// The result of the operation. 89 | public static bool operator ==(LineInfo lhs, LineInfo rhs) 90 | { 91 | return lhs.Equals(rhs); 92 | } 93 | 94 | /// Inequality operator. 95 | /// The left hand side. 96 | /// The right hand side. 97 | /// The result of the operation. 98 | public static bool operator !=(LineInfo lhs, LineInfo rhs) 99 | { 100 | return !lhs.Equals(rhs); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Sarif.Driver/MultiplyByPrimesHash.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.Globalization; 8 | // Copyright (c) Microsoft. All rights reserved. 9 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 10 | 11 | // /******************************************************** 12 | // * * 13 | // * Copyright (C) Microsoft. All rights reserved. * 14 | // * * 15 | // ********************************************************/ 16 | 17 | namespace Microsoft.CodeAnalysis.Sarif.Driver 18 | { 19 | /// Multiply by primes hash calculator. 20 | public class MultiplyByPrimesHash 21 | { 22 | /// Internal state of the hash. 23 | private int _state; 24 | 25 | /// Initializes a new instance of the MultiplyByPrimesHash class. 26 | public MultiplyByPrimesHash() 27 | { 28 | _state = 17; 29 | } 30 | 31 | /// Equality operator. 32 | /// The left hand side. 33 | /// The right hand side. 34 | /// true of is equal to ; otherwise, false. 35 | public static bool operator ==(MultiplyByPrimesHash lhs, MultiplyByPrimesHash rhs) 36 | { 37 | if (object.ReferenceEquals(lhs, null)) 38 | { 39 | return object.ReferenceEquals(rhs, null); 40 | } 41 | else if (object.ReferenceEquals(rhs, null)) 42 | { 43 | return false; 44 | } 45 | 46 | return lhs._state == rhs._state; 47 | } 48 | 49 | /// Inequality operator. 50 | /// The left hand side. 51 | /// The right hand side. 52 | /// true of is not equal to ; otherwise, false. 53 | public static bool operator !=(MultiplyByPrimesHash lhs, MultiplyByPrimesHash rhs) 54 | { 55 | return !(lhs == rhs); 56 | } 57 | 58 | /// Adds item to the calculated hash. 59 | /// The item to add to the calculated hash. 60 | public void Add(int item) 61 | { 62 | _state = unchecked((_state * 31) + item); 63 | } 64 | 65 | /// Adds multiple items to the calculated hash. 66 | /// The items to add. 67 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 68 | public void AddRange(int[] items) 69 | { 70 | foreach (int item in items) 71 | { 72 | this.Add(item); 73 | } 74 | } 75 | 76 | /// Adds multiple items to the calculated hash. 77 | /// The items to add. 78 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 79 | public void AddRange(IEnumerable items) 80 | { 81 | foreach (int item in items) 82 | { 83 | this.Add(item); 84 | } 85 | } 86 | 87 | /// Indicates whether this instance and a specified object are equal. 88 | /// Another object to compare to. 89 | /// true if and this instance are the same type and 90 | /// represent the same value; otherwise, false. 91 | public override bool Equals(object obj) 92 | { 93 | var other = obj as MultiplyByPrimesHash; 94 | if (other == null) 95 | { 96 | return false; 97 | } 98 | else 99 | { 100 | return other._state == _state; 101 | } 102 | } 103 | 104 | /// Returns the hash code for this instance. 105 | /// A 32-bit signed integer that is the hash code for this instance. 106 | public override int GetHashCode() 107 | { 108 | return _state; 109 | } 110 | 111 | /// Returns a human readable string describing this instance. 112 | /// A human readable string describing this instance. 113 | public override string ToString() 114 | { 115 | return string.Format(CultureInfo.InvariantCulture, "MultiplyByPrimesHash state: 0x{0:X}", _state); 116 | } 117 | 118 | /// Adds item to the calculated hash. 119 | /// The item to add to the calculated hash. If this parameter is 120 | /// null, the effect will be the same as if its 121 | /// function returns 0. 122 | public void Add(object item) 123 | { 124 | this.Add(item == null ? 0 : item.GetHashCode()); 125 | } 126 | 127 | /// Adds a set of items to the calculated hash. 128 | /// The items to add. If any item is null, the effect is the 129 | /// same as if that item's returned null. 130 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 131 | public void AddRange(IEnumerable items) 132 | { 133 | foreach (object item in items) 134 | { 135 | if (item == null) 136 | { 137 | this.Add(0); 138 | } 139 | else 140 | { 141 | this.Add(item.GetHashCode()); 142 | } 143 | } 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /src/Sarif.Driver/MurmurHash.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Diagnostics.CodeAnalysis; 7 | using System.Globalization; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.Driver 10 | { 11 | /// Murmur hash 3 implementation of IHashCalculator. See 12 | /// http://www.codeproject.com/Articles/32829/Hash-Functions-An-Empirical-Comparison 13 | /// http://code.google.com/p/smhasher/ 14 | /// http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp 15 | /// 16 | /// This implementation is the x86_32 version. Note that we don't deal with the "tail" bits of the algorithm 17 | /// because we allow only integer inputs. 18 | public class MurmurHash 19 | { 20 | /// The first murmur hash constant. 21 | private const uint ConstantOne = 0xCC9E2D51u; 22 | 23 | /// The second murmur hash constant. 24 | private const uint ConstantTwo = 0x1B873593u; 25 | 26 | /// The internal state of the hash. 27 | private uint _internalState; 28 | 29 | /// Number of items inserted into the hash. 30 | private uint _itemCount; 31 | 32 | /// Equality operator. 33 | /// The left hand side. 34 | /// The right hand side. 35 | /// true of is equal to ; otherwise, false. 36 | public static bool operator ==(MurmurHash lhs, MurmurHash rhs) 37 | { 38 | if (object.ReferenceEquals(lhs, null)) 39 | { 40 | return object.ReferenceEquals(rhs, null); 41 | } 42 | else if (object.ReferenceEquals(rhs, null)) 43 | { 44 | return false; 45 | } 46 | 47 | return lhs._internalState == rhs._internalState 48 | && lhs._itemCount == rhs._itemCount; 49 | } 50 | 51 | /// Inequality operator. 52 | /// The left hand side. 53 | /// The right hand side. 54 | /// true of is not equal to ; otherwise, false. 55 | public static bool operator !=(MurmurHash lhs, MurmurHash rhs) 56 | { 57 | return !(lhs == rhs); 58 | } 59 | 60 | /// Adds item to the calculated hash. 61 | /// The item to add to the calculated hash. 62 | public void Add(int item) 63 | { 64 | unchecked 65 | { 66 | _itemCount++; 67 | uint istate = _internalState; 68 | uint uitem = (uint)item; 69 | uitem *= ConstantOne; 70 | uitem = RotateLeft(uitem, 15); 71 | uitem *= ConstantTwo; 72 | istate ^= uitem; 73 | istate = RotateLeft(istate, 13); 74 | istate = (istate * 5) + 0xE6546B64u; 75 | _internalState = istate; 76 | } 77 | } 78 | 79 | /// Adds multiple items to the calculated hash. 80 | /// The items to add. 81 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 82 | public void AddRange(int[] items) 83 | { 84 | foreach (int item in items) 85 | { 86 | this.Add(item); 87 | } 88 | } 89 | 90 | /// Adds multiple items to the calculated hash. 91 | /// The items to add. 92 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 93 | public void AddRange(IEnumerable items) 94 | { 95 | foreach (int item in items) 96 | { 97 | this.Add(item); 98 | } 99 | } 100 | 101 | /// Indicates whether this instance and a specified object are equal. 102 | /// Another object to compare to. 103 | /// true if and this instance are the same type and 104 | /// represent the same value; otherwise, false. 105 | public override bool Equals(object obj) 106 | { 107 | var other = obj as MurmurHash; 108 | if (other == null) 109 | { 110 | return false; 111 | } 112 | else 113 | { 114 | return other._internalState == _internalState 115 | && other._itemCount == _itemCount; 116 | } 117 | } 118 | 119 | /// Returns the hash code for this instance. 120 | /// A 32-bit signed integer that is the hash code for this instance. 121 | public override int GetHashCode() 122 | { 123 | uint result = _internalState; 124 | result ^= _itemCount * 4; 125 | result = Mix(result); 126 | return unchecked((int)result); 127 | } 128 | 129 | /// Returns a human readable string describing this instance. 130 | /// A human readable string describing this instance. 131 | public override string ToString() 132 | { 133 | return string.Format(CultureInfo.InvariantCulture, "MurmurHash state: h: 0x{0:X} count: 0x{1:X}", _internalState, _itemCount); 134 | } 135 | 136 | /// Adds item to the calculated hash. 137 | /// The item to add to the calculated hash. If this parameter is 138 | /// null, the effect will be the same as if its 139 | /// function returns 0. 140 | public void Add(object item) 141 | { 142 | if (item == null) 143 | { 144 | this.Add(0); 145 | } 146 | else 147 | { 148 | this.Add(item.GetHashCode()); 149 | } 150 | } 151 | 152 | /// Adds a set of items to the calculated hash. 153 | /// The items to add. If any item is null, the effect is the 154 | /// same as if that item's returned null. 155 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 156 | public void AddRange(IEnumerable items) 157 | { 158 | foreach (object item in items) 159 | { 160 | if (item == null) 161 | { 162 | this.Add(0); 163 | } 164 | else 165 | { 166 | this.Add(item.GetHashCode()); 167 | } 168 | } 169 | } 170 | 171 | /// Mixes the given hash value. 172 | /// Hash value to process. 173 | /// The mixed hash value. 174 | /// This function must be in an unchecked context. 175 | private static uint Mix(uint h) 176 | { 177 | h ^= h >> 16; 178 | h *= 0x85EBCA6Bu; 179 | h ^= h >> 13; 180 | h *= 0xC2B2AE35u; 181 | h ^= h >> 16; 182 | 183 | return h; 184 | } 185 | 186 | /// Rotates left. 187 | /// Hash value to process. 188 | /// The amount by which shall be rotated. 189 | /// The rotated value of . 190 | private static uint RotateLeft(uint h, byte amount) 191 | { 192 | return (h << amount) | (h >> (32 - amount)); 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /src/Sarif.Driver/NewLineIndex.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Immutable; 6 | using System.Diagnostics; 7 | using System.Diagnostics.CodeAnalysis; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.Driver 10 | { 11 | /// 12 | /// An index of newline start locations in a string in order to relatively cheaply 13 | /// turn a given offset into a line / column number. 14 | /// 15 | public class NewLineIndex 16 | { 17 | // Each index n in this list denotes the halfopen range 18 | // [lineOffsetStarts(n), lineOffsetStarts(n+1)) 19 | // which is the line in the file at index n. 20 | private readonly ImmutableArray _lineOffsetStarts; 21 | 22 | /// Initializes a new instance of the class indexing the 23 | /// specified string. 24 | /// The text to add to this . 25 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 26 | public NewLineIndex(string textToIndex) 27 | { 28 | ImmutableArray.Builder result = ImmutableArray.CreateBuilder(); 29 | result.Add(0); 30 | 31 | int indexLength = textToIndex.Length; 32 | for (int charCount = 0; charCount < indexLength; ++charCount) 33 | { 34 | char c = textToIndex[charCount]; 35 | // Detect \r, \n, \u2028, \u2029, but NOT \r\n 36 | // (\r\n gets taken care of on the following loop 37 | // iteration and is detected as \n there) 38 | if (c == '\n' || 39 | (c == '\r' && (charCount + 1 >= indexLength || textToIndex[charCount + 1] != '\n')) || 40 | c == '\u2028' || // Unicode line separator 41 | c == '\u2029' // Unicode paragraph separator 42 | ) 43 | { 44 | result.Add(charCount + 1); 45 | } 46 | } 47 | 48 | _lineOffsetStarts = result.ToImmutable(); 49 | } 50 | 51 | /// Gets a for the line at the specified index. 52 | /// Thrown when is not 53 | /// a valid line number; e.g. if it is zero, negative, or greater than the maximum line count in 54 | /// the file. 55 | /// The line number. 56 | /// A for . 57 | public LineInfo GetLineInfoForLine(int lineNumber) 58 | { 59 | if (lineNumber <= 0 || lineNumber > this.MaximumLineNumber) 60 | { 61 | throw new ArgumentOutOfRangeException("lineNumber", lineNumber, ExceptionStrings.LineNumberWasOutOfRange); 62 | } 63 | 64 | return new LineInfo(_lineOffsetStarts[lineNumber - 1], lineNumber); 65 | } 66 | 67 | /// Gets the maximum line number. 68 | /// The maximum line number. 69 | public int MaximumLineNumber 70 | { 71 | get 72 | { 73 | return _lineOffsetStarts.Length; 74 | } 75 | } 76 | 77 | /// Gets line information for the line containing the character at the specified offset. 78 | /// Thrown when is negative. 79 | /// The offset. 80 | /// The line information for the specified offset. 81 | public LineInfo GetLineInfoForOffset(int offset) 82 | { 83 | if (offset < 0) 84 | { 85 | throw new ArgumentOutOfRangeException("offset", offset, ExceptionStrings.ValueCannotBeNegative); 86 | } 87 | 88 | int startLine = _lineOffsetStarts.BinarySearch(offset); 89 | 90 | if (startLine < 0) 91 | { 92 | // If BinarySearch returns negative, returns the bitwise 93 | // complement of the next larger index. (upper_bound) 94 | // We want the next smaller index, which is where the -1 comes from. 95 | startLine = ~startLine - 1; 96 | Debug.Assert(startLine >= 0); // Because startLine < 0 if block 97 | } 98 | 99 | return new LineInfo(_lineOffsetStarts[startLine], startLine + 1); 100 | } 101 | 102 | /// Gets information for a given offset, such as the line and column numbers. 103 | /// Thrown when is negative. 104 | /// The offset for which information shall be obtained. 105 | /// The information for offset. 106 | public OffsetInfo GetOffsetInfoForOffset(int offset) 107 | { 108 | if (offset < 0) 109 | { 110 | throw new ArgumentOutOfRangeException("offset", offset, ExceptionStrings.ValueCannotBeNegative); 111 | } 112 | 113 | LineInfo lineInfo = this.GetLineInfoForOffset(offset); 114 | return new OffsetInfo(offset - lineInfo.StartOffset, lineInfo.LineNumber); 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Sarif.Driver/OffsetInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Globalization; 6 | using System.Runtime.Serialization; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver 9 | { 10 | /// Information about an offset in a block of text. 11 | [Serializable] 12 | public struct OffsetInfo : IEquatable, ISerializable 13 | { 14 | private readonly int _columnNumber; 15 | private readonly int _lineNumber; 16 | 17 | // The Math.Max calls are present because arbitrary bytes can be interpreted as a struct; 18 | // they maintain the invariants that ColumnNumber >= 0, LineNumber >= 1 19 | // 20 | // If profiling indicates that these Max calls are expensive it may make sense to sacrifice 21 | // some safety by turning them into asserts instead. 22 | 23 | /// The zero-based index of the column where the offset is located. 24 | public int ColumnNumber { get { return Math.Max(_columnNumber, 0); } } 25 | 26 | /// The one-based index of the line in the file or string on which the offset is 27 | /// located. 28 | public int LineNumber { get { return Math.Max(_lineNumber, 1); } } 29 | 30 | /// Initializes a new instance of the struct. 31 | /// Thrown when is 32 | /// negative or is not at least 1. 33 | /// The zero-based index of the column on which an offset is located. 34 | /// The one-based index of the line in the file or string. 35 | public OffsetInfo(int columnNumber, int lineNumber) 36 | { 37 | if (columnNumber < 0) 38 | { 39 | throw new ArgumentOutOfRangeException("columnNumber", columnNumber, ExceptionStrings.ValueCannotBeNegative); 40 | } 41 | 42 | if (lineNumber <= 0) 43 | { 44 | throw new ArgumentOutOfRangeException("lineNumber", lineNumber, ExceptionStrings.ValueMustBeAtLeastOne); 45 | } 46 | 47 | _columnNumber = columnNumber; 48 | _lineNumber = lineNumber; 49 | } 50 | 51 | /// Initializes a new instance of the struct. 52 | /// The serialization info from which the value shall be deserialized. 53 | /// The streaming context from which the value shall be deserialized. 54 | private OffsetInfo(SerializationInfo info, StreamingContext context) 55 | : this(info.GetInt32("ColumnNumber"), info.GetInt32("lineNumber")) 56 | { } 57 | 58 | /// Tests if this object is considered equal to another. 59 | /// Another object to compare to. 60 | /// true if the objects are considered equal, false if they are not. 61 | public override bool Equals(object obj) 62 | { 63 | OffsetInfo? other = obj as OffsetInfo?; 64 | return other != null 65 | && this.Equals(other.Value); 66 | } 67 | 68 | /// Tests if this is considered equal to another. 69 | /// Another object to compare to. 70 | /// true if the objects are considered equal, false if they are not. 71 | public bool Equals(OffsetInfo other) 72 | { 73 | return this.LineNumber == other.LineNumber 74 | && this.ColumnNumber == other.ColumnNumber; 75 | } 76 | 77 | /// Returns a hash code for this object. 78 | /// A hash code for this object. 79 | public override int GetHashCode() 80 | { 81 | var hash = new MultiplyByPrimesHash(); 82 | hash.Add(this.LineNumber); 83 | hash.Add(this.ColumnNumber); 84 | return hash.GetHashCode(); 85 | } 86 | 87 | /// Convert this object into a string representation. 88 | /// A string that represents this object. 89 | public override string ToString() 90 | { 91 | return String.Format(CultureInfo.InvariantCulture, "{0}:{1}", this.LineNumber, this.ColumnNumber); 92 | } 93 | 94 | /// Gets object data for serialization. 95 | /// The serialization info into which the value shall be serialized. 96 | /// The streaming context into which the value shall be serialized. 97 | public void GetObjectData(SerializationInfo info, StreamingContext context) 98 | { 99 | if (info == null) 100 | { 101 | throw new ArgumentNullException("info"); 102 | } 103 | 104 | info.AddValue("ColumnNumber", this.ColumnNumber); 105 | info.AddValue("LineNumber", this.LineNumber); 106 | } 107 | 108 | /// Equality operator. 109 | /// The left hand side. 110 | /// The right hand side. 111 | /// The result of the operation. 112 | public static bool operator ==(OffsetInfo lhs, OffsetInfo rhs) 113 | { 114 | return lhs.Equals(rhs); 115 | } 116 | 117 | /// Inequality operator. 118 | /// The left hand side. 119 | /// The right hand side. 120 | /// The result of the operation. 121 | public static bool operator !=(OffsetInfo lhs, OffsetInfo rhs) 122 | { 123 | return !lhs.Equals(rhs); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Pair.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver 7 | { 8 | /// Contains a function to make it less verbose to make key value pairs. Similar to C++'s 9 | /// std::make_pair. 10 | public static class Pair 11 | { 12 | /// Makes a pair, with the generic type parameters determined using generic argument deduction. 13 | /// Key type. 14 | /// Value type. 15 | /// The key to use in the new pair. 16 | /// The value to use in the new pair. 17 | /// A KeyValuePair{TKey,TValue} containing the supplied key and value. 18 | public static KeyValuePair Make(TKey key, TValue value) 19 | { 20 | return new KeyValuePair(key, value); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Sarif.Driver/PathExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | // Copyright (c) Microsoft. All rights reserved. 9 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 10 | 11 | // /******************************************************** 12 | // * * 13 | // * Copyright (C) Microsoft. All rights reserved. * 14 | // * * 15 | // ********************************************************/ 16 | 17 | namespace Microsoft.CodeAnalysis.Sarif.Driver 18 | { 19 | /// Path extension functions. 20 | public static class PathExtensions 21 | { 22 | /// Gets a path relative to the SdlCommon library. 23 | /// The relative path to obtain to SdlCommon.dll. 24 | /// The path relative to the SdlCommon library. 25 | public static string GetPathRelativeToSdlCommon(string relativePath) 26 | { 27 | string dllPath = Assembly.GetExecutingAssembly().Location; 28 | string dllDirectory = Path.GetDirectoryName(dllPath); 29 | return Path.Combine(dllDirectory, relativePath); 30 | } 31 | 32 | /// 33 | /// Try to get the directory containing a file or the directory itself if path is a directory. 34 | /// 35 | /// file or directory 36 | /// directory if possible, otherwise null 37 | public static string TryGetDirectory(string fileOrDirectory) 38 | { 39 | if (File.Exists(fileOrDirectory)) 40 | { 41 | return Path.GetDirectoryName(fileOrDirectory); 42 | } 43 | 44 | if (Directory.Exists(fileOrDirectory)) 45 | { 46 | return fileOrDirectory; 47 | } 48 | 49 | try 50 | { 51 | string result = Path.GetDirectoryName(fileOrDirectory); 52 | if (!string.IsNullOrEmpty(result)) 53 | { 54 | return result; 55 | } 56 | } 57 | catch (ArgumentException) { } 58 | // GetDirectoryName path parameter contains invalid characters, is empty, or contains only white spaces. 59 | // We can't determine a directory so fall through. 60 | 61 | catch (PathTooLongException) { } 62 | // GetDirectoryName path parameter is longer than the system-defined maximum length. 63 | // We can't determine a directory so fall through. 64 | 65 | catch (IOException) { } 66 | // GetDirectoryName (or File.Exists, Directory.Exists) failed for some other reason. There aren't any others documented in .Net 4.0 but 4.5 has 67 | // IOException. 68 | // We can't determine a directory so fall through. 69 | 70 | // If there are any other unexpected exceptions, like NullReferenceException or AccessViolationException or StackOverflowException, we want to fail. 71 | 72 | return null; 73 | } 74 | 75 | /// Unescapes a potentially quoted path. 76 | /// Thrown when an invalid path is supplied. 77 | /// The path to unescape. 78 | /// An unescaped version of . 79 | public static string PathUnescapePath(string sourcePath) 80 | { 81 | if (sourcePath == null) 82 | { 83 | return string.Empty; 84 | } 85 | 86 | char[] invalidPathChars = Path.GetInvalidPathChars(); 87 | if (sourcePath.StartsWith("\"", StringComparison.Ordinal)) 88 | { 89 | // Path is a quoted path 90 | // http://msdn.microsoft.com/en-us/library/windows/desktop/bb776391.aspx 91 | // CommandLineToArgvW has a special interpretation of backslash characters when they are followed by a quotation mark character ("), as follows: 92 | // * 2n backslashes followed by a quotation mark produce n backslashes followed by a quotation mark. 93 | // * (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark. 94 | // * n backslashes not followed by a quotation mark simply produce n backslashes. 95 | int sourceLength = sourcePath.Length; 96 | char[] resultTemp = new char[sourceLength - 1]; // would be - 2 because of 2 quote characters, but the end quote might not be there. 97 | int resultIdx = 0; 98 | int backslashN = 0; 99 | for (int idx = 1; idx != sourceLength; ++idx) 100 | { 101 | char c = sourcePath[idx]; 102 | 103 | if (c != '"' && invalidPathChars.Contains(c)) 104 | { 105 | throw new IOException("Invalid path detected: " + sourcePath + " had invalid characters."); 106 | } 107 | 108 | if (c == '\\') 109 | { 110 | backslashN++; 111 | continue; 112 | } 113 | else if (backslashN != 0 && c == '"') 114 | { 115 | AddSlashes(resultTemp, ref resultIdx, backslashN / 2); 116 | if (backslashN % 2 == 0) 117 | { 118 | backslashN = 0; 119 | break; 120 | } 121 | else 122 | { 123 | backslashN = 0; 124 | } 125 | } 126 | else if (backslashN != 0 && c != '"') 127 | { 128 | AddSlashes(resultTemp, ref resultIdx, backslashN); 129 | backslashN = 0; 130 | } 131 | else if (c == '"') 132 | { 133 | break; 134 | } 135 | 136 | resultTemp[resultIdx++] = c; 137 | } 138 | 139 | AddSlashes(resultTemp, ref resultIdx, backslashN); 140 | return new string(resultTemp, 0, resultIdx); 141 | } 142 | else 143 | { 144 | // Path is an unquoted path. Make sure it contains all valid characters. 145 | foreach (char c in sourcePath) 146 | { 147 | if (invalidPathChars.Contains(c)) 148 | { 149 | throw new IOException("Invalid path detected: " + sourcePath + " had invalid characters."); 150 | } 151 | } 152 | 153 | return sourcePath; 154 | } 155 | } 156 | 157 | /// Adds slashes to the temporary array. 158 | /// The result temporary array. 159 | /// [in,out] Zero-based index of where slashes are being added. On return, set to the next insertion index in . 160 | /// The number of slashes to add. 161 | private static void AddSlashes(char[] resultTemp, ref int resultIdx, int slashesToAdd) 162 | { 163 | for (int slashCount = slashesToAdd; slashCount != 0; --slashCount) 164 | { 165 | resultTemp[resultIdx++] = '\\'; 166 | } 167 | } 168 | } 169 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Reflection; 5 | using System.Runtime.InteropServices; 6 | 7 | [assembly: AssemblyTitle("Microsoft Driver Utilities")] 8 | [assembly: AssemblyProduct("Driver.Utilities")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyCopyright("Copyright \u00A9 2015")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | [assembly: ComVisible(false)] 17 | [assembly: AssemblyVersion("1.0.0.0")] 18 | [assembly: AssemblyFileVersion("1.0.0.0")] 19 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Ref.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Diagnostics; 6 | using System.Diagnostics.CodeAnalysis; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver 9 | { 10 | /// A class that makes atomized string reference comparison easier. Stolen (slightly 11 | /// modified) from http://referencesource.microsoft.com/#System.Xml/System/Xml/Ref.cs. 12 | public static class Ref 13 | { 14 | /// Compares strings for reference equality and asserts if they are equal but not reference equal in debug mode. 15 | /// The first string to compare. 16 | /// The second string to compare. 17 | /// true if Object.ReferenceEquals(lhs, rhs); otherwise, false. 18 | public static bool Equal(string lhs, string rhs) 19 | { 20 | Debug.Assert(((object)lhs) == ((object)rhs) || !String.Equals(lhs, rhs, StringComparison.Ordinal), 21 | "Object comparison used for non-atomized string \"" + lhs + "\"."); 22 | return ((object)lhs) == ((object)rhs); 23 | } 24 | 25 | /// Do not call this function. Prevents typo Ref.Equals from compiling. 26 | /// Object to be compared. 27 | /// Object to be compared. 28 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "unusedA")] 29 | [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "unusedB")] 30 | public static new void Equals(object unusedA, object unusedB) 31 | { } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Sarif.Driver/ReferenceEqualityComparer`1.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.Runtime.CompilerServices; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver 9 | { 10 | /// Reference equals equality comparer. 11 | /// Generic type compared. 12 | /// 13 | public class ReferenceEqualityComparer : IEqualityComparer 14 | { 15 | /// The instance of equality comparer for T. 16 | [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] 17 | [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] 18 | public static readonly ReferenceEqualityComparer Instance = new ReferenceEqualityComparer(); 19 | 20 | /// 21 | /// Prevents clients from constructing instances. 22 | /// 23 | private ReferenceEqualityComparer() 24 | { } 25 | 26 | /// Tests if two T objects are considered equal. 27 | /// Left T to be compared. 28 | /// Right T to be compared. 29 | /// true if the objects are considered equal, false if they are not. 30 | /// 31 | public bool Equals(T x, T y) 32 | { 33 | return object.ReferenceEquals(x, y); 34 | } 35 | 36 | /// Calculates the hash code for a given T. 37 | /// The object to get a hash code for. 38 | /// The hash code for . 39 | /// 40 | public int GetHashCode(T obj) 41 | { 42 | return RuntimeHelpers.GetHashCode(obj); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/AggregatingLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using Microsoft.CodeAnalysis.Sarif.Sdk; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 10 | { 11 | public class AggregatingLogger : IDisposable, IResultLogger 12 | { 13 | public AggregatingLogger() : this(null) 14 | { 15 | } 16 | 17 | public AggregatingLogger(IEnumerable loggers) 18 | { 19 | this.Loggers = loggers != null ? 20 | new List(loggers) : 21 | new List(); 22 | } 23 | 24 | public IList Loggers { get; set; } 25 | 26 | public void Dispose() 27 | { 28 | foreach (IResultLogger logger in Loggers) 29 | { 30 | using (logger as IDisposable) { }; 31 | } 32 | } 33 | 34 | public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message) 35 | { 36 | foreach (IResultLogger logger in Loggers) 37 | { 38 | logger.Log(messageKind, context, message); 39 | } 40 | } 41 | 42 | public void Log(ResultKind messageKind, IAnalysisContext context, string message) 43 | { 44 | foreach (IResultLogger logger in Loggers) 45 | { 46 | logger.Log(messageKind, context, message); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/AnalysisApplicability.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | 5 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 6 | { 7 | public enum AnalysisApplicability 8 | { 9 | Unknown, 10 | NotApplicableToSpecifiedTarget, 11 | ApplicableToSpecifiedTarget, 12 | NotApplicableToAnyTargetWithoutPolicy 13 | } 14 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/AnalyzeOptionsBase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using CommandLine; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | [Verb("analyze", HelpText = "Analyze one or more binary files for security and correctness issues.")] 11 | public class AnalyzeOptionsBase : IAnalyzeOptions 12 | { 13 | [Value(0, 14 | HelpText = "One or more specifiers to a file, directory, or filter pattern that resolves to one or more binaries to analyze.")] 15 | public IEnumerable TargetFileSpecifiers { get; set; } 16 | 17 | [Option( 18 | 'o', 19 | "output", 20 | HelpText = "File path to which analysis output will be written.")] 21 | public string OutputFilePath { get; set; } 22 | 23 | [Option( 24 | 'v', 25 | "verbose", 26 | HelpText = "Emit verbose output. The resulting comprehensive report is designed to provide appropriate evidence for compliance scenarios.")] 27 | public bool Verbose { get; set; } 28 | 29 | [Option( 30 | 'r', 31 | "recurse", 32 | HelpText = "Recurse into subdirectories when evaluating file specifier arguments.")] 33 | public bool Recurse { get; set; } 34 | 35 | [Option( 36 | 'c', 37 | "config", 38 | HelpText = "Path to policy file that will be used to configure analysis. Pass value of 'default' to use built-in settings.")] 39 | public string PolicyFilePath { get; set; } 40 | 41 | [Option( 42 | 's', 43 | "statistics", 44 | HelpText = "Generate timing and other statistics for analysis session.")] 45 | public bool Statistics { get; set; } 46 | 47 | [Option( 48 | 'h', 49 | "hashes", 50 | HelpText = "Output SHA-256 hash of analysis targets when emitting SARIF reports.")] 51 | public bool ComputeTargetsHash { get; set; } 52 | 53 | [Option( 54 | 'p', 55 | "plug-in", 56 | Separator = ';', 57 | HelpText = "Path to plug-in that will be invoked against all targets in the analysis set.")] 58 | public IList PlugInFilePaths { get; set; } 59 | } 60 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/CompositionUtilities.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Collections.Immutable; 6 | using System.Composition.Convention; 7 | using System.Composition.Hosting; 8 | using System.Reflection; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 11 | { 12 | internal static class DriverUtilities 13 | { 14 | public static ImmutableArray GetExports(IEnumerable assemblies) 15 | { 16 | var container = CreateCompositionContainer(assemblies); 17 | return container.GetExports().ToImmutableArray(); 18 | } 19 | 20 | private static CompositionHost CreateCompositionContainer(IEnumerable assemblies) 21 | { 22 | ConventionBuilder conventions = GetConventions(); 23 | 24 | return new ContainerConfiguration() 25 | .WithAssemblies(assemblies, conventions) 26 | .CreateContainer(); 27 | } 28 | 29 | private static ConventionBuilder GetConventions() 30 | { 31 | var conventions = new ConventionBuilder(); 32 | 33 | // New per-analyzer options mechanism 34 | conventions.ForTypesDerivedFrom() 35 | .Export(); 36 | 37 | return conventions; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ConsoleLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using Microsoft.CodeAnalysis.Sarif.Sdk; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 8 | { 9 | public class ConsoleLogger : IResultLogger 10 | { 11 | public ConsoleLogger(bool verbose) 12 | { 13 | Verbose = verbose; 14 | } 15 | 16 | public bool Verbose { get; set; } 17 | 18 | public void Log(ResultKind messageKind, IAnalysisContext context, string message) 19 | { 20 | switch (messageKind) 21 | { 22 | 23 | // These result types are optionally emitted 24 | case ResultKind.Pass: 25 | case ResultKind.Note: 26 | case ResultKind.NotApplicable: 27 | { 28 | if (Verbose) 29 | { 30 | Console.WriteLine(GetMessageText(context, message, messageKind)); 31 | } 32 | break; 33 | } 34 | 35 | // These result types are alwayss emitted 36 | case ResultKind.Error: 37 | case ResultKind.Warning: 38 | case ResultKind.InternalError: 39 | case ResultKind.ConfigurationError: 40 | { 41 | Console.WriteLine(GetMessageText(context, message, messageKind)); 42 | break; 43 | } 44 | 45 | default: 46 | { 47 | throw new InvalidOperationException(); 48 | } 49 | } 50 | } 51 | public static string GetMessageText( 52 | IAnalysisContext context, 53 | string message, 54 | ResultKind messageKind, 55 | Region region = null) 56 | { 57 | string path = null; 58 | Uri uri = context.TargetUri; 59 | 60 | if (uri != null) 61 | { 62 | // If a path refers to a URI of form file://blah, we will convert to the local path 63 | if (uri.IsAbsoluteUri && uri.Scheme == Uri.UriSchemeFile) 64 | { 65 | path = uri.LocalPath; 66 | } 67 | else 68 | { 69 | path = uri.ToString(); 70 | } 71 | } 72 | 73 | string issueType = null; 74 | 75 | switch (messageKind) 76 | { 77 | case ResultKind.ConfigurationError: 78 | { 79 | issueType = "CONFIGURATION ERROR"; 80 | break; 81 | } 82 | 83 | case ResultKind.InternalError: 84 | { 85 | issueType = "INTERNAL ERROR"; 86 | break; 87 | } 88 | 89 | case ResultKind.Error: 90 | { 91 | issueType = "error"; 92 | break; 93 | } 94 | 95 | case ResultKind.Warning: 96 | { 97 | issueType = "warning"; 98 | break; 99 | } 100 | 101 | case ResultKind.NotApplicable: 102 | case ResultKind.Note: 103 | { 104 | issueType = "note"; 105 | break; 106 | } 107 | 108 | default: 109 | { 110 | throw new InvalidOperationException("Unknown message kind:" + messageKind.ToString()); 111 | } 112 | } 113 | 114 | string detailedDiagnosis = NormalizeMessage(message, enquote: false); 115 | 116 | string location = ""; 117 | 118 | if (region != null) 119 | { 120 | // TODO 121 | if (region.Offset > 0 || region.StartColumn == 0) { throw new NotImplementedException(); } 122 | 123 | if (region.StartLine == 0) { throw new InvalidOperationException(); } 124 | 125 | // VS supports the following formatting options: 126 | // (startLine) 127 | // (startLine-endLine) 128 | // (startLine,startColumn) 129 | // (startLine,startColumn-endColumn) 130 | // (startLine,startColumn,endLine,endColumn 131 | // 132 | // For expedience, we'll convert everything to the most fully qualified format 133 | 134 | string start = region.StartLine.ToString() + "," + 135 | (region.StartColumn > 0 ? region.StartColumn.ToString() : "1"); 136 | 137 | string end = (region.EndLine > region.StartLine ? region.EndLine.ToString() : region.StartLine.ToString()) + "," + 138 | (region.EndColumn > 0 ? region.EndColumn.ToString() : region.StartColumn.ToString()); 139 | 140 | location = 141 | "(" + 142 | start + (end != start ? "," + end : "") + 143 | ")"; 144 | } 145 | 146 | return (path != null ? (path + location + ": ") : "") + 147 | issueType + " " + 148 | context.Rule.Id + ": " + 149 | detailedDiagnosis; 150 | } 151 | 152 | public static string NormalizeMessage(string message, bool enquote) 153 | { 154 | return (enquote ? "\"" : "") + 155 | message.Replace('"', '\'') + 156 | (enquote ? "\"" : ""); 157 | } 158 | 159 | public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message) 160 | { 161 | throw new NotImplementedException(); 162 | } 163 | } 164 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/DriverCommand.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Reflection; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | public abstract class DriverCommand 11 | { 12 | abstract public int Run(T options); 13 | 14 | public const int FAILURE = 1; 15 | public const int SUCCESS = 0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ErrorDescriptors.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.CodeAnalysis.Sarif.Sdk; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | public static class ErrorDescriptors 11 | { 12 | public static IRuleDescriptor InvalidConfiguration = new RuleDescriptor() 13 | { 14 | Id = "ERR0997", 15 | Name = nameof(InvalidConfiguration), 16 | FullDescription = SdkResources.InvalidConfiguration_Description, 17 | FormatSpecifiers = BuildDictionary(new string[] { 18 | nameof(SdkResources.ExceptionCreatingLogFile), 19 | nameof(SdkResources.ExceptionLoadingAnalysisPlugIn), 20 | nameof(SdkResources.ExceptionLoadingAnalysisTarget) 21 | }) 22 | }; 23 | 24 | public static IRuleDescriptor UnhandledRuleException = new RuleDescriptor() 25 | { 26 | Id = "ERR0998", 27 | Name = nameof(UnhandledRuleException), 28 | FullDescription = SdkResources.ExceptionInRule_Description, 29 | FormatSpecifiers = BuildDictionary(new string[] { 30 | nameof(SdkResources.ExceptionInitializingRule), 31 | nameof(SdkResources.ExceptionAnalyzingTarget) 32 | }) 33 | }; 34 | 35 | public static IRuleDescriptor UnhandledEngineException = new RuleDescriptor() 36 | { 37 | Id = "ERR0999", 38 | Name = nameof(UnhandledEngineException), 39 | FullDescription = SdkResources.ExceptionInAnalysisEngine_Description, 40 | FormatSpecifiers = BuildDictionary(new string[] { 41 | nameof(SdkResources.ExceptionInAnalysisEngine) 42 | }) 43 | }; 44 | 45 | 46 | public static IRuleDescriptor ParseError = new RuleDescriptor() 47 | { 48 | Id = "ERR1001", 49 | Name = nameof(ParseError), 50 | FullDescription = SdkResources.ParseError_Description, 51 | FormatSpecifiers = BuildDictionary(new string[] { 52 | nameof(SdkResources.ParseError) 53 | }) 54 | }; 55 | 56 | private static Dictionary BuildDictionary(IEnumerable resourceNames) 57 | { 58 | // Note this dictionary provides for case-insensitive keys 59 | var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); 60 | 61 | foreach (string resourceName in resourceNames) 62 | { 63 | string resourceValue = SdkResources.ResourceManager.GetString(resourceName); 64 | dictionary[resourceName] = resourceValue; 65 | } 66 | 67 | return dictionary; 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ExitApplicationException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | public class ExitApplicationException : Exception where T : struct 9 | { 10 | public ExitApplicationException() : base() { } 11 | public ExitApplicationException(string message) : base(message) { } 12 | public ExitApplicationException(string message, Exception innerException) : base(message, innerException) { } 13 | 14 | public T ExitReason { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ExitReason.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 5 | { 6 | public enum ExitReason 7 | { 8 | None, 9 | ExceptionCreatingLogFile, 10 | UnhandledExceptionInstantiatingSkimmers, 11 | UnhandledExceptionInEngine, 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ExportConfigurationCommandBase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Immutable; 6 | using System.IO; 7 | using System.Reflection; 8 | 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 11 | { 12 | public abstract class ExportConfigurationCommandBase : PlugInDriverCommand 13 | { 14 | public override int Run(ExportConfigurationOptions exportOptions) 15 | { 16 | int result = FAILURE; 17 | 18 | try 19 | { 20 | PropertyBag allOptions = new PropertyBag(); 21 | 22 | // The export command could be updated in the future to accept an arbitrary set 23 | // of analyzers for which to build an options XML file suitable for configuring them. 24 | // Currently, we perform discovery against the built-in CodeFormatter rules 25 | // and analyzers only. 26 | ImmutableArray providers = DriverUtilities.GetExports(DefaultPlugInAssemblies); 27 | foreach (IOptionsProvider provider in providers) 28 | { 29 | foreach (IOption option in provider.GetOptions()) 30 | { 31 | allOptions.SetProperty(option, option.DefaultValue, cacheDescription: true); 32 | } 33 | } 34 | 35 | string exe = Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location); 36 | 37 | allOptions.SaveTo(exportOptions.OutputFilePath, id: exe + "-config"); 38 | Console.WriteLine("Configuration file saved to: " + Path.GetFullPath(exportOptions.OutputFilePath)); 39 | 40 | result = SUCCESS; 41 | } 42 | catch (Exception ex) 43 | { 44 | Console.Error.WriteLine(ex.ToString()); 45 | } 46 | 47 | return result; 48 | } 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ExportConfigurationOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using CommandLine; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | [Verb("exportConfig", HelpText = "Export rule options to an XML file that can be edited and used to configure subsequent analysis.")] 9 | public class ExportConfigurationOptions 10 | { 11 | [Value(0, HelpText = "Output path for exported analysis options", Required = true)] 12 | public string OutputFilePath { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ExportRulesMetadataCommandBase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.IO; 8 | using System.Text; 9 | 10 | using Microsoft.CodeAnalysis.Sarif.Sdk; 11 | using Microsoft.CodeAnalysis.Sarif.Readers; 12 | using Microsoft.CodeAnalysis.Sarif; 13 | 14 | using Newtonsoft.Json; 15 | 16 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 17 | { 18 | public abstract class ExportRulesMetadataCommandBase : PlugInDriverCommand 19 | { 20 | 21 | public override int Run(ExportRulesMetadataOptions exportOptions) 22 | { 23 | int result = FAILURE; 24 | 25 | try 26 | { 27 | ImmutableArray skimmers = DriverUtilities.GetExports(DefaultPlugInAssemblies); 28 | 29 | string format = ""; 30 | string outputFilePath = exportOptions.OutputFilePath; 31 | string extension = Path.GetExtension(outputFilePath); 32 | 33 | switch (extension) 34 | { 35 | case (".json"): 36 | case (".sarif"): 37 | { 38 | format = "SARIF"; 39 | ImmutableArray options = DriverUtilities.GetExports(DefaultPlugInAssemblies); 40 | OutputSarifRulesMetada(outputFilePath, skimmers, options); 41 | break; 42 | } 43 | 44 | case (".xml"): 45 | { 46 | format = "SonarQube"; 47 | OutputSonarQubeRulesMetada(outputFilePath, skimmers); 48 | break; 49 | } 50 | 51 | default: 52 | { 53 | throw new InvalidOperationException("Unrecognized output file extension: " + extension); 54 | } 55 | } 56 | 57 | result = SUCCESS; 58 | Console.WriteLine(format + " rules metadata exported to: " + Path.GetFullPath(outputFilePath)); 59 | } 60 | catch (Exception ex) 61 | { 62 | Console.Error.WriteLine(ex.ToString()); 63 | } 64 | 65 | return result; 66 | } 67 | 68 | private void OutputSonarQubeRulesMetada(string outputFilePath, ImmutableArray skimmers) 69 | { 70 | const string TAB = " "; 71 | var sb = new StringBuilder(); 72 | 73 | SortedDictionary sortedRuleContexts = new SortedDictionary(); 74 | 75 | foreach (IRuleDescriptor ruleDescriptor in skimmers) 76 | { 77 | int numericId = GetIdIntegerSuffix(ruleDescriptor.Id); 78 | sortedRuleContexts[numericId] = ruleDescriptor; 79 | } 80 | 81 | sb.AppendLine("" + Environment.NewLine + 82 | ""); 83 | 84 | foreach (IRuleDescriptor ruleContext in sortedRuleContexts.Values) 85 | { 86 | sb.AppendLine(TAB + ""); 87 | sb.AppendLine(TAB + TAB + "" + ruleContext.Id + ""); 88 | sb.AppendLine(TAB + TAB + "" + ruleContext.Name + ""); 89 | sb.AppendLine(TAB + TAB + "MAJOR"); 90 | 91 | sb.AppendLine(TAB + TAB + "" + Environment.NewLine + 92 | TAB + TAB + TAB + "" + Environment.NewLine + 95 | TAB + TAB + ""); 96 | 97 | sb.AppendLine(TAB + TAB + "binary"); 98 | sb.AppendLine(TAB + ""); 99 | } 100 | 101 | sb.AppendLine("" + Environment.NewLine + ""); 102 | 103 | File.WriteAllText(outputFilePath, sb.ToString()); 104 | } 105 | 106 | private void OutputSarifRulesMetada(string outputFilePath, ImmutableArray skimmers, ImmutableArray options) 107 | { 108 | var log = new ResultLog(); 109 | 110 | log.Version = SarifVersion.ZeroDotFour; 111 | 112 | // The SARIF spec currently requires an array 113 | // of run logs with at least one member 114 | log.RunLogs = new List(); 115 | 116 | var runLog = new RunLog(); 117 | runLog.ToolInfo = new ToolInfo(); 118 | 119 | runLog.ToolInfo.InitializeFromAssembly(this.GetType().Assembly, Prerelease); 120 | runLog.Results = new List(); 121 | 122 | log.RunLogs.Add(runLog); 123 | runLog.ToolInfo.RuleInfo = new List(); 124 | 125 | SortedDictionary sortedRuleDescriptors = new SortedDictionary(); 126 | 127 | foreach (IRuleDescriptor descriptor in skimmers) 128 | { 129 | var ruleDescriptor = new RuleDescriptor(); 130 | 131 | ruleDescriptor.Id = descriptor.Id; 132 | ruleDescriptor.Name = descriptor.Name; 133 | ruleDescriptor.FullDescription = descriptor.FullDescription; 134 | 135 | int numericId = GetIdIntegerSuffix(ruleDescriptor.Id); 136 | 137 | sortedRuleDescriptors[numericId] = ruleDescriptor; 138 | } 139 | 140 | foreach (RuleDescriptor ruleDescriptor in sortedRuleDescriptors.Values) 141 | { 142 | runLog.ToolInfo.RuleInfo.Add(ruleDescriptor); 143 | } 144 | 145 | var settings = new JsonSerializerSettings() 146 | { 147 | ContractResolver = SarifContractResolver.Instance, 148 | Formatting = Formatting.Indented, 149 | }; 150 | File.WriteAllText(outputFilePath, JsonConvert.SerializeObject(log, settings)); 151 | } 152 | 153 | private int GetIdIntegerSuffix(string id) 154 | { 155 | int alphaCount = 0; 156 | 157 | foreach (char ch in id) 158 | { 159 | if (Char.IsLetter(ch)) 160 | { 161 | alphaCount++; 162 | continue; 163 | } 164 | break; 165 | } 166 | return Int32.Parse(id.Substring(alphaCount)); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ExportRulesMetadataOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using CommandLine; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | [Verb("exportRules", HelpText = "Export rules metadata to a SARIF or SonarQube XML file.")] 9 | public class ExportRulesMetadataOptions 10 | { 11 | [Value(0, HelpText = "Output path for exported analysis options. Use a .json or .sarif extension to produce SARIF. Use .xml to produce a SonarQube rule descriptor file.", Required = true)] 12 | public string OutputFilePath { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/Hash.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.Security.Cryptography; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | public static class HashUtilities 11 | { 12 | public static string ComputeSha256Hash(string fileName) 13 | { 14 | string sha256Hash = null; 15 | 16 | try 17 | { 18 | using (FileStream stream = File.OpenRead(fileName)) 19 | { 20 | using (var bufferedStream = new BufferedStream(stream, 1024 * 32)) 21 | { 22 | var sha = new SHA256Cng(); 23 | byte[] checksum = sha.ComputeHash(bufferedStream); 24 | sha256Hash = BitConverter.ToString(checksum).Replace("-", String.Empty); 25 | } 26 | } 27 | } 28 | catch (IOException) { } 29 | catch (UnauthorizedAccessException) { } 30 | return sha256Hash; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/IAnalysisContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.using System; 3 | 4 | using System; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.Sdk; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | public interface IAnalysisContext : IDisposable 11 | { 12 | Uri TargetUri { get; set; } 13 | 14 | Exception TargetLoadException { get; set; } 15 | 16 | bool IsValidAnalysisTarget { get; } 17 | 18 | IRuleDescriptor Rule { get; set; } 19 | 20 | PropertyBag Policy { get; set; } 21 | 22 | IResultLogger Logger { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/IAnalyzeOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | public interface IAnalyzeOptions 9 | { 10 | IEnumerable TargetFileSpecifiers { get; } 11 | 12 | string OutputFilePath { get; } 13 | 14 | bool Verbose { get; } 15 | 16 | bool Recurse { get; } 17 | 18 | string PolicyFilePath { get; } 19 | 20 | bool Statistics { get; } 21 | 22 | bool ComputeTargetsHash { get; } 23 | 24 | IList PlugInFilePaths { get; } 25 | } 26 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/IOption.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | public interface IOption 9 | { 10 | string Description { get; } 11 | string Feature { get; } 12 | string Name { get; } 13 | Type Type { get; } 14 | object DefaultValue { get; } 15 | bool IsPerLanguage { get; } 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/IOptionsProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | public interface IOptionsProvider 9 | { 10 | IEnumerable GetOptions(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/IResultLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.Sdk; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | public interface IResultLogger 9 | { 10 | void Log(ResultKind messageKind, IAnalysisContext context, string message); 11 | 12 | void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ISkimmer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.Sdk; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | public interface ISkimmer : IRuleDescriptor 9 | { 10 | /// 11 | /// Initialize method for skimmer instance. This method will only 12 | /// only be called a single time per skimmer instantiation. 13 | /// 14 | /// 15 | void Initialize(TContext context); 16 | 17 | /// 18 | /// Determine whether a target is a valid target for analysis. 19 | /// May be called from multiple threads. 20 | /// 21 | /// 22 | /// 23 | /// An analysis applicability value that indicates whether a check is 24 | /// applicable to a specified target, is not applicable to a specified target, 25 | /// or is not applicable to any target due to the absence of a configured 26 | /// policy. In cases where the analysis is determined not to be applicable, 27 | /// the 'reasonIfNotApplicable' property should be set to a string that 28 | /// describes the observed state or condition that prevents analysis. 29 | /// 30 | AnalysisApplicability CanAnalyze(TContext context, out string reasonIfNotApplicable); 31 | 32 | /// 33 | /// Analyze specified binary target and use context-resident loggers 34 | /// to record the results of the analysis. May be called from multiple threads. 35 | /// 36 | /// 37 | void Analyze(TContext context); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/IntegerSet.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Runtime.Serialization; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | [Serializable] 11 | public class IntegerSet : HashSet 12 | { 13 | public IntegerSet() { } 14 | 15 | public IntegerSet(IEnumerable integers) : base(integers) { } 16 | 17 | protected IntegerSet(SerializationInfo info, StreamingContext context) 18 | : base(info, context) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/MessageUtilities.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Diagnostics; 6 | using System.Globalization; 7 | using System.IO; 8 | using Microsoft.CodeAnalysis.Sarif.Sdk; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 11 | { 12 | public static class MessageUtilities 13 | { 14 | public static string BuildMessage(IAnalysisContext context, string messageFormatString, params string[] arguments) 15 | { 16 | // By convention, the first argument is always the target name, 17 | // which we retrieve from the context 18 | Debug.Assert(File.Exists(context.TargetUri.LocalPath)); 19 | string targetName = Path.GetFileName(context.TargetUri.LocalPath); 20 | 21 | string[] fullArguments = new string[arguments != null ? arguments.Length + 1 : 1]; 22 | fullArguments[0] = targetName; 23 | 24 | if (fullArguments.Length > 1) 25 | { 26 | arguments.CopyTo(fullArguments, 1); 27 | } 28 | 29 | return String.Format(CultureInfo.InvariantCulture, 30 | messageFormatString, fullArguments); 31 | } 32 | 33 | 34 | public static string BuildTargetNotAnalyzedMessage(string targetPath, string ruleName, string reason) 35 | { 36 | targetPath = Path.GetFileName(targetPath); 37 | 38 | // Image '{0}' was not evaluated for check '{1}' as the analysis 39 | // is not relevant based on observed metadata: {2} 40 | return String.Format( 41 | CultureInfo.InvariantCulture, 42 | SdkResources.TargetNotAnalyzed_NotApplicable, 43 | targetPath, 44 | ruleName, 45 | reason); 46 | } 47 | 48 | public static string BuildRuleDisabledDueToMissingPolicyMessage(string ruleName, string reason) 49 | { 50 | // BinSkim command-line using the --policy argument (recommended), or 51 | // pass --defaultPolicy to invoke built-in settings. Invoke the 52 | // BinSkim.exe 'export' command to produce an initial policy file 53 | // that can be edited if required and passed back into the tool. 54 | return String.Format( 55 | CultureInfo.InvariantCulture, 56 | SdkResources.RuleWasDisabledDueToMissingPolicy, 57 | ruleName, 58 | reason); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/NoteDescriptors.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using Microsoft.CodeAnalysis.Sarif.Sdk; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | public static class NoteDescriptors 11 | { 12 | public static IRuleDescriptor AnalyzingTarget = new RuleDescriptor() 13 | { 14 | // A file is being analyzed. 15 | Id = "MSG1001", 16 | Name = nameof(AnalyzingTarget), 17 | FullDescription = SdkResources.InvalidTarget_Description, 18 | FormatSpecifiers = BuildDictionary(new string[] { 19 | nameof(SdkResources.Analyzing), 20 | }) 21 | }; 22 | 23 | public static IRuleDescriptor InvalidTarget = new RuleDescriptor() 24 | { 25 | // A file was skipped as it does not appear to be a valid target for analysis. 26 | Id = "MSG1002", 27 | Name = nameof(InvalidTarget), 28 | FullDescription = SdkResources.InvalidTarget_Description, 29 | FormatSpecifiers = BuildDictionary(new string[] { 30 | nameof(SdkResources.TargetNotAnalyzed_InvalidTarget), 31 | }) 32 | }; 33 | 34 | private static Dictionary BuildDictionary(IEnumerable resourceNames) 35 | { 36 | // Note this dictionary provides for case-insensitive keys 37 | var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); 38 | 39 | foreach (string resourceName in resourceNames) 40 | { 41 | string resourceValue = SdkResources.ResourceManager.GetString(resourceName); 42 | dictionary[resourceName] = resourceValue; 43 | } 44 | 45 | return dictionary; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/PerLanguageOption.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | /// 9 | /// An option that can be specified once per language. 10 | /// 11 | /// 12 | public class PerLanguageOption : IOption 13 | { 14 | /// 15 | /// A description of this specificoption. 16 | /// 17 | public string Description { get; } 18 | 19 | /// 20 | /// Feature this option is associated with. 21 | /// 22 | public string Feature { get; } 23 | 24 | /// 25 | /// The name of the option. 26 | /// 27 | public string Name { get; } 28 | 29 | /// 30 | /// The type of the option value. 31 | /// 32 | public Type Type 33 | { 34 | get { return typeof(T); } 35 | } 36 | 37 | /// 38 | /// The default option value. 39 | /// 40 | public Func DefaultValue { get; } 41 | 42 | public PerLanguageOption(string feature, string name, Func defaultValue, string description = null) 43 | { 44 | if (string.IsNullOrWhiteSpace(feature)) 45 | { 46 | throw new ArgumentNullException(nameof(feature)); 47 | } 48 | 49 | if (string.IsNullOrWhiteSpace(name)) 50 | { 51 | throw new ArgumentException(nameof(name)); 52 | } 53 | 54 | this.Feature = feature; 55 | this.Name = name; 56 | this.DefaultValue = defaultValue; 57 | this.Description = description; 58 | } 59 | 60 | Type IOption.Type 61 | { 62 | get { return typeof(T); } 63 | } 64 | 65 | object IOption.DefaultValue 66 | { 67 | get { return this.DefaultValue(); } 68 | } 69 | 70 | bool IOption.IsPerLanguage 71 | { 72 | get { return true; } 73 | } 74 | 75 | public override string ToString() 76 | { 77 | return string.Format("{0} - {1}", this.Feature, this.Name); 78 | } 79 | } 80 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/PlugInDriverCommand.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Reflection; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | public abstract class PlugInDriverCommand : DriverCommand 11 | { 12 | public virtual IEnumerable DefaultPlugInAssemblies 13 | { 14 | get { return null; } 15 | set { throw new InvalidOperationException(); } 16 | } 17 | 18 | public abstract string Prerelease { get; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/PropertyBag.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.ComponentModel; 8 | using System.IO; 9 | using System.Runtime.Serialization; 10 | using System.Xml; 11 | 12 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 13 | { 14 | [Serializable] 15 | public class PropertyBag : TypedPropertyBag 16 | { 17 | public PropertyBag() : base() { } 18 | 19 | public PropertyBag( 20 | PropertyBag initializer = null, 21 | IEqualityComparer comparer = null) 22 | : base(initializer, comparer) 23 | { 24 | } 25 | 26 | protected PropertyBag(SerializationInfo info, StreamingContext context) 27 | : base(info, context) 28 | { 29 | } 30 | 31 | public string Name { get; set; } 32 | 33 | public virtual T GetProperty(PerLanguageOption setting, bool cacheDefault = true) 34 | { 35 | if (setting == null) { throw new ArgumentNullException("setting"); } 36 | 37 | PropertyBag properties = GetSettingsContainer(setting, cacheDefault); 38 | 39 | T value; 40 | if (!properties.TryGetProperty(setting.Name, out value) && setting.DefaultValue != null) 41 | { 42 | value = setting.DefaultValue(); 43 | 44 | if (cacheDefault) { properties[setting.Name] = value; } 45 | } 46 | return value; 47 | } 48 | 49 | public override void SetProperty(IOption setting, object value, bool cacheDescription = false) 50 | { 51 | if (setting == null) { throw new ArgumentNullException("setting"); } 52 | 53 | PropertyBag properties = GetSettingsContainer(setting, true); 54 | 55 | if (value == null && properties.ContainsKey(setting.Name)) 56 | { 57 | properties.Remove(setting.Name); 58 | return; 59 | } 60 | 61 | if (cacheDescription) 62 | { 63 | SettingNameToDescriptionsMap = SettingNameToDescriptionsMap ?? new Dictionary(); 64 | SettingNameToDescriptionsMap[setting.Name] = setting.Description; 65 | } 66 | 67 | properties[setting.Name] = value; 68 | } 69 | 70 | internal bool TryGetProperty(string key, out T value) 71 | { 72 | value = default(T); 73 | 74 | object result; 75 | if (this.TryGetValue(key, out result)) 76 | { 77 | if (result is T) 78 | { 79 | value = (T)result; 80 | return true; 81 | } 82 | return TryConvertFromString((string)result, out value); 83 | } 84 | 85 | return false; 86 | } 87 | 88 | private PropertyBag GetSettingsContainer(IOption setting, bool cacheDefault) 89 | { 90 | PropertyBag properties = this; 91 | 92 | if (String.IsNullOrEmpty(Name)) 93 | { 94 | object propertiesObject; 95 | string featureOptionsName = setting.Feature + ".Options"; 96 | if (!TryGetValue(featureOptionsName, out propertiesObject)) 97 | { 98 | properties = new PropertyBag(); 99 | if (cacheDefault) { this[featureOptionsName] = properties; } 100 | properties.Name = featureOptionsName; 101 | } 102 | else 103 | { 104 | properties = (PropertyBag)propertiesObject; 105 | } 106 | } 107 | return properties; 108 | } 109 | 110 | private static bool TryConvertFromString(string source, out T destination) 111 | { 112 | destination = default(T); 113 | if (source == null) return false; 114 | TypeConverter converter = TypeDescriptor.GetConverter(typeof(T)); 115 | destination = (T)converter.ConvertFrom(source); 116 | return destination != null; 117 | } 118 | 119 | public void SaveTo(string filePath, string id) 120 | { 121 | using (var writer = new FileStream(filePath, FileMode.Create, FileAccess.Write)) 122 | SaveTo(writer, id); 123 | } 124 | 125 | public void SaveTo(Stream stream, string id) 126 | { 127 | var settings = new XmlWriterSettings { Indent = true }; 128 | using (XmlWriter writer = XmlWriter.Create(stream, settings)) 129 | { 130 | this.SavePropertyBagToStream(writer, settings, id, SettingNameToDescriptionsMap); 131 | } 132 | } 133 | 134 | public void LoadFrom(string filePath) 135 | { 136 | using (var reader = new FileStream(filePath, FileMode.Open, FileAccess.Read)) 137 | LoadFrom(reader); 138 | } 139 | 140 | public void LoadFrom(Stream stream) 141 | { 142 | using (XmlReader reader = XmlReader.Create(stream)) 143 | { 144 | if (reader.IsStartElement(PropertyBagExtensionMethods.PROPERTIES_ID)) 145 | { 146 | bool isEmpty = reader.IsEmptyElement; 147 | this.Clear(); 148 | 149 | // Note: we do not recover the property bag id 150 | // as there is no current product use for the value 151 | 152 | reader.ReadStartElement(PropertyBagExtensionMethods.PROPERTIES_ID); 153 | 154 | this.LoadPropertiesFromXmlStream(reader); 155 | if (!isEmpty) reader.ReadEndElement(); 156 | } 157 | } 158 | } 159 | 160 | // Current consumers of this data expect that child namespaces 161 | // will always precede parent namespaces, if also included. 162 | public static ImmutableArray DefaultNamespaces = new List( 163 | new string[] { 164 | "Microsoft.CodeAnalysis.Options.", 165 | "Microsoft.CodeAnalysis." 166 | }).ToImmutableArray(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/ResultLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Reflection; 8 | using Microsoft.CodeAnalysis.Sarif.Writers; 9 | using Newtonsoft.Json; 10 | using Microsoft.CodeAnalysis.Sarif; 11 | using Microsoft.CodeAnalysis.Sarif.Sdk; 12 | 13 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 14 | { 15 | public class ResultLogger 16 | { 17 | private FileStream _fileStream; 18 | private TextWriter _textWriter; 19 | private JsonTextWriter _jsonTextWriter; 20 | private ResultLogJsonWriter _issueLogJsonWriter; 21 | 22 | public ResultLogger( 23 | Assembly assembly, 24 | string outputFilePath, 25 | bool verbose, 26 | IEnumerable analysisTargets, 27 | bool computeTargetsHash, 28 | string prereleaseInfo) 29 | { 30 | Verbose = verbose; 31 | 32 | _fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.None); 33 | _textWriter = new StreamWriter(_fileStream); 34 | _jsonTextWriter = new JsonTextWriter(_textWriter); 35 | 36 | // for debugging it is nice to have the following line added. 37 | _jsonTextWriter.Formatting = Newtonsoft.Json.Formatting.Indented; 38 | 39 | _issueLogJsonWriter = new ResultLogJsonWriter(_jsonTextWriter); 40 | 41 | var toolInfo = new ToolInfo(); 42 | toolInfo.InitializeFromAssembly(assembly, prereleaseInfo); 43 | 44 | RunInfo runInfo = new RunInfo(); 45 | runInfo.AnalysisTargets = new List(); 46 | 47 | foreach (string target in analysisTargets) 48 | { 49 | var fileReference = new FileReference() 50 | { 51 | Uri = target.CreateUriForJsonSerialization(), 52 | }; 53 | 54 | if (computeTargetsHash) 55 | { 56 | string sha256Hash = HashUtilities.ComputeSha256Hash(target) ?? "[could not compute file hash]"; 57 | fileReference.Hashes = new List(new Hash[] 58 | { 59 | new Hash() 60 | { 61 | Value = sha256Hash, 62 | Algorithm = AlgorithmKind.Sha256, 63 | } 64 | }); 65 | } 66 | runInfo.AnalysisTargets.Add(fileReference); 67 | } 68 | runInfo.InvocationInfo = Environment.CommandLine; 69 | 70 | _issueLogJsonWriter.WriteToolAndRunInfo(toolInfo, runInfo); 71 | } 72 | 73 | public bool Verbose { get; set; } 74 | 75 | public Uri Uri 76 | { 77 | get 78 | { 79 | throw new NotImplementedException(); 80 | } 81 | } 82 | 83 | public IRuleDescriptor Rule 84 | { 85 | get 86 | { 87 | throw new NotImplementedException(); 88 | } 89 | } 90 | 91 | public void Dispose() 92 | { 93 | // Disposing the json writer closes the stream but the textwriter 94 | // still needs to be disposed or closed to write the results 95 | if (_issueLogJsonWriter != null) { _issueLogJsonWriter.Dispose(); } 96 | if (_textWriter != null) { _textWriter.Dispose(); } 97 | } 98 | 99 | public void Log(ResultKind resultKind, IAnalysisContext context, string message) 100 | { 101 | Result result = new Result(); 102 | 103 | result.RuleId = context.Rule.Id; 104 | result.FullMessage = message; 105 | result.Kind = resultKind; 106 | result.Locations = new[]{ 107 | new Sarif.Sdk.Location { 108 | AnalysisTarget = new[] 109 | { 110 | new PhysicalLocationComponent 111 | { 112 | // Why? When NewtonSoft serializes this Uri, it will use the 113 | // original string used to construct the Uri. For a file path, 114 | // this will be the local file path. We want to persist this 115 | // information using the file:// protocol rendering, however. 116 | Uri = context.TargetUri.LocalPath.CreateUriForJsonSerialization(), 117 | MimeType = MimeType.Binary 118 | } 119 | } 120 | } 121 | }; 122 | 123 | _issueLogJsonWriter.WriteResult(result); 124 | } 125 | private void WriteJsonIssue(string binary, string ruleId, string message, ResultKind issueKind) 126 | { 127 | Result result = new Result(); 128 | 129 | result.RuleId = ruleId; 130 | result.FullMessage = message; 131 | result.Kind = issueKind; 132 | result.Locations = new[]{ 133 | new Sarif.Sdk.Location { 134 | AnalysisTarget = new[] 135 | { 136 | new PhysicalLocationComponent 137 | { 138 | // Why? When NewtonSoft serializes this Uri, it will use the 139 | // original string used to construct the Uri. For a file path, 140 | // this will be the local file path. We want to persist this 141 | // information using the file:// protocol rendering, however. 142 | Uri = binary.CreateUriForJsonSerialization(), 143 | MimeType = MimeType.Binary 144 | } 145 | } 146 | } 147 | }; 148 | 149 | _issueLogJsonWriter.WriteResult(result); 150 | } 151 | 152 | public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message) 153 | { 154 | throw new NotImplementedException(); 155 | } 156 | } 157 | } -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/RuntimeConditions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 7 | { 8 | // This enum is used to identify specific runtime conditions 9 | // encountered during execution. This mechanism is used by 10 | // unit tests to ensure that failure conditions travel expected 11 | // code paths. These conditions are a combination of fatal 12 | // and non-fatal circumstances 13 | [Flags] 14 | public enum RuntimeConditions 15 | { 16 | NoErrors = 0, 17 | 18 | // Not used today but perhaps soon... 19 | //CouldNotLoadCustomLoggerAssembly, 20 | //CouldNotLoadCustomLoggerType, 21 | //UnrecognizedDefaultLoggerExtension, 22 | //MalformedCustomLoggersArgument, 23 | //LoggerFailedInitialization, 24 | //LoggerRaisedExceptionOnInitialization, 25 | //LoggerRaisedExceptionOnWrite, 26 | //LoggerRaisedExceptionOnClose, 27 | 28 | // Fatal conditions 29 | ExceptionInstantiatingSkimmers = 0x01, 30 | ExceptionInSkimmerInitialize = 0x02, 31 | ExceptionRaisedInSkimmerCanAnalyze = 0x04, 32 | ExceptionInSkimmerAnalyze = 0x08, 33 | ExceptionCreatingLogfile = 0x10, 34 | ExceptionInEngine = 0x20, 35 | ExceptionLoadingTargetFile = 0x40, 36 | ExceptionLoadingAnalysisPlugIn = 0x80, 37 | Fatal = (Int32.MaxValue ^ NonFatal), 38 | 39 | // Non-fatal conditions 40 | OneOrMoreTargetsNotValidToAnalyze = 0x80, 41 | 42 | NonFatal = OneOrMoreTargetsNotValidToAnalyze, 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/SarifLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Reflection; 8 | 9 | using Microsoft.CodeAnalysis.Sarif; 10 | using Microsoft.CodeAnalysis.Sarif.Sdk; 11 | using Microsoft.CodeAnalysis.Sarif.Writers; 12 | 13 | using Newtonsoft.Json; 14 | 15 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 16 | { 17 | public class SarifLogger : IDisposable, IResultLogger 18 | { 19 | private FileStream _fileStream; 20 | private TextWriter _textWriter; 21 | private JsonTextWriter _jsonTextWriter; 22 | private ResultLogJsonWriter _issueLogJsonWriter; 23 | 24 | public static ToolInfo CreateDefaultToolInfo(string prereleaseInfo = null) 25 | { 26 | Assembly assembly = typeof(SarifLogger).Assembly; 27 | string name = Path.GetFileNameWithoutExtension(assembly.Location); 28 | Version version = assembly.GetName().Version; 29 | 30 | ToolInfo toolInfo = new ToolInfo(); 31 | toolInfo.Name = name; 32 | toolInfo.Version = version.Major.ToString() + "." + version.Minor.ToString() + "." + version.Build.ToString(); 33 | toolInfo.FullName = name + " " + toolInfo.Version + (prereleaseInfo ?? ""); 34 | 35 | return toolInfo; 36 | } 37 | 38 | public SarifLogger( 39 | string outputFilePath, 40 | bool verbose, 41 | IEnumerable analysisTargets, 42 | bool computeTargetsHash, 43 | string prereleaseInfo) 44 | { 45 | Verbose = verbose; 46 | 47 | _fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.None); 48 | _textWriter = new StreamWriter(_fileStream); 49 | _jsonTextWriter = new JsonTextWriter(_textWriter); 50 | 51 | // for debugging it is nice to have the following line added. 52 | _jsonTextWriter.Formatting = Newtonsoft.Json.Formatting.Indented; 53 | 54 | _issueLogJsonWriter = new ResultLogJsonWriter(_jsonTextWriter); 55 | 56 | var toolInfo = CreateDefaultToolInfo(prereleaseInfo); 57 | 58 | RunInfo runInfo = new RunInfo(); 59 | runInfo.AnalysisTargets = new List(); 60 | 61 | foreach (string target in analysisTargets) 62 | { 63 | var fileReference = new FileReference() 64 | { 65 | Uri = target.CreateUriForJsonSerialization(), 66 | }; 67 | 68 | if (computeTargetsHash) 69 | { 70 | string sha256Hash = HashUtilities.ComputeSha256Hash(target) ?? "[could not compute file hash]"; 71 | fileReference.Hashes = new List(new Hash[] 72 | { 73 | new Hash() 74 | { 75 | Value = sha256Hash, 76 | Algorithm = AlgorithmKind.Sha256, 77 | } 78 | }); 79 | } 80 | runInfo.AnalysisTargets.Add(fileReference); 81 | } 82 | runInfo.InvocationInfo = Environment.CommandLine; 83 | 84 | _issueLogJsonWriter.WriteToolAndRunInfo(toolInfo, runInfo); 85 | } 86 | 87 | public bool Verbose { get; set; } 88 | 89 | public void Dispose() 90 | { 91 | // Disposing the json writer closes the stream but the textwriter 92 | // still needs to be disposed or closed to write the results 93 | if (_issueLogJsonWriter != null) { _issueLogJsonWriter.Dispose(); } 94 | if (_textWriter != null) { _textWriter.Dispose(); } 95 | } 96 | 97 | public void Log(ResultKind messageKind, IAnalysisContext context, string message) 98 | { 99 | switch (messageKind) 100 | { 101 | case ResultKind.Pass: 102 | { 103 | if (Verbose) 104 | { 105 | WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.Pass); 106 | } 107 | break; 108 | } 109 | 110 | case ResultKind.Error: 111 | case ResultKind.Warning: 112 | { 113 | WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.Error); 114 | break; 115 | } 116 | 117 | case ResultKind.NotApplicable: 118 | { 119 | if (Verbose) 120 | { 121 | WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.NotApplicable); 122 | } 123 | break; 124 | } 125 | 126 | case ResultKind.Note: 127 | { 128 | if (Verbose) 129 | { 130 | WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.Note); 131 | } 132 | break; 133 | } 134 | 135 | case ResultKind.ConfigurationError: 136 | { 137 | WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.ConfigurationError); 138 | break; 139 | } 140 | 141 | case ResultKind.InternalError: 142 | { 143 | WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.InternalError); 144 | break; 145 | } 146 | 147 | default: 148 | { 149 | throw new InvalidOperationException(); 150 | } 151 | } 152 | } 153 | private void WriteJsonIssue(string binary, string ruleId, string message, ResultKind issueKind) 154 | { 155 | Result result = new Result(); 156 | 157 | result.RuleId = ruleId; 158 | result.FullMessage = message; 159 | result.Kind = issueKind; 160 | result.Locations = new[]{ 161 | new Sarif.Sdk.Location { 162 | AnalysisTarget = new[] 163 | { 164 | new PhysicalLocationComponent 165 | { 166 | // Why? When NewtonSoft serializes this Uri, it will use the 167 | // original string used to construct the Uri. For a file path, 168 | // this will be the local file path. We want to persist this 169 | // information using the file:// protocol rendering, however. 170 | Uri = binary.CreateUriForJsonSerialization(), 171 | MimeType = MimeType.Binary 172 | } 173 | } 174 | } 175 | }; 176 | 177 | _issueLogJsonWriter.WriteResult(result); 178 | } 179 | 180 | public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message) 181 | { 182 | throw new NotImplementedException(); 183 | } 184 | } 185 | } 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/SkimmerBase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 8 | { 9 | public abstract class SkimmerBase : ISkimmer 10 | { 11 | public SkimmerBase() 12 | { 13 | this.Options = new Dictionary(); 14 | this.FormatSpecifiers = new Dictionary(); 15 | } 16 | 17 | public Dictionary FormatSpecifiers { get; } 18 | 19 | abstract public string Id { get; } 20 | 21 | abstract public string FullDescription { get; } 22 | 23 | public virtual string ShortDescription 24 | { 25 | get { return FirstSentence(FullDescription); } 26 | } 27 | 28 | internal static string FirstSentence(string fullDescription) 29 | { 30 | int charCount = 0; 31 | bool withinApostrophe = false; 32 | 33 | foreach (char ch in fullDescription) 34 | { 35 | charCount++; 36 | switch (ch) 37 | { 38 | case '\'': 39 | { 40 | withinApostrophe = !withinApostrophe; 41 | continue; 42 | } 43 | 44 | case '.': 45 | { 46 | if (withinApostrophe) { continue; } 47 | return fullDescription.Substring(0, charCount); 48 | } 49 | } 50 | } 51 | int length = Math.Min(fullDescription.Length, 80); 52 | bool truncated = length < fullDescription.Length; 53 | return fullDescription.Substring(0, length) + (truncated ? "..." : ""); 54 | } 55 | 56 | public virtual string Name { get { return this.GetType().Name; } } 57 | 58 | public Dictionary Options { get; } 59 | 60 | public Dictionary Properties { get; } 61 | 62 | public virtual void Initialize(TContext context) { } 63 | 64 | public virtual AnalysisApplicability CanAnalyze(TContext context, out string reasonIfNotApplicable) 65 | { 66 | reasonIfNotApplicable = null; 67 | return AnalysisApplicability.ApplicableToSpecifiedTarget; 68 | } 69 | 70 | public abstract void Analyze(TContext context); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/StatisticsLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Diagnostics; 6 | 7 | using Microsoft.CodeAnalysis.Sarif.Sdk; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 10 | { 11 | public class StatisticsLogger : IResultLogger 12 | { 13 | private Stopwatch _stopwatch; 14 | private long _targetsCount; 15 | private long _invalidTargetsCount; 16 | 17 | public StatisticsLogger() 18 | { 19 | _stopwatch = Stopwatch.StartNew(); 20 | } 21 | 22 | public void Log(ResultKind messageKind, IAnalysisContext context, string message) 23 | { 24 | switch (messageKind) 25 | { 26 | 27 | case ResultKind.Pass: 28 | { 29 | break; 30 | } 31 | 32 | case ResultKind.Error: 33 | { 34 | break; 35 | } 36 | 37 | case ResultKind.Warning: 38 | { 39 | break; 40 | } 41 | 42 | case ResultKind.NotApplicable: 43 | { 44 | if (context.Rule.Id == NoteDescriptors.InvalidTarget.Id) 45 | { 46 | _invalidTargetsCount++; 47 | } 48 | break; 49 | } 50 | 51 | case ResultKind.Note: 52 | { 53 | if (context.Rule.Id == NoteDescriptors.AnalyzingTarget.Id) 54 | { 55 | _targetsCount++; 56 | } 57 | break; 58 | } 59 | 60 | case ResultKind.InternalError: 61 | { 62 | break; 63 | } 64 | 65 | case ResultKind.ConfigurationError: 66 | { 67 | break; 68 | } 69 | 70 | default: 71 | { 72 | throw new InvalidOperationException(); 73 | } 74 | } 75 | } 76 | 77 | public void Dispose() 78 | { 79 | Console.WriteLine(); 80 | Console.WriteLine("# valid targets: " + _targetsCount.ToString()); 81 | Console.WriteLine("# invalid targets: " + _invalidTargetsCount.ToString()); 82 | Console.WriteLine("Time elapsed: " + _stopwatch.Elapsed.ToString()); 83 | } 84 | 85 | public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message) 86 | { 87 | throw new NotImplementedException(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/StringSet.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Runtime.Serialization; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | [Serializable] 11 | public class StringSet : HashSet 12 | { 13 | public StringSet() { } 14 | 15 | public StringSet(IEnumerable strings) : base(strings) { } 16 | 17 | protected StringSet(SerializationInfo info, StreamingContext context) 18 | : base(info, context) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Sarif.Driver/Sdk/TypedPropertyBag.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Runtime.Serialization; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk 9 | { 10 | [Serializable] 11 | public class TypedPropertyBag : Dictionary where T : new() 12 | { 13 | public TypedPropertyBag() : this(null, StringComparer.Ordinal) 14 | { 15 | } 16 | 17 | public TypedPropertyBag(PropertyBag initializer, IEqualityComparer comparer) : base(comparer) 18 | { 19 | if (initializer != null) 20 | { 21 | foreach (string key in initializer.Keys) 22 | { 23 | this[key] = (T)initializer[key]; 24 | } 25 | } 26 | } 27 | 28 | protected TypedPropertyBag(SerializationInfo info, StreamingContext context) 29 | : base(info, context) 30 | { 31 | } 32 | 33 | protected Dictionary SettingNameToDescriptionsMap { get; set; } 34 | 35 | public virtual T GetProperty(PerLanguageOption setting, bool cacheDefault = true) 36 | { 37 | if (setting == null) { throw new ArgumentNullException("setting"); } 38 | 39 | T value; 40 | if (!base.TryGetValue(setting.Name, out value) && setting.DefaultValue != null) 41 | { 42 | value = setting.DefaultValue(); 43 | 44 | if (cacheDefault) { this[setting.Name] = value; } 45 | } 46 | return value; 47 | } 48 | 49 | public virtual void SetProperty(IOption setting, T value, bool cacheDescription = false) 50 | { 51 | if (setting == null) { throw new ArgumentNullException("setting"); } 52 | 53 | if (value == null && this.ContainsKey(setting.Name)) 54 | { 55 | this.Remove(setting.Name); 56 | return; 57 | } 58 | 59 | if (cacheDescription) 60 | { 61 | SettingNameToDescriptionsMap = SettingNameToDescriptionsMap ?? new Dictionary(); 62 | SettingNameToDescriptionsMap[setting.Name] = setting.Description; 63 | } 64 | 65 | this[setting.Name] = value; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Sarif.Driver/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.Driver 7 | { 8 | /// Extensions on the class. 9 | public static class StringExtensions 10 | { 11 | /// Gets a null value for null or whitespace strings. Otherwise passes though the source string unchanged. 12 | /// The string to check. 13 | /// If is null or whitespace, null; otherwise . 14 | public static string ClampToNullIfWhiteSpace(this string target) 15 | { 16 | if (String.IsNullOrWhiteSpace(target)) 17 | { 18 | return null; 19 | } 20 | 21 | return target; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Sarif.Driver/TempDirectory.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.IO; 6 | using System.Text; 7 | // Copyright (c) Microsoft. All rights reserved. 8 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 9 | 10 | // /******************************************************** 11 | // * * 12 | // * Copyright (C) Microsoft. All rights reserved. * 13 | // * * 14 | // ********************************************************/ 15 | 16 | namespace Microsoft.CodeAnalysis.Sarif.Driver 17 | { 18 | /// 19 | /// Temporary directory class; implements to ensure an effort is made to 20 | /// delete the temporary directory in the face of exceptions. If you only need a single file, use the 21 | /// class instead. 22 | /// 23 | /// 24 | /// 25 | public sealed class TempDirectory : IDisposable 26 | { 27 | /// Initializes a new instance of the class. 28 | public TempDirectory() 29 | { 30 | this.Name = TempFile.CreateTempName(); 31 | Directory.CreateDirectory(this.Name); 32 | } 33 | 34 | /// Gets the name of the generated directory. 35 | /// The name of the generated directory. 36 | public string Name { get; private set; } 37 | 38 | /// 39 | /// Gets the full path to a file with the supplied name inside this temp directory. 40 | /// 41 | /// File name of the file path to generate. 42 | /// 43 | /// The current combined with . 44 | /// 45 | public string Combine(string fileName) 46 | { 47 | return Path.Combine(this.Name, fileName); 48 | } 49 | 50 | /// Touches the given file in the temp directory. 51 | /// File name of the file path to generate. 52 | /// The full path to the file created or updated. 53 | public string Touch(string fileName) 54 | { 55 | string filePath = this.Combine(fileName); 56 | new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read | FileShare.Write | FileShare.Delete).Dispose(); 57 | return filePath; 58 | } 59 | 60 | /// Writes text to the given file in the temp directory. 61 | /// File name of the file path to generate. 62 | /// The text to write. 63 | /// The full path to the file created or updated. 64 | public string Write(string fileName, string text) 65 | { 66 | string filePath = this.Combine(fileName); 67 | File.WriteAllText(filePath, text, Encoding.UTF8); 68 | return filePath; 69 | } 70 | 71 | /// 72 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged 73 | /// resources. Makes a best-effort attempt to delete the temporary directory. 74 | /// 75 | /// 76 | public void Dispose() 77 | { 78 | this.DisposeImpl(); 79 | GC.SuppressFinalize(this); 80 | } 81 | 82 | /// 83 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged 84 | /// resources. Makes a best-effort attempt to delete the temporary directory. 85 | /// 86 | /// 87 | ~TempDirectory() 88 | { 89 | this.DisposeImpl(); 90 | } 91 | 92 | private void DisposeImpl() 93 | { 94 | try 95 | { 96 | Directory.Delete(this.Name, true); 97 | } 98 | catch (DirectoryNotFoundException) 99 | { 100 | // Not found; doesn't matter because this delete is best-effort. 101 | } 102 | catch (IOException) 103 | { 104 | // Lock violation; doesn't matter because this delete is best-effort. 105 | } 106 | catch (UnauthorizedAccessException) 107 | { 108 | // Access denied; doesn't matter because this delete is best-effort. 109 | } 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/Sarif.Driver/TempFile.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Diagnostics.CodeAnalysis; 6 | using System.IO; 7 | // Copyright (c) Microsoft. All rights reserved. 8 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 9 | 10 | // /******************************************************** 11 | // * * 12 | // * Copyright (C) Microsoft. All rights reserved. * 13 | // * * 14 | // ********************************************************/ 15 | 16 | namespace Microsoft.CodeAnalysis.Sarif.Driver 17 | { 18 | /// 19 | /// Temporary file class; implements to ensure an effort is made to 20 | /// delete the temporary file in the face of exceptions. If you need a directory or set of 21 | /// files instead of a file, use the class instead. 22 | /// 23 | /// 24 | /// 25 | public sealed class TempFile : IDisposable 26 | { 27 | /// Initializes a new instance of the class. 28 | public TempFile() 29 | { 30 | this.Name = CreateTempName(); 31 | } 32 | 33 | /// Initializes a new instance of the class where the file name has the indicated extension. 34 | /// The requested extension. 35 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 36 | public TempFile(string requestedExtension) 37 | { 38 | string name = CreateTempName(); 39 | if (!requestedExtension.StartsWith(".", StringComparison.Ordinal)) 40 | { 41 | name += "."; 42 | } 43 | 44 | this.Name = name + requestedExtension; 45 | } 46 | 47 | /// Gets the name of the generated file. 48 | /// The name of the generated file. 49 | public string Name { get; private set; } 50 | 51 | /// Creates temporary path name. 52 | /// A temporary path name where a file is not present on the file system. 53 | public static string CreateTempName() 54 | { 55 | // This file won't be present on the file system because GetRandomFileName 56 | // returns a path name generated from a cryptographically secure random number 57 | // generator (e.g. CryptGenRandom). 58 | return Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 59 | } 60 | 61 | /// 62 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged 63 | /// resources. Makes a best-effort attempt to delete the temporary file. 64 | /// 65 | /// 66 | public void Dispose() 67 | { 68 | this.DisposeImpl(); 69 | GC.SuppressFinalize(this); 70 | } 71 | 72 | /// 73 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged 74 | /// resources. Makes a best-effort attempt to delete the temporary file. 75 | /// 76 | /// 77 | ~TempFile() 78 | { 79 | this.DisposeImpl(); 80 | } 81 | 82 | private void DisposeImpl() 83 | { 84 | try 85 | { 86 | File.Delete(this.Name); 87 | } 88 | catch (DirectoryNotFoundException) 89 | { 90 | // Not found; doesn't matter because this delete is best-effort. 91 | } 92 | catch (IOException) 93 | { 94 | // Lock violation; doesn't matter because this delete is best-effort. 95 | } 96 | catch (UnauthorizedAccessException) 97 | { 98 | // Access denied; doesn't matter because this delete is best-effort. 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Sarif.Driver/VersionConstants.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT 2 | // license. See LICENSE file in the project root for full license information. 3 | namespace Microsoft.CodeAnalysis.Sarif 4 | { 5 | public static class VersionConstants 6 | { 7 | public const string Prerelease = "-beta"; 8 | public const string AssemblyVersion = "1.0.9"; 9 | public const string FileVersion = AssemblyVersion + ".0"; 10 | public const string Version = AssemblyVersion + Prerelease; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Sarif.Driver/XmlWriterExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.Diagnostics.CodeAnalysis; 8 | using System.Xml; 9 | // Copyright (c) Microsoft. All rights reserved. 10 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 11 | 12 | // /******************************************************** 13 | // * * 14 | // * Copyright (C) Microsoft. All rights reserved. * 15 | // * * 16 | // ********************************************************/ 17 | 18 | namespace Microsoft.CodeAnalysis.Sarif.Driver 19 | { 20 | /// Extension methods applied to class XmlWriter. 21 | public static class XmlWriterExtensions 22 | { 23 | /// Writes an element whose value is the supplied integer. 24 | /// The writer to which an element shall be written. 25 | /// The name of the element to be written. 26 | /// The value of the resulting element. 27 | [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0")] 28 | public static void WriteElementInt(this XmlWriter writer, string localElementName, int value) 29 | { 30 | if (String.IsNullOrWhiteSpace(localElementName)) 31 | { 32 | throw new ArgumentException(ExceptionStrings.XmlElementNameWasUnset, "localElementName"); 33 | } 34 | 35 | writer.WriteStartElement(String.Empty, localElementName, String.Empty); 36 | writer.WriteValue(value); 37 | writer.WriteEndElement(); 38 | } 39 | 40 | /// Writes an element if the supplied value is not null or whitespace. 41 | /// Thrown when is null. 42 | /// Thrown when is not set. 43 | /// The writer to which an element shall be written. 44 | /// The name of the element to be written. 45 | /// The element string if the element should be written; otherwise, null. 46 | public static void WriteElementIfNonempty(this XmlWriter writer, string localElementName, string elementValue) 47 | { 48 | if (writer == null) 49 | { 50 | throw new ArgumentNullException("writer"); 51 | } 52 | 53 | if (String.IsNullOrWhiteSpace(localElementName)) 54 | { 55 | throw new ArgumentException(ExceptionStrings.XmlElementNameWasUnset, "localElementName"); 56 | } 57 | 58 | if (String.IsNullOrWhiteSpace(elementValue)) 59 | { 60 | return; 61 | } 62 | 63 | writer.WriteElementString(localElementName, elementValue); 64 | } 65 | 66 | internal static void WriteEntryList( 67 | this XmlWriter writer, 68 | string entryListName, 69 | IEnumerable> entryListEntries) 70 | { 71 | Debug.Assert(!String.IsNullOrWhiteSpace(entryListName)); 72 | 73 | // Null is semantically the same as an empty list 74 | if (entryListEntries == null) 75 | { 76 | return; 77 | } 78 | 79 | using (IEnumerator> entryEnumerator = entryListEntries.GetEnumerator()) 80 | { 81 | if (!entryEnumerator.MoveNext()) 82 | { 83 | // There were no entries to enumerate. Don't even write the outer element. 84 | return; 85 | } 86 | 87 | // We now know that there is at least one entry to enumerate. As a result, we want to 88 | // write the outer node. 89 | writer.WriteStartElement(entryListName); 90 | 91 | do 92 | { 93 | KeyValuePair currentEntry = entryEnumerator.Current; 94 | writer.WriteStartElement("ENTRY"); 95 | writer.WriteAttributeString("key", currentEntry.Key); 96 | writer.WriteValue(currentEntry.Value); 97 | writer.WriteEndElement(); // 98 | } while (entryEnumerator.MoveNext()); 99 | } 100 | 101 | writer.WriteEndElement(); // 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Sarif.Driver/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | Any CPU 7 | $(MsBuildThisFileDirectory)..\bld\obj\$(MSBuildProjectName)\$(Platform)\$(Configuration)\ 8 | $(MsBuildThisFileDirectory)..\bld\bin\$(MSBuildProjectName)\$(Platform)_$(Configuration)\ 9 | $(MsBuildThisFileDirectory)..\bld\bin\DataModelGenerator\$(Platform)_$(Configuration)\ 10 | v4.5.2 11 | 512 12 | true 13 | true 14 | false 15 | prompt 16 | 4 17 | 18 | 19 | 20 | true 21 | full 22 | false 23 | DEBUG;TRACE 24 | 25 | 26 | pdbonly 27 | true 28 | TRACE 29 | 30 | 31 | x86 32 | 33 | 34 | x64 35 | 36 | 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------