Merge pull request #7 from Microsoft/1-0-9

Update to 1.0.9. Add line location to message output.
This commit is contained in:
Michael C. Fanning 2015-12-18 18:43:49 -08:00
Родитель 663c09f827 70123c3f4f
Коммит 101835a7bc
34 изменённых файлов: 2729 добавлений и 4 удалений

Просмотреть файл

@ -6,7 +6,7 @@ SETLOCAL
set MAJOR=1
set MINOR=0
set PATCH=6
set PATCH=9
set PRERELEASE=-beta
set VERSION_CONSTANTS=src\Sarif.Driver\VersionConstants.cs

Просмотреть файл

@ -3,11 +3,11 @@
<metadata>
<id>$id$</id>
<version>$major$.$minor$.$patch$$prerelease$</version>
<title>Microsoft SARIF Driver Framework</title>
<title>Microsoft SARIF Driver Framework (includes SARIF SDK)</title>
<authors>Microsoft</authors>
<owners>Michael C. Fanning, Billy O'Neal</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>SARIF-based classes and utilities for building static analysis drivers</description>
<description>SARIF-based classes and utilities for building static analysis drivers. Includes the SARIF SDK.</description>
<releaseNotes>Version $major$.$minor$.$patch$$prerelease$ of the Microsoft SARIF Driver Utilities</releaseNotes>
<copyright>Copyright Microsoft 2015</copyright>
<licenseUrl>https://github.com/Microsoft/driver-utilities/blob/master/LICENSE</licenseUrl>

Просмотреть файл

@ -0,0 +1,241 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Reflection;
using Microsoft.CodeAnalysis.Sarif.Driver.Sdk;
using Microsoft.CodeAnalysis.Sarif.Sdk;
using Microsoft.CodeAnalysis.Sarif.Readers;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class AnalyzeCommandBaseTests
{
private void ExceptionTestHelper(
ExceptionCondition exceptionCondition,
RuntimeConditions runtimeConditions,
ExitReason expectedExitReason = ExitReason.None,
TestAnalyzeOptions analyzeOptions = null)
{
ExceptionRaisingRule.s_exceptionCondition = exceptionCondition;
analyzeOptions = analyzeOptions ?? new TestAnalyzeOptions()
{
TargetFileSpecifiers = new string[0]
};
var command = new TestAnalyzeCommand();
command.DefaultPlugInAssemblies = new Assembly[] { typeof(ExceptionRaisingRule).Assembly };
int result = command.Run(analyzeOptions);
int expectedResult =
(runtimeConditions & RuntimeConditions.Fatal) == RuntimeConditions.NoErrors ?
TestAnalyzeCommand.SUCCESS : TestAnalyzeCommand.FAILURE;
Assert.Equal(runtimeConditions, command.RuntimeErrors);
Assert.Equal(expectedResult, result);
if (expectedExitReason != ExitReason.None)
{
Assert.NotNull(command.ExecutionException);
if (expectedExitReason != ExitReason.UnhandledExceptionInEngine)
{
var eax = command.ExecutionException as ExitApplicationException<ExitReason>;
Assert.NotNull(eax);
}
}
else
{
Assert.Null(command.ExecutionException);
}
ExceptionRaisingRule.s_exceptionCondition = ExceptionCondition.None;
}
[Fact]
public void ExceptionRaisedInstantiatingSkimmers()
{
ExceptionTestHelper(
ExceptionCondition.InvokingConstructor,
RuntimeConditions.ExceptionInstantiatingSkimmers,
ExitReason.UnhandledExceptionInstantiatingSkimmers);
}
[Fact]
public void ExceptionRaisedInvokingInitialize()
{
ExceptionTestHelper(
ExceptionCondition.InvokingInitialize,
RuntimeConditions.ExceptionInSkimmerInitialize
);
}
[Fact]
public void ExceptionRaisedInvokingCanAnalyze()
{
var options = new TestAnalyzeOptions()
{
TargetFileSpecifiers = new string[] { this.GetType().Assembly.Location },
};
ExceptionTestHelper(
ExceptionCondition.InvokingCanAnalyze,
RuntimeConditions.ExceptionRaisedInSkimmerCanAnalyze,
analyzeOptions: options
);
}
[Fact]
public void ExceptionRaisedInvokingAnalyze()
{
var options = new TestAnalyzeOptions()
{
TargetFileSpecifiers = new string[] { this.GetType().Assembly.Location },
};
ExceptionTestHelper(
ExceptionCondition.InvokingAnalyze,
RuntimeConditions.ExceptionInSkimmerAnalyze,
analyzeOptions: options
);
}
[Fact]
public void ExceptionRaisedInEngine()
{
TestAnalyzeCommand.RaiseUnhandledExceptionInDriverCode = true;
var options = new TestAnalyzeOptions()
{
TargetFileSpecifiers = new string[] { this.GetType().Assembly.Location },
};
ExceptionTestHelper(
ExceptionCondition.None,
RuntimeConditions.ExceptionInEngine,
ExitReason.UnhandledExceptionInEngine);
TestAnalyzeCommand.RaiseUnhandledExceptionInDriverCode = false;
}
[Fact]
public void IOExceptionRaisedCreatingSarifLog()
{
string path = Path.GetTempFileName();
try
{
using (var stream = File.OpenWrite(path))
{
// our log file is locked for write
// causing exceptions at analysis time
var options = new TestAnalyzeOptions()
{
TargetFileSpecifiers = new string[] { this.GetType().Assembly.Location },
OutputFilePath = path,
Verbose = true,
};
ExceptionTestHelper(
ExceptionCondition.None,
RuntimeConditions.ExceptionCreatingLogfile,
expectedExitReason: ExitReason.ExceptionCreatingLogFile,
analyzeOptions: options);
}
}
finally
{
File.Delete(path);
}
}
[Fact]
public void UnauthorizedAccessExceptionCreatingSarifLog()
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.Windows);
path = Path.Combine(path, Guid.NewGuid().ToString());
try
{
// attempt to persist to unauthorized location will raise exception
var options = new TestAnalyzeOptions()
{
TargetFileSpecifiers = new string[] { this.GetType().Assembly.Location },
OutputFilePath = path,
Verbose = true,
};
ExceptionTestHelper(
ExceptionCondition.None,
RuntimeConditions.ExceptionCreatingLogfile,
expectedExitReason: ExitReason.ExceptionCreatingLogFile,
analyzeOptions: options);
}
finally
{
File.Delete(path);
}
}
public RunLog AnalyzeFile(string fileName)
{
string path = Path.GetTempFileName();
RunLog runLog = null;
try
{
var options = new TestAnalyzeOptions
{
TargetFileSpecifiers = new string[] { fileName },
Verbose = true,
Statistics = true,
ComputeTargetsHash = true,
PolicyFilePath = "default",
Recurse = true,
OutputFilePath = path,
};
var command = new TestAnalyzeCommand();
command.DefaultPlugInAssemblies = new Assembly[] { this.GetType().Assembly };
int result = command.Run(options);
Assert.Equal(TestAnalyzeCommand.SUCCESS, result);
JsonSerializerSettings settings = new JsonSerializerSettings()
{
ContractResolver = SarifContractResolver.Instance
};
ResultLog log = JsonConvert.DeserializeObject<ResultLog>(File.ReadAllText(path), settings);
Assert.NotNull(log);
Assert.Equal<int>(1, log.RunLogs.Count);
runLog = log.RunLogs[0];
}
finally
{
File.Delete(path);
}
return runLog;
}
[Fact]
public void EndToEndAnalysisWithNoIssues()
{
RunLog runLog = AnalyzeFile(this.GetType().Assembly.Location);
int issueCount = 0;
SarifHelpers.ValidateRunLog(runLog, (issue) => { issueCount++; });
Assert.Equal(1, issueCount);
}
}
}

Просмотреть файл

@ -0,0 +1,16 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public enum ExceptionCondition
{
None,
AccessingId,
AccessingName,
InvokingConstructor,
InvokingAnalyze,
InvokingCanAnalyze,
InvokingInitialize
}
}

Просмотреть файл

@ -0,0 +1,115 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
internal class ExceptionRaisingRule : IRuleDescriptor, ISkimmer<TestAnalysisContext>
{
internal static ExceptionCondition s_exceptionCondition;
private ExceptionCondition _exceptionCondition;
public ExceptionRaisingRule()
{
_exceptionCondition = s_exceptionCondition;
if (_exceptionCondition == ExceptionCondition.InvokingConstructor)
{
throw new InvalidOperationException(nameof(ExceptionCondition.InvokingConstructor));
}
}
public string ExceptionRaisingRuleId = "TEST1001";
public string Id
{
get
{
if (_exceptionCondition == ExceptionCondition.AccessingId)
{
throw new InvalidOperationException(nameof(ExceptionCondition.AccessingId));
}
return ExceptionRaisingRuleId;
}
}
public string Name
{
get
{
if (_exceptionCondition == ExceptionCondition.AccessingName)
{
throw new InvalidOperationException(nameof(ExceptionCondition.AccessingName));
}
return nameof(ExceptionRaisingRule);
}
}
public string FullDescription
{
get { return "Test Rule Description"; }
}
public string ShortDescription
{
get
{
throw new NotImplementedException();
}
}
public Dictionary<string, string> Options
{
get
{
throw new NotImplementedException();
}
}
public Dictionary<string, string> FormatSpecifiers
{
get
{
throw new NotImplementedException();
}
}
public Dictionary<string, string> Properties
{
get
{
throw new NotImplementedException();
}
}
public void Analyze(TestAnalysisContext context)
{
if (_exceptionCondition == ExceptionCondition.InvokingAnalyze)
{
throw new InvalidOperationException(nameof(ExceptionCondition.InvokingAnalyze));
}
}
public AnalysisApplicability CanAnalyze(TestAnalysisContext context, out string reasonIfNotApplicable)
{
reasonIfNotApplicable = null;
if (_exceptionCondition == ExceptionCondition.InvokingCanAnalyze)
{
throw new InvalidOperationException(nameof(ExceptionCondition.InvokingCanAnalyze));
}
return AnalysisApplicability.ApplicableToSpecifiedTarget;
}
public void Initialize(TestAnalysisContext context)
{
if (_exceptionCondition == ExceptionCondition.InvokingInitialize)
{
throw new InvalidOperationException(nameof(ExceptionCondition.InvokingInitialize));
}
}
}
}

Просмотреть файл

@ -0,0 +1,10 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Reflection;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Sarif Driver Utilities Unit Tests")]
[assembly: AssemblyDescription("Unit tests for the SARIF driver utilities framework")]

Просмотреть файл

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props" Condition="Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" />
<PropertyGroup>
<ProjectGuid>{66915F7B-9872-4390-AFED-DB8DE7B761BE}</ProjectGuid>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>Microsoft.CodeAnalysis.Driver</RootNamespace>
</PropertyGroup>
<PropertyGroup>
<AssemblyName>Sarif.Driver.UnitTests</AssemblyName>
</PropertyGroup>
<PropertyGroup>
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory).., build.props))\build.props" />
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Sarif, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Sarif.Sdk.1.4.10-beta\lib\net40\Sarif.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.37.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Collections.Immutable.1.1.37\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Core" />
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.abstractions.2.0.0\lib\net35\xunit.abstractions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.assert, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.assert.2.1.0\lib\dotnet\xunit.assert.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.core, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.core.2.1.0\lib\dotnet\xunit.core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="xunit.execution.desktop, Version=2.1.0.3179, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL">
<HintPath>..\packages\xunit.extensibility.execution.2.1.0\lib\net45\xunit.execution.desktop.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AnalyzeCommandTests.cs" />
<Compile Include="ExceptionCondition.cs" />
<Compile Include="ExceptionRaisingRule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SarifHelpers.cs" />
<Compile Include="TestAnalysisContext.cs" />
<Compile Include="TestAnalyzeCommand.cs" />
<Compile Include="TestAnalyzeOptions.cs" />
<Compile Include="TestMessageLogger.cs" />
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sarif.Driver\Sarif.Driver.csproj">
<Project>{8ceaea61-b1a2-4777-bcbe-c9a129a5f6c5}</Project>
<Name>Sarif.Driver</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="CopyFunctionalTestsData" AfterTargets="Build">
<ItemGroup>
<TestFiles Include="$(SolutionDir)FunctionalTestsData\**\*" />
</ItemGroup>
<Copy SourceFiles="@(TestFiles)" DestinationFolder="$(OutputPath)\FunctionalTestsData\%(RecursiveDir)" />
</Target>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>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}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\xunit.runner.visualstudio.2.1.0\build\net20\xunit.runner.visualstudio.props'))" />
</Target>
</Project>

Просмотреть файл

@ -0,0 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.CodeAnalysis.Sarif.Sdk;
using Xunit;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
internal static class SarifHelpers
{
public static void ValidateRunLog(RunLog runLog, Action<Result> resultAction)
{
ValidateToolInfo(runLog.ToolInfo);
foreach (Result result in runLog.Results) { resultAction(result); }
}
public static void ValidateToolInfo(ToolInfo toolInfo)
{
Assert.Equal("Sarif.Driver", toolInfo.Name);
// TODO version, etc
}
}
}

Просмотреть файл

@ -0,0 +1,27 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class TestAnalysisContext : IAnalysisContext
{
public bool IsValidAnalysisTarget { get; set; }
public IResultLogger Logger { get; set; }
public PropertyBag Policy { get; set; }
public IRuleDescriptor Rule { get; set; }
public Exception TargetLoadException { get; set; }
public Uri TargetUri { get; set; }
public void Dispose()
{
}
}
}

Просмотреть файл

@ -0,0 +1,22 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.Reflection;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class TestAnalyzeCommand : AnalyzeCommandBase<TestAnalysisContext, TestAnalyzeOptions>
{
public override IEnumerable<Assembly> DefaultPlugInAssemblies { get; set; }
public override string Prerelease { get { return ""; } }
protected override TestAnalysisContext CreateContext(TestAnalyzeOptions options, IResultLogger logger, PropertyBag policy, string filePath = null)
{
var context = base.CreateContext(options, logger, policy, filePath);
context.IsValidAnalysisTarget = options.RegardAnalysisTargetAsValid;
return context;
}
}
}

Просмотреть файл

@ -0,0 +1,34 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class TestAnalyzeOptions : IAnalyzeOptions
{
public TestAnalyzeOptions()
{
RegardAnalysisTargetAsValid = true;
}
public bool ComputeTargetsHash { get; set; }
public string OutputFilePath { get; set; }
public IList<string> PlugInFilePaths { get; set; }
public string PolicyFilePath { get; set; }
public bool Recurse { get; set; }
public bool Statistics { get; set; }
public IEnumerable<string> TargetFileSpecifiers { get; set; }
public bool Verbose { get; set; }
public bool RegardAnalysisTargetAsValid { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,65 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
internal class TestMessageLogger : IResultLogger
{
public TestMessageLogger()
{
FailTargets = new HashSet<string>();
PassTargets = new HashSet<string>();
NotApplicableTargets = new HashSet<string>();
}
public HashSet<string> PassTargets { get; set; }
public HashSet<string> FailTargets { get; set; }
public HashSet<string> NotApplicableTargets { get; set; }
public void Log(ResultKind messageKind, IAnalysisContext context, string message)
{
switch (messageKind)
{
case ResultKind.Pass:
{
PassTargets.Add(context.TargetUri.LocalPath);
break;
}
case ResultKind.Error:
{
FailTargets.Add(context.TargetUri.LocalPath);
break;
}
case ResultKind.NotApplicable:
{
NotApplicableTargets.Add(context.TargetUri.LocalPath);
break;
}
case ResultKind.Note:
case ResultKind.InternalError:
case ResultKind.ConfigurationError:
{
throw new NotImplementedException();
}
default:
{
throw new InvalidOperationException();
}
}
}
public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message)
{
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Sarif.Sdk" version="1.4.10-beta" targetFramework="net452" />
<package id="xunit" version="2.1.0" targetFramework="net452" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net452" />
<package id="xunit.assert" version="2.1.0" targetFramework="net452" />
<package id="xunit.core" version="2.1.0" targetFramework="net452" />
<package id="xunit.extensibility.core" version="2.1.0" targetFramework="net452" />
<package id="xunit.extensibility.execution" version="2.1.0" targetFramework="net452" />
<package id="xunit.runner.visualstudio" version="2.1.0" targetFramework="net452" />
</packages>

Просмотреть файл

@ -0,0 +1,50 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class AggregatingLogger : IDisposable, IResultLogger
{
public AggregatingLogger() : this(null)
{
}
public AggregatingLogger(IEnumerable<IResultLogger> loggers)
{
this.Loggers = loggers != null ?
new List<IResultLogger>(loggers) :
new List<IResultLogger>();
}
public IList<IResultLogger> Loggers { get; set; }
public void Dispose()
{
foreach (IResultLogger logger in Loggers)
{
using (logger as IDisposable) { };
}
}
public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message)
{
foreach (IResultLogger logger in Loggers)
{
logger.Log(messageKind, context, message);
}
}
public void Log(ResultKind messageKind, IAnalysisContext context, string message)
{
foreach (IResultLogger logger in Loggers)
{
logger.Log(messageKind, context, message);
}
}
}
}

Просмотреть файл

@ -0,0 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public enum AnalysisApplicability
{
Unknown,
NotApplicableToSpecifiedTarget,
ApplicableToSpecifiedTarget,
NotApplicableToAnyTargetWithoutPolicy
}
}

Просмотреть файл

@ -0,0 +1,507 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.CodeAnalysis.Sarif.Driver;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public abstract class AnalyzeCommandBase<TContext, TOptions> : PlugInDriverCommand<TOptions>
where TContext : IAnalysisContext, new()
where TOptions : IAnalyzeOptions
{
public Exception ExecutionException { get; set; }
public RuntimeConditions RuntimeErrors { get; set; }
public static bool RaiseUnhandledExceptionInDriverCode { get; set; }
public override int Run(TOptions analyzeOptions)
{
// 0. Initialize an common logger that drives all outputs. This
// object drives logging for console, statistics, etc.
using (AggregatingLogger logger = InitializeLogger(analyzeOptions))
{
try
{
Analyze(analyzeOptions, logger);
}
catch (ExitApplicationException<ExitReason> ex)
{
// These exceptions have already been logged
ExecutionException = ex;
return FAILURE;
}
catch (Exception ex)
{
// These exceptions escaped our net and must be logged here
TContext context = new TContext();
context.Rule = ErrorDescriptors.UnhandledEngineException;
context.Logger = logger;
LogUnhandledEngineException(ex, context);
ExecutionException = ex;
return FAILURE;
}
}
return ((RuntimeErrors & RuntimeConditions.Fatal) == RuntimeConditions.NoErrors) ? SUCCESS : FAILURE;
}
private void Analyze(TOptions analyzeOptions, AggregatingLogger logger)
{
// 1. Scrape the analyzer options for settings that alter
// behaviors of binary parsers (such as settings for
// symbols resolution).
InitializeFromOptions(analyzeOptions);
// 2. Produce a comprehensive set of analysis targets
HashSet<string> targets = CreateTargetsSet(analyzeOptions);
// 3. Proactively validate that we can locate and
// access all analysis targets. Helper will return
// a list that potentially filters out files which
// did not exist, could not be accessed, etc.
targets = ValidateTargetsExist(logger, targets);
// 4. Create our policy, which will be shared across
// all context objects that are created during analysis
PropertyBag policy = CreatePolicyFromOptions(analyzeOptions);
// 5. Create short-lived context object to pass to
// skimmers during initialization. The logger and
// policy objects are common to all context instances
// and will be passed on again for analysis.
TContext context = CreateContext(analyzeOptions, logger, policy);
// 6. Initialize report file, if configured.
InitializeOutputFile(analyzeOptions, context, targets);
// 7. Instantiate skimmers.
HashSet<ISkimmer<TContext>> skimmers = CreateSkimmers(logger);
// 8. Initialize skimmers. Initialize occurs a single time only.
skimmers = InitializeSkimmers(skimmers, context);
// 9. Run all analysis
AnalyzeTargets(analyzeOptions, skimmers, context, targets);
// 10. For test purposes, raise an unhandled exception if indicated
if (RaiseUnhandledExceptionInDriverCode)
{
throw new InvalidOperationException(this.GetType().Name);
}
}
internal AggregatingLogger InitializeLogger(IAnalyzeOptions analyzeOptions)
{
var logger = new AggregatingLogger();
logger.Loggers.Add(new ConsoleLogger(analyzeOptions.Verbose));
if (analyzeOptions.Statistics)
{
logger.Loggers.Add(new StatisticsLogger());
}
return logger;
}
protected virtual void InitializeFromOptions(TOptions analyzeOptions)
{
}
private static HashSet<string> CreateTargetsSet(TOptions analyzeOptions)
{
HashSet<string> targets = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (string specifier in analyzeOptions.TargetFileSpecifiers)
{
// Currently, we do not filter on any extensions.
var fileSpecifier = new FileSpecifier(specifier, recurse: analyzeOptions.Recurse, filter: "*");
foreach (string file in fileSpecifier.Files) { targets.Add(file); }
}
return targets;
}
private HashSet<string> ValidateTargetsExist(IResultLogger logger, HashSet<string> targets)
{
return targets;
}
protected virtual TContext CreateContext(TOptions options, IResultLogger logger, PropertyBag policy, string filePath = null)
{
var context = new TContext();
context.Logger = logger;
context.Policy = policy;
if (filePath != null)
{
context.TargetUri = new Uri(filePath);
}
return context;
}
private void InitializeOutputFile(TOptions analyzeOptions, TContext context, HashSet<string> targets)
{
string filePath = analyzeOptions.OutputFilePath;
AggregatingLogger aggregatingLogger = (AggregatingLogger)context.Logger;
if (!string.IsNullOrEmpty(filePath))
{
InvokeCatchingRelevantIOExceptions
(
() => aggregatingLogger.Loggers.Add(
new SarifLogger(
analyzeOptions.OutputFilePath,
analyzeOptions.Verbose,
targets,
analyzeOptions.ComputeTargetsHash,
Prerelease)),
(ex) =>
{
LogExceptionCreatingLogFile(filePath, context, ex);
throw new ExitApplicationException<ExitReason>(SdkResources.UnexpectedApplicationExit, ex)
{
ExitReason = ExitReason.ExceptionCreatingLogFile
};
}
);
}
}
public void InvokeCatchingRelevantIOExceptions(Action action, Action<Exception> exceptionHandler)
{
try
{
action();
}
catch (UnauthorizedAccessException ex)
{
exceptionHandler(ex);
}
catch (IOException ex)
{
exceptionHandler(ex);
}
}
private HashSet<ISkimmer<TContext>> CreateSkimmers(IResultLogger logger)
{
HashSet<ISkimmer<TContext>> result = new HashSet<ISkimmer<TContext>>();
try
{
IEnumerable<ISkimmer<TContext>> skimmers;
skimmers = DriverUtilities.GetExports<ISkimmer<TContext>>(DefaultPlugInAssemblies);
foreach (ISkimmer<TContext> skimmer in skimmers)
{
result.Add(skimmer);
}
return result;
}
catch (Exception ex)
{
RuntimeErrors |= RuntimeConditions.ExceptionInstantiatingSkimmers;
throw new ExitApplicationException<ExitReason>(SdkResources.UnexpectedApplicationExit, ex)
{
ExitReason = ExitReason.UnhandledExceptionInstantiatingSkimmers
};
}
}
protected virtual void AnalyzeTargets(
TOptions options,
IEnumerable<ISkimmer<TContext>> skimmers,
TContext rootContext,
IEnumerable<string> targets)
{
HashSet<string> disabledSkimmers = new HashSet<string>();
foreach (string target in targets)
{
using (TContext context = AnalyzeTarget(options, skimmers, rootContext, target, disabledSkimmers))
{
}
}
}
protected virtual TContext AnalyzeTarget(
TOptions options,
IEnumerable<ISkimmer<TContext>> skimmers,
TContext rootContext,
string target,
HashSet<string> disabledSkimmers)
{
var context = CreateContext(options, rootContext.Logger, rootContext.Policy, target);
if (context.TargetLoadException != null)
{
LogExceptionLoadingTarget(context);
return context;
}
else if (!context.IsValidAnalysisTarget)
{
LogExceptionInvalidTarget(context);
return context;
}
// Analyzing {0}...
context.Rule = NoteDescriptors.AnalyzingTarget;
context.Logger.Log(ResultKind.Note, context,
string.Format(SdkResources.Analyzing, Path.GetFileName(context.TargetUri.LocalPath)));
foreach (ISkimmer<TContext> skimmer in skimmers)
{
if (disabledSkimmers.Contains(skimmer.Id)) { continue; }
string reasonForNotAnalyzing = null;
context.Rule = skimmer;
AnalysisApplicability applicability = AnalysisApplicability.Unknown;
try
{
applicability = skimmer.CanAnalyze(context, out reasonForNotAnalyzing);
}
catch (Exception ex)
{
LogUnhandledRuleExceptionAssessingTargetApplicability(disabledSkimmers, context, skimmer, ex);
continue;
}
switch (applicability)
{
case AnalysisApplicability.NotApplicableToSpecifiedTarget:
{
// Image '{0}' was not evaluated for check '{1}' as the analysis
// is not relevant based on observed binary metadata: {2}.
context.Logger.Log(ResultKind.NotApplicable,
context,
MessageUtilities.BuildTargetNotAnalyzedMessage(
context.TargetUri.LocalPath,
context.Rule.Name,
reasonForNotAnalyzing));
break;
}
case AnalysisApplicability.NotApplicableToAnyTargetWithoutPolicy:
{
// Check '{0}' was disabled for this run as the analysis was not
// configured with required policy ({1}). To resolve this,
// configure and provide a policy file on the BinSkim command-line
// using the --policy argument (recommended), or pass
// '--policy default' to invoke built-in settings. Invoke the
// BinSkim.exe 'export' command to produce an initial policy file
// that can be edited if required and passed back into the tool.
context.Logger.Log(ResultKind.ConfigurationError, context,
MessageUtilities.BuildRuleDisabledDueToMissingPolicyMessage(
context.Rule.Name,
reasonForNotAnalyzing));
disabledSkimmers.Add(skimmer.Id);
break;
}
case AnalysisApplicability.ApplicableToSpecifiedTarget:
{
try
{
skimmer.Analyze(context);
}
catch (Exception ex)
{
LogUnhandledRuleExceptionAnalyzingTarget(disabledSkimmers, context, skimmer, ex);
}
break;
}
}
}
return context;
}
private void LogUnhandledEngineException(Exception ex, IAnalysisContext context)
{
// An unhandled exception was raised during analysis:
// {1}
context.Logger.Log(ResultKind.InternalError,
context,
string.Format(SdkResources.UnhandledEngineException,
ex.ToString()));
RuntimeErrors |= RuntimeConditions.ExceptionInEngine;
}
private void LogExceptionLoadingRoslynAnalyzer(string analyzerFilePath, TContext context, Exception ex)
{
context.Rule = ErrorDescriptors.InvalidConfiguration;
// An exception was raised attempting to load Roslyn analyzer '{0}'. Exception information:
// {1}
context.Logger.Log(ResultKind.ConfigurationError,
context,
string.Format(SdkResources.ExceptionLoadingAnalysisPlugIn,
analyzerFilePath,
context.TargetLoadException.ToString()));
RuntimeErrors |= RuntimeConditions.ExceptionLoadingAnalysisPlugIn;
}
private void LogExceptionInvalidTarget(TContext context)
{
context.Rule = NoteDescriptors.InvalidTarget;
// Image '{0}' was not analyzed as the it does not
// appear to be a valid portable executable.
context.Logger.Log(ResultKind.NotApplicable,
context,
string.Format(
SdkResources.TargetNotAnalyzed_InvalidTarget,
context.TargetUri.LocalPath));
context.Dispose();
RuntimeErrors |= RuntimeConditions.OneOrMoreTargetsNotValidToAnalyze;
}
private void LogExceptionLoadingTarget(TContext context)
{
context.Rule = ErrorDescriptors.InvalidConfiguration;
// An exception was raised attempting to load analysis target '{0}'. Exception information:
// {1}
context.Logger.Log(ResultKind.ConfigurationError,
context,
string.Format(SdkResources.ExceptionLoadingAnalysisTarget,
context.TargetUri.LocalPath,
context.TargetLoadException.ToString()));
context.Dispose();
RuntimeErrors |= RuntimeConditions.ExceptionLoadingTargetFile;
}
private void LogExceptionCreatingLogFile(string fileName, TContext context, Exception ex)
{
// An exception was raised attempting to create output file '{0}'. Exception information:
// {1}
context.Rule = ErrorDescriptors.InvalidConfiguration;
context.Logger.Log(ResultKind.ConfigurationError,
context,
string.Format(SdkResources.ExceptionCreatingLogFile,
fileName,
ex.ToString()));
RuntimeErrors |= RuntimeConditions.ExceptionCreatingLogfile;
}
private void LogUnhandledExceptionInitializingRule(TContext context, ISkimmer<TContext> skimmer, Exception ex)
{
string ruleName = context.Rule.Name;
// An unhandled exception was encountered initializing check '{0}', which
// has been disabled for the remainder of the analysis. Exception information:
// {1}
context.Rule = ErrorDescriptors.UnhandledRuleException;
context.Logger.Log(ResultKind.InternalError,
context,
string.Format(SdkResources.ExceptionInitializingRule,
ruleName,
ex.ToString()));
RuntimeErrors |= RuntimeConditions.ExceptionInSkimmerInitialize;
}
private void LogUnhandledRuleExceptionAssessingTargetApplicability(HashSet<string> disabledSkimmers, TContext context, ISkimmer<TContext> skimmer, Exception ex)
{
string ruleName = context.Rule.Name;
// An unhandled exception was raised attempting to determine whether '{0}'
// is a valid analysis target for check '{1}' (which has been disabled
// for the remainder of the analysis). The exception may have resulted
// from a problem related to parsing image metadata and not specific to
// the rule, however. Exception information:
// {2}
context.Rule = ErrorDescriptors.UnhandledRuleException;
context.Logger.Log(ResultKind.InternalError,
context,
string.Format(SdkResources.ExceptionCheckingApplicability,
context.TargetUri.LocalPath,
ruleName,
ex.ToString()));
if (disabledSkimmers != null) { disabledSkimmers.Add(skimmer.Id); }
RuntimeErrors |= RuntimeConditions.ExceptionRaisedInSkimmerCanAnalyze;
}
private void LogUnhandledRuleExceptionAnalyzingTarget(HashSet<string> disabledSkimmers, TContext context, ISkimmer<TContext> skimmer, Exception ex)
{
string ruleName = context.Rule.Name;
// An unhandled exception was encountered analyzing '{0}' for check '{1}',
// which has been disabled for the remainder of the analysis.The
// exception may have resulted from a problem related to parsing
// image metadata and not specific to the rule, however.
// Exception information:
// {2}
context.Rule = ErrorDescriptors.UnhandledRuleException;
context.Logger.Log(ResultKind.InternalError,
context,
string.Format(SdkResources.ExceptionAnalyzingTarget,
context.TargetUri.LocalPath,
ruleName,
ex.ToString()));
if (disabledSkimmers != null) { disabledSkimmers.Add(skimmer.Id); }
RuntimeErrors |= RuntimeConditions.ExceptionInSkimmerAnalyze;
}
protected virtual HashSet<ISkimmer<TContext>> InitializeSkimmers(HashSet<ISkimmer<TContext>> skimmers, TContext context)
{
HashSet<ISkimmer<TContext>> disabledSkimmers = new HashSet<ISkimmer<TContext>>();
// ONE-TIME initialization of skimmers. Do not call
// Initialize more than once per skimmer instantiation
foreach (ISkimmer<TContext> skimmer in skimmers)
{
try
{
context.Rule = skimmer;
skimmer.Initialize(context);
}
catch (Exception ex)
{
RuntimeErrors |= RuntimeConditions.ExceptionInSkimmerInitialize;
LogUnhandledExceptionInitializingRule(context, skimmer, ex);
disabledSkimmers.Add(skimmer);
}
}
foreach (ISkimmer<TContext> disabledSkimmer in disabledSkimmers)
{
skimmers.Remove(disabledSkimmer);
}
return skimmers;
}
private static PropertyBag CreatePolicyFromOptions(TOptions analyzeOptions)
{
PropertyBag policy = null;
string policyFilePath = analyzeOptions.PolicyFilePath;
if (!string.IsNullOrEmpty(policyFilePath))
{
policy = new PropertyBag();
if (!policyFilePath.Equals("default", StringComparison.OrdinalIgnoreCase))
{
policy.LoadFrom(policyFilePath);
}
}
return policy;
}
}
}

Просмотреть файл

@ -0,0 +1,164 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class ConsoleLogger : IResultLogger
{
public ConsoleLogger(bool verbose)
{
Verbose = verbose;
}
public bool Verbose { get; set; }
public void Log(ResultKind messageKind, IAnalysisContext context, string message)
{
switch (messageKind)
{
// These result types are optionally emitted
case ResultKind.Pass:
case ResultKind.Note:
case ResultKind.NotApplicable:
{
if (Verbose)
{
Console.WriteLine(GetMessageText(context, message, messageKind));
}
break;
}
// These result types are alwayss emitted
case ResultKind.Error:
case ResultKind.Warning:
case ResultKind.InternalError:
case ResultKind.ConfigurationError:
{
Console.WriteLine(GetMessageText(context, message, messageKind));
break;
}
default:
{
throw new InvalidOperationException();
}
}
}
public static string GetMessageText(
IAnalysisContext context,
string message,
ResultKind messageKind,
Region region = null)
{
string path = null;
Uri uri = context.TargetUri;
if (uri != null)
{
// If a path refers to a URI of form file://blah, we will convert to the local path
if (uri.IsAbsoluteUri && uri.Scheme == Uri.UriSchemeFile)
{
path = uri.LocalPath;
}
else
{
path = uri.ToString();
}
}
string issueType = null;
switch (messageKind)
{
case ResultKind.ConfigurationError:
{
issueType = "CONFIGURATION ERROR";
break;
}
case ResultKind.InternalError:
{
issueType = "INTERNAL ERROR";
break;
}
case ResultKind.Error:
{
issueType = "error";
break;
}
case ResultKind.Warning:
{
issueType = "warning";
break;
}
case ResultKind.NotApplicable:
case ResultKind.Note:
{
issueType = "note";
break;
}
default:
{
throw new InvalidOperationException("Unknown message kind:" + messageKind.ToString());
}
}
string detailedDiagnosis = NormalizeMessage(message, enquote: false);
string location = "";
if (region != null)
{
// TODO
if (region.Offset > 0 || region.StartColumn == 0) { throw new NotImplementedException(); }
if (region.StartLine == 0) { throw new InvalidOperationException(); }
// VS supports the following formatting options:
// (startLine)
// (startLine-endLine)
// (startLine,startColumn)
// (startLine,startColumn-endColumn)
// (startLine,startColumn,endLine,endColumn
//
// For expedience, we'll convert everything to the most fully qualified format
string start = region.StartLine.ToString() + "," +
(region.StartColumn > 0 ? region.StartColumn.ToString() : "1");
string end = (region.EndLine > region.StartLine ? region.EndLine.ToString() : region.StartLine.ToString()) + "," +
(region.EndColumn > 0 ? region.EndColumn.ToString() : region.StartColumn.ToString());
location =
"(" +
start + (end != start ? "," + end : "") +
")";
}
return (path != null ? (path + location + ": ") : "") +
issueType + " " +
context.Rule.Id + ": " +
detailedDiagnosis;
}
public static string NormalizeMessage(string message, bool enquote)
{
return (enquote ? "\"" : "") +
message.Replace('"', '\'') +
(enquote ? "\"" : "");
}
public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message)
{
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -0,0 +1,70 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public static class ErrorDescriptors
{
public static IRuleDescriptor InvalidConfiguration = new RuleDescriptor()
{
Id = "ERR0997",
Name = nameof(InvalidConfiguration),
FullDescription = SdkResources.InvalidConfiguration_Description,
FormatSpecifiers = BuildDictionary(new string[] {
nameof(SdkResources.ExceptionCreatingLogFile),
nameof(SdkResources.ExceptionLoadingAnalysisPlugIn),
nameof(SdkResources.ExceptionLoadingAnalysisTarget)
})
};
public static IRuleDescriptor UnhandledRuleException = new RuleDescriptor()
{
Id = "ERR0998",
Name = nameof(UnhandledRuleException),
FullDescription = SdkResources.ExceptionInRule_Description,
FormatSpecifiers = BuildDictionary(new string[] {
nameof(SdkResources.ExceptionInitializingRule),
nameof(SdkResources.ExceptionAnalyzingTarget)
})
};
public static IRuleDescriptor UnhandledEngineException = new RuleDescriptor()
{
Id = "ERR0999",
Name = nameof(UnhandledEngineException),
FullDescription = SdkResources.ExceptionInAnalysisEngine_Description,
FormatSpecifiers = BuildDictionary(new string[] {
nameof(SdkResources.ExceptionInAnalysisEngine)
})
};
public static IRuleDescriptor ParseError = new RuleDescriptor()
{
Id = "ERR1001",
Name = nameof(ParseError),
FullDescription = SdkResources.ParseError_Description,
FormatSpecifiers = BuildDictionary(new string[] {
nameof(SdkResources.ParseError)
})
};
private static Dictionary<string, string> BuildDictionary(IEnumerable<string> resourceNames)
{
// Note this dictionary provides for case-insensitive keys
var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (string resourceName in resourceNames)
{
string resourceValue = SdkResources.ResourceManager.GetString(resourceName);
dictionary[resourceName] = resourceValue;
}
return dictionary;
}
}
}

Просмотреть файл

@ -0,0 +1,13 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public enum ExitReason
{
None,
ExceptionCreatingLogFile,
UnhandledExceptionInstantiatingSkimmers,
UnhandledExceptionInEngine,
}
}

Просмотреть файл

@ -0,0 +1,33 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.IO;
using System.Security.Cryptography;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public static class HashUtilities
{
public static string ComputeSha256Hash(string fileName)
{
string sha256Hash = null;
try
{
using (FileStream stream = File.OpenRead(fileName))
{
using (var bufferedStream = new BufferedStream(stream, 1024 * 32))
{
var sha = new SHA256Cng();
byte[] checksum = sha.ComputeHash(bufferedStream);
sha256Hash = BitConverter.ToString(checksum).Replace("-", String.Empty);
}
}
}
catch (IOException) { }
catch (UnauthorizedAccessException) { }
return sha256Hash;
}
}
}

Просмотреть файл

@ -0,0 +1,24 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.using System;
using System;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public interface IAnalysisContext : IDisposable
{
Uri TargetUri { get; set; }
Exception TargetLoadException { get; set; }
bool IsValidAnalysisTarget { get; }
IRuleDescriptor Rule { get; set; }
PropertyBag Policy { get; set; }
IResultLogger Logger { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public interface IAnalyzeOptions
{
IEnumerable<string> TargetFileSpecifiers { get; }
string OutputFilePath { get; }
bool Verbose { get; }
bool Recurse { get; }
string PolicyFilePath { get; }
bool Statistics { get; }
bool ComputeTargetsHash { get; }
IList<string> PlugInFilePaths { get; }
}
}

Просмотреть файл

@ -0,0 +1,14 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public interface IResultLogger
{
void Log(ResultKind messageKind, IAnalysisContext context, string message);
void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message);
}
}

Просмотреть файл

@ -0,0 +1,39 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public interface ISkimmer<TContext> : IRuleDescriptor
{
/// <summary>
/// Initialize method for skimmer instance. This method will only
/// only be called a single time per skimmer instantiation.
/// </summary>
/// <param name="context"></param>
void Initialize(TContext context);
/// <summary>
/// Determine whether a target is a valid target for analysis.
/// May be called from multiple threads.
///
/// </summary>
/// <param name="context"></param>
/// <returns>An analysis applicability value that indicates whether a check is
/// applicable to a specified target, is not applicable to a specified target,
/// or is not applicable to any target due to the absence of a configured
/// policy. In cases where the analysis is determined not to be applicable,
/// the 'reasonIfNotApplicable' property should be set to a string that
/// describes the observed state or condition that prevents analysis.
/// </returns>
AnalysisApplicability CanAnalyze(TContext context, out string reasonIfNotApplicable);
/// <summary>
/// Analyze specified binary target and use context-resident loggers
/// to record the results of the analysis. May be called from multiple threads.
/// </summary>
/// <param name="context"></param>
void Analyze(TContext context);
}
}

Просмотреть файл

@ -0,0 +1,61 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public static class MessageUtilities
{
public static string BuildMessage(IAnalysisContext context, string messageFormatString, params string[] arguments)
{
// By convention, the first argument is always the target name,
// which we retrieve from the context
Debug.Assert(File.Exists(context.TargetUri.LocalPath));
string targetName = Path.GetFileName(context.TargetUri.LocalPath);
string[] fullArguments = new string[arguments != null ? arguments.Length + 1 : 1];
fullArguments[0] = targetName;
if (fullArguments.Length > 1)
{
arguments.CopyTo(fullArguments, 1);
}
return String.Format(CultureInfo.InvariantCulture,
messageFormatString, fullArguments);
}
public static string BuildTargetNotAnalyzedMessage(string targetPath, string ruleName, string reason)
{
targetPath = Path.GetFileName(targetPath);
// Image '{0}' was not evaluated for check '{1}' as the analysis
// is not relevant based on observed metadata: {2}
return String.Format(
CultureInfo.InvariantCulture,
SdkResources.TargetNotAnalyzed_NotApplicable,
targetPath,
ruleName,
reason);
}
public static string BuildRuleDisabledDueToMissingPolicyMessage(string ruleName, string reason)
{
// BinSkim command-line using the --policy argument (recommended), or
// pass --defaultPolicy to invoke built-in settings. Invoke the
// BinSkim.exe 'export' command to produce an initial policy file
// that can be edited if required and passed back into the tool.
return String.Format(
CultureInfo.InvariantCulture,
SdkResources.RuleWasDisabledDueToMissingPolicy,
ruleName,
reason);
}
}
}

Просмотреть файл

@ -0,0 +1,48 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public static class NoteDescriptors
{
public static IRuleDescriptor AnalyzingTarget = new RuleDescriptor()
{
// A file is being analyzed.
Id = "MSG1001",
Name = nameof(AnalyzingTarget),
FullDescription = SdkResources.InvalidTarget_Description,
FormatSpecifiers = BuildDictionary(new string[] {
nameof(SdkResources.Analyzing),
})
};
public static IRuleDescriptor InvalidTarget = new RuleDescriptor()
{
// A file was skipped as it does not appear to be a valid target for analysis.
Id = "MSG1002",
Name = nameof(InvalidTarget),
FullDescription = SdkResources.InvalidTarget_Description,
FormatSpecifiers = BuildDictionary(new string[] {
nameof(SdkResources.TargetNotAnalyzed_InvalidTarget),
})
};
private static Dictionary<string, string> BuildDictionary(IEnumerable<string> resourceNames)
{
// Note this dictionary provides for case-insensitive keys
var dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (string resourceName in resourceNames)
{
string resourceValue = SdkResources.ResourceManager.GetString(resourceName);
dictionary[resourceName] = resourceValue;
}
return dictionary;
}
}
}

Просмотреть файл

@ -0,0 +1,157 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.CodeAnalysis.Sarif.Writers;
using Newtonsoft.Json;
using Microsoft.CodeAnalysis.Sarif;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class ResultLogger
{
private FileStream _fileStream;
private TextWriter _textWriter;
private JsonTextWriter _jsonTextWriter;
private ResultLogJsonWriter _issueLogJsonWriter;
public ResultLogger(
Assembly assembly,
string outputFilePath,
bool verbose,
IEnumerable<string> analysisTargets,
bool computeTargetsHash,
string prereleaseInfo)
{
Verbose = verbose;
_fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
_textWriter = new StreamWriter(_fileStream);
_jsonTextWriter = new JsonTextWriter(_textWriter);
// for debugging it is nice to have the following line added.
_jsonTextWriter.Formatting = Newtonsoft.Json.Formatting.Indented;
_issueLogJsonWriter = new ResultLogJsonWriter(_jsonTextWriter);
var toolInfo = new ToolInfo();
toolInfo.InitializeFromAssembly(assembly, prereleaseInfo);
RunInfo runInfo = new RunInfo();
runInfo.AnalysisTargets = new List<FileReference>();
foreach (string target in analysisTargets)
{
var fileReference = new FileReference()
{
Uri = target.CreateUriForJsonSerialization(),
};
if (computeTargetsHash)
{
string sha256Hash = HashUtilities.ComputeSha256Hash(target) ?? "[could not compute file hash]";
fileReference.Hashes = new List<Hash>(new Hash[]
{
new Hash()
{
Value = sha256Hash,
Algorithm = AlgorithmKind.Sha256,
}
});
}
runInfo.AnalysisTargets.Add(fileReference);
}
runInfo.InvocationInfo = Environment.CommandLine;
_issueLogJsonWriter.WriteToolAndRunInfo(toolInfo, runInfo);
}
public bool Verbose { get; set; }
public Uri Uri
{
get
{
throw new NotImplementedException();
}
}
public IRuleDescriptor Rule
{
get
{
throw new NotImplementedException();
}
}
public void Dispose()
{
// Disposing the json writer closes the stream but the textwriter
// still needs to be disposed or closed to write the results
if (_issueLogJsonWriter != null) { _issueLogJsonWriter.Dispose(); }
if (_textWriter != null) { _textWriter.Dispose(); }
}
public void Log(ResultKind resultKind, IAnalysisContext context, string message)
{
Result result = new Result();
result.RuleId = context.Rule.Id;
result.FullMessage = message;
result.Kind = resultKind;
result.Locations = new[]{
new Sarif.Sdk.Location {
AnalysisTarget = new[]
{
new PhysicalLocationComponent
{
// Why? When NewtonSoft serializes this Uri, it will use the
// original string used to construct the Uri. For a file path,
// this will be the local file path. We want to persist this
// information using the file:// protocol rendering, however.
Uri = context.TargetUri.LocalPath.CreateUriForJsonSerialization(),
MimeType = MimeType.Binary
}
}
}
};
_issueLogJsonWriter.WriteResult(result);
}
private void WriteJsonIssue(string binary, string ruleId, string message, ResultKind issueKind)
{
Result result = new Result();
result.RuleId = ruleId;
result.FullMessage = message;
result.Kind = issueKind;
result.Locations = new[]{
new Sarif.Sdk.Location {
AnalysisTarget = new[]
{
new PhysicalLocationComponent
{
// Why? When NewtonSoft serializes this Uri, it will use the
// original string used to construct the Uri. For a file path,
// this will be the local file path. We want to persist this
// information using the file:// protocol rendering, however.
Uri = binary.CreateUriForJsonSerialization(),
MimeType = MimeType.Binary
}
}
}
};
_issueLogJsonWriter.WriteResult(result);
}
public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message)
{
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -0,0 +1,44 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
// This enum is used to identify specific runtime conditions
// encountered during execution. This mechanism is used by
// unit tests to ensure that failure conditions travel expected
// code paths. These conditions are a combination of fatal
// and non-fatal circumstances
[Flags]
public enum RuntimeConditions
{
NoErrors = 0,
// Not used today but perhaps soon...
//CouldNotLoadCustomLoggerAssembly,
//CouldNotLoadCustomLoggerType,
//UnrecognizedDefaultLoggerExtension,
//MalformedCustomLoggersArgument,
//LoggerFailedInitialization,
//LoggerRaisedExceptionOnInitialization,
//LoggerRaisedExceptionOnWrite,
//LoggerRaisedExceptionOnClose,
// Fatal conditions
ExceptionInstantiatingSkimmers = 0x01,
ExceptionInSkimmerInitialize = 0x02,
ExceptionRaisedInSkimmerCanAnalyze = 0x04,
ExceptionInSkimmerAnalyze = 0x08,
ExceptionCreatingLogfile = 0x10,
ExceptionInEngine = 0x20,
ExceptionLoadingTargetFile = 0x40,
ExceptionLoadingAnalysisPlugIn = 0x80,
Fatal = (Int32.MaxValue ^ NonFatal),
// Non-fatal conditions
OneOrMoreTargetsNotValidToAnalyze = 0x80,
NonFatal = OneOrMoreTargetsNotValidToAnalyze,
}
}

Просмотреть файл

@ -0,0 +1,188 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.CodeAnalysis.Sarif;
using Microsoft.CodeAnalysis.Sarif.Sdk;
using Microsoft.CodeAnalysis.Sarif.Writers;
using Newtonsoft.Json;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class SarifLogger : IDisposable, IResultLogger
{
private FileStream _fileStream;
private TextWriter _textWriter;
private JsonTextWriter _jsonTextWriter;
private ResultLogJsonWriter _issueLogJsonWriter;
public static ToolInfo CreateDefaultToolInfo(string prereleaseInfo = null)
{
Assembly assembly = typeof(SarifLogger).Assembly;
string name = Path.GetFileNameWithoutExtension(assembly.Location);
Version version = assembly.GetName().Version;
ToolInfo toolInfo = new ToolInfo();
toolInfo.Name = name;
toolInfo.Version = version.Major.ToString() + "." + version.Minor.ToString() + "." + version.Build.ToString();
toolInfo.FullName = name + " " + toolInfo.Version + (prereleaseInfo ?? "");
return toolInfo;
}
public SarifLogger(
string outputFilePath,
bool verbose,
IEnumerable<string> analysisTargets,
bool computeTargetsHash,
string prereleaseInfo)
{
Verbose = verbose;
_fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
_textWriter = new StreamWriter(_fileStream);
_jsonTextWriter = new JsonTextWriter(_textWriter);
// for debugging it is nice to have the following line added.
_jsonTextWriter.Formatting = Newtonsoft.Json.Formatting.Indented;
_issueLogJsonWriter = new ResultLogJsonWriter(_jsonTextWriter);
var toolInfo = CreateDefaultToolInfo(prereleaseInfo);
RunInfo runInfo = new RunInfo();
runInfo.AnalysisTargets = new List<FileReference>();
foreach (string target in analysisTargets)
{
var fileReference = new FileReference()
{
Uri = target.CreateUriForJsonSerialization(),
};
if (computeTargetsHash)
{
string sha256Hash = HashUtilities.ComputeSha256Hash(target) ?? "[could not compute file hash]";
fileReference.Hashes = new List<Hash>(new Hash[]
{
new Hash()
{
Value = sha256Hash,
Algorithm = AlgorithmKind.Sha256,
}
});
}
runInfo.AnalysisTargets.Add(fileReference);
}
runInfo.InvocationInfo = Environment.CommandLine;
_issueLogJsonWriter.WriteToolAndRunInfo(toolInfo, runInfo);
}
public bool Verbose { get; set; }
public void Dispose()
{
// Disposing the json writer closes the stream but the textwriter
// still needs to be disposed or closed to write the results
if (_issueLogJsonWriter != null) { _issueLogJsonWriter.Dispose(); }
if (_textWriter != null) { _textWriter.Dispose(); }
}
public void Log(ResultKind messageKind, IAnalysisContext context, string message)
{
switch (messageKind)
{
case ResultKind.Pass:
{
if (Verbose)
{
WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.Pass);
}
break;
}
case ResultKind.Error:
case ResultKind.Warning:
{
WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.Error);
break;
}
case ResultKind.NotApplicable:
{
if (Verbose)
{
WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.NotApplicable);
}
break;
}
case ResultKind.Note:
{
if (Verbose)
{
WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.Note);
}
break;
}
case ResultKind.ConfigurationError:
{
WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.ConfigurationError);
break;
}
case ResultKind.InternalError:
{
WriteJsonIssue(context.TargetUri.LocalPath, context.Rule.Id, message, ResultKind.InternalError);
break;
}
default:
{
throw new InvalidOperationException();
}
}
}
private void WriteJsonIssue(string binary, string ruleId, string message, ResultKind issueKind)
{
Result result = new Result();
result.RuleId = ruleId;
result.FullMessage = message;
result.Kind = issueKind;
result.Locations = new[]{
new Sarif.Sdk.Location {
AnalysisTarget = new[]
{
new PhysicalLocationComponent
{
// Why? When NewtonSoft serializes this Uri, it will use the
// original string used to construct the Uri. For a file path,
// this will be the local file path. We want to persist this
// information using the file:// protocol rendering, however.
Uri = binary.CreateUriForJsonSerialization(),
MimeType = MimeType.Binary
}
}
}
};
_issueLogJsonWriter.WriteResult(result);
}
public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message)
{
throw new NotImplementedException();
}
}
}

260
src/Sarif.Driver/Sdk/SdkResources.Designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,260 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class SdkResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal SdkResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.CodeAnalysis.Sarif.Driver.Sdk.SdkResources", typeof(SdkResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Analyzing {0}....
/// </summary>
internal static string Analyzing {
get {
return ResourceManager.GetString("Analyzing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to InvalidTarget_Description.
/// </summary>
internal static string AnalyzingTarget_Description {
get {
return ResourceManager.GetString("AnalyzingTarget_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised analyzing &apos;{0}&apos; for check &apos;{1}&apos; (which has been disabled for the remainder of the analysis). The exception may have resulted from a problem related to parsing image metadata and not specific to the rule, however. Exception information:
///{2}.
/// </summary>
internal static string ExceptionAnalyzingTarget {
get {
return ResourceManager.GetString("ExceptionAnalyzingTarget", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised attempting to determine whether &apos;{0}&apos; is a valid analysis target for check &apos;{1}&apos; (which has been disabled for the remainder of the analysis). The exception may have resulted from a problem related to parsing the analysis target and not specific to the rule, however. Exception information:
///{2}.
/// </summary>
internal static string ExceptionCheckingApplicability {
get {
return ResourceManager.GetString("ExceptionCheckingApplicability", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised attempting to create output file &apos;{0}&apos;. Exception information:
///{1}.
/// </summary>
internal static string ExceptionCreatingLogFile {
get {
return ResourceManager.GetString("ExceptionCreatingLogFile", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised during analysis:
///{0}.
/// </summary>
internal static string ExceptionInAnalysisEngine {
get {
return ResourceManager.GetString("ExceptionInAnalysisEngine", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised in the analysis engine..
/// </summary>
internal static string ExceptionInAnalysisEngine_Description {
get {
return ResourceManager.GetString("ExceptionInAnalysisEngine_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised initializing check &apos;{0}&apos; (which has been disabled for the remainder of the analysis). Exception information:
///{1}.
/// </summary>
internal static string ExceptionInitializingRule {
get {
return ResourceManager.GetString("ExceptionInitializingRule", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised in an analysis rule, indicating an issue with the rule itself or a problem inspecting the binary being analyzed..
/// </summary>
internal static string ExceptionInRule_Description {
get {
return ResourceManager.GetString("ExceptionInRule_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised attempting to load analysis plug-in &apos;{0}&apos;. Exception information:
///{1}.
/// </summary>
internal static string ExceptionLoadingAnalysisPlugIn {
get {
return ResourceManager.GetString("ExceptionLoadingAnalysisPlugIn", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised attempting to load analysis target &apos;{0}&apos;. Exception information:
///{1}.
/// </summary>
internal static string ExceptionLoadingAnalysisTarget {
get {
return ResourceManager.GetString("ExceptionLoadingAnalysisTarget", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An unhandled exception was raised while configuring analysis for execution..
/// </summary>
internal static string InvalidConfiguration_Description {
get {
return ResourceManager.GetString("InvalidConfiguration_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A file was skipped as it does not appear to be a valid target for analysis..
/// </summary>
internal static string InvalidTarget_Description {
get {
return ResourceManager.GetString("InvalidTarget_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No analyzer paths specified.
/// </summary>
internal static string NoAnalyzerPathsSpecified {
get {
return ResourceManager.GetString("NoAnalyzerPathsSpecified", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A parse error occurred: {0}.
/// </summary>
internal static string ParseError {
get {
return ResourceManager.GetString("ParseError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A parse error occurred..
/// </summary>
internal static string ParseError_Description {
get {
return ResourceManager.GetString("ParseError_Description", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Check &apos;{0}&apos; was disabled for this run as the analysis was not configured with required policy ({1}). To resolve this, configure and provide a policy file on the BinSkim command-line using the --policy argument (recommended), or pass --defaultPolicy to invoke built-in settings. Invoke the BinSkim.exe &apos;export&apos; command to produce an initial policy file that can be edited if required and passed back into the tool..
/// </summary>
internal static string RuleWasDisabledDueToMissingPolicy {
get {
return ResourceManager.GetString("RuleWasDisabledDueToMissingPolicy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &apos;{0}&apos; was not analyzed as it does not appear to be a valid target for analysis..
/// </summary>
internal static string TargetNotAnalyzed_InvalidTarget {
get {
return ResourceManager.GetString("TargetNotAnalyzed_InvalidTarget", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &apos;{0}&apos; was not evaluated for check &apos;{1}&apos; as the analysis is not relevant based on observed binary metadata: {2}..
/// </summary>
internal static string TargetNotAnalyzed_NotApplicable {
get {
return ResourceManager.GetString("TargetNotAnalyzed_NotApplicable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Application exited unexpectedly..
/// </summary>
internal static string UnexpectedApplicationExit {
get {
return ResourceManager.GetString("UnexpectedApplicationExit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An exception was raised during analysis:
///{0}.
/// </summary>
internal static string UnhandledEngineException {
get {
return ResourceManager.GetString("UnhandledEngineException", resourceCulture);
}
}
}
}

Просмотреть файл

@ -0,0 +1,191 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Analyzing" xml:space="preserve">
<value>Analyzing {0}...</value>
</data>
<data name="AnalyzingTarget_Description" xml:space="preserve">
<value>InvalidTarget_Description</value>
</data>
<data name="ExceptionAnalyzingTarget" xml:space="preserve">
<value>An exception was raised analyzing '{0}' for check '{1}' (which has been disabled for the remainder of the analysis). The exception may have resulted from a problem related to parsing image metadata and not specific to the rule, however. Exception information:
{2}</value>
</data>
<data name="ExceptionCheckingApplicability" xml:space="preserve">
<value>An exception was raised attempting to determine whether '{0}' is a valid analysis target for check '{1}' (which has been disabled for the remainder of the analysis). The exception may have resulted from a problem related to parsing the analysis target and not specific to the rule, however. Exception information:
{2}</value>
</data>
<data name="ExceptionCreatingLogFile" xml:space="preserve">
<value>An exception was raised attempting to create output file '{0}'. Exception information:
{1}</value>
</data>
<data name="ExceptionInAnalysisEngine" xml:space="preserve">
<value>An exception was raised during analysis:
{0}</value>
</data>
<data name="ExceptionInAnalysisEngine_Description" xml:space="preserve">
<value>An exception was raised in the analysis engine.</value>
</data>
<data name="ExceptionInitializingRule" xml:space="preserve">
<value>An exception was raised initializing check '{0}' (which has been disabled for the remainder of the analysis). Exception information:
{1}</value>
</data>
<data name="ExceptionInRule_Description" xml:space="preserve">
<value>An exception was raised in an analysis rule, indicating an issue with the rule itself or a problem inspecting the binary being analyzed.</value>
</data>
<data name="ExceptionLoadingAnalysisPlugIn" xml:space="preserve">
<value>An exception was raised attempting to load analysis plug-in '{0}'. Exception information:
{1}</value>
</data>
<data name="ExceptionLoadingAnalysisTarget" xml:space="preserve">
<value>An exception was raised attempting to load analysis target '{0}'. Exception information:
{1}</value>
</data>
<data name="InvalidConfiguration_Description" xml:space="preserve">
<value>An unhandled exception was raised while configuring analysis for execution.</value>
</data>
<data name="InvalidTarget_Description" xml:space="preserve">
<value>A file was skipped as it does not appear to be a valid target for analysis.</value>
</data>
<data name="NoAnalyzerPathsSpecified" xml:space="preserve">
<value>No analyzer paths specified</value>
</data>
<data name="RuleWasDisabledDueToMissingPolicy" xml:space="preserve">
<value>Check '{0}' was disabled for this run as the analysis was not configured with required policy ({1}). To resolve this, configure and provide a policy file on the BinSkim command-line using the --policy argument (recommended), or pass --defaultPolicy to invoke built-in settings. Invoke the BinSkim.exe 'export' command to produce an initial policy file that can be edited if required and passed back into the tool.</value>
</data>
<data name="TargetNotAnalyzed_InvalidTarget" xml:space="preserve">
<value>'{0}' was not analyzed as it does not appear to be a valid target for analysis.</value>
</data>
<data name="TargetNotAnalyzed_NotApplicable" xml:space="preserve">
<value>'{0}' was not evaluated for check '{1}' as the analysis is not relevant based on observed binary metadata: {2}.</value>
</data>
<data name="UnexpectedApplicationExit" xml:space="preserve">
<value>Application exited unexpectedly.</value>
</data>
<data name="UnhandledEngineException" xml:space="preserve">
<value>An exception was raised during analysis:
{0}</value>
</data>
<data name="ParseError" xml:space="preserve">
<value>A parse error occurred: {0}</value>
</data>
<data name="ParseError_Description" xml:space="preserve">
<value>A parse error occurred.</value>
</data>
</root>

Просмотреть файл

@ -0,0 +1,72 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public abstract class SkimmerBase<TContext> : ISkimmer<TContext>
{
public SkimmerBase()
{
this.Options = new Dictionary<string, string>();
this.FormatSpecifiers = new Dictionary<string, string>();
}
public Dictionary<string, string> FormatSpecifiers { get; }
abstract public string Id { get; }
abstract public string FullDescription { get; }
public virtual string ShortDescription
{
get { return FirstSentence(FullDescription); }
}
internal static string FirstSentence(string fullDescription)
{
int charCount = 0;
bool withinApostrophe = false;
foreach (char ch in fullDescription)
{
charCount++;
switch (ch)
{
case '\'':
{
withinApostrophe = !withinApostrophe;
continue;
}
case '.':
{
if (withinApostrophe) { continue; }
return fullDescription.Substring(0, charCount);
}
}
}
int length = Math.Min(fullDescription.Length, 80);
bool truncated = length < fullDescription.Length;
return fullDescription.Substring(0, length) + (truncated ? "..." : "");
}
public virtual string Name { get { return this.GetType().Name; } }
public Dictionary<string, string> Options { get; }
public Dictionary<string, string> Properties { get; }
public virtual void Initialize(TContext context) { }
public virtual AnalysisApplicability CanAnalyze(TContext context, out string reasonIfNotApplicable)
{
reasonIfNotApplicable = null;
return AnalysisApplicability.ApplicableToSpecifiedTarget;
}
public abstract void Analyze(TContext context);
}
}

Просмотреть файл

@ -0,0 +1,90 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Sarif.Sdk;
namespace Microsoft.CodeAnalysis.Sarif.Driver.Sdk
{
public class StatisticsLogger : IResultLogger
{
private Stopwatch _stopwatch;
private long _targetsCount;
private long _invalidTargetsCount;
public StatisticsLogger()
{
_stopwatch = Stopwatch.StartNew();
}
public void Log(ResultKind messageKind, IAnalysisContext context, string message)
{
switch (messageKind)
{
case ResultKind.Pass:
{
break;
}
case ResultKind.Error:
{
break;
}
case ResultKind.Warning:
{
break;
}
case ResultKind.NotApplicable:
{
if (context.Rule.Id == NoteDescriptors.InvalidTarget.Id)
{
_invalidTargetsCount++;
}
break;
}
case ResultKind.Note:
{
if (context.Rule.Id == NoteDescriptors.AnalyzingTarget.Id)
{
_targetsCount++;
}
break;
}
case ResultKind.InternalError:
{
break;
}
case ResultKind.ConfigurationError:
{
break;
}
default:
{
throw new InvalidOperationException();
}
}
}
public void Dispose()
{
Console.WriteLine();
Console.WriteLine("# valid targets: " + _targetsCount.ToString());
Console.WriteLine("# invalid targets: " + _invalidTargetsCount.ToString());
Console.WriteLine("Time elapsed: " + _stopwatch.Elapsed.ToString());
}
public void Log(ResultKind messageKind, IAnalysisContext context, FormattedMessage message)
{
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -5,7 +5,7 @@ namespace Microsoft.CodeAnalysis.Sarif
public static class VersionConstants
{
public const string Prerelease = "-beta";
public const string AssemblyVersion = "1.0.6";
public const string AssemblyVersion = "1.0.9";
public const string FileVersion = AssemblyVersion + ".0";
public const string Version = AssemblyVersion + Prerelease;
}