Fixes Sarif Output Format (#550)
This commit is contained in:
Родитель
bd25052fd2
Коммит
b830cf902b
|
@ -270,3 +270,4 @@ output.html
|
|||
result.json
|
||||
AppInspector.Tests/logs/
|
||||
RulesPacker/appinspector.log.txt
|
||||
AppInspector.CLI/out.sarif
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotLiquid" Version="2.2.692" />
|
||||
<PackageReference Include="Sarif.Sdk" Version="4.1.0" />
|
||||
<PackageReference Include="Sarif.Sdk" Version="4.2.0" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="7.0.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
|
|
|
@ -55,12 +55,45 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
|
||||
if (result is AnalyzeResult analyzeResult)
|
||||
{
|
||||
SarifLog log = new();
|
||||
var sarifVersion = SarifVersion.Current;
|
||||
log.SchemaUri = sarifVersion.ConvertToSchemaUri();
|
||||
log.Version = sarifVersion;
|
||||
SarifLog log = new()
|
||||
{
|
||||
Version = SarifVersion.Current
|
||||
};
|
||||
|
||||
log.Runs = new List<Run>();
|
||||
var run = new Run();
|
||||
// Convert Base Path to Forward Slashes to be a valid URI
|
||||
|
||||
var run = new Run()
|
||||
{
|
||||
Tool = new Tool
|
||||
{
|
||||
Driver = new ToolComponent
|
||||
{
|
||||
Name = "Application Inspector",
|
||||
InformationUri = new Uri("https://github.com/microsoft/ApplicationInspector/"),
|
||||
Organization = "Microsoft",
|
||||
Version = Helpers.GetVersionString()
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!string.IsNullOrEmpty(basePath))
|
||||
{
|
||||
if (Path.DirectorySeparatorChar == '\\')
|
||||
{
|
||||
basePath = basePath.Replace("\\","/");
|
||||
if (!basePath.EndsWith("/"))
|
||||
{
|
||||
basePath = $"{basePath}/";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
run.OriginalUriBaseIds = new Dictionary<string, ArtifactLocation>()
|
||||
{
|
||||
|
||||
{ "ROOT", new ArtifactLocation() { Uri = new Uri($"file://{basePath}") } }
|
||||
};
|
||||
}
|
||||
|
||||
if (Uri.TryCreate(cliAnalyzeCmdOptions.RepositoryUri, UriKind.RelativeOrAbsolute, out var uri))
|
||||
{
|
||||
|
@ -69,7 +102,11 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
new()
|
||||
{
|
||||
RepositoryUri = uri,
|
||||
RevisionId = cliAnalyzeCmdOptions.CommitHash
|
||||
RevisionId = cliAnalyzeCmdOptions.CommitHash,
|
||||
MappedTo = new ArtifactLocation()
|
||||
{
|
||||
UriBaseId = "ROOT"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -81,22 +118,17 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
{
|
||||
RepositoryUri = analyzeResult.Metadata.RepositoryUri,
|
||||
RevisionId = analyzeResult.Metadata.CommitHash ?? string.Empty,
|
||||
Branch = analyzeResult.Metadata.Branch ?? string.Empty
|
||||
Branch = analyzeResult.Metadata.Branch ?? string.Empty,
|
||||
MappedTo = new ArtifactLocation()
|
||||
{
|
||||
UriBaseId = "ROOT"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var artifacts = new List<Artifact>();
|
||||
run.Tool = new Tool
|
||||
{
|
||||
Driver = new ToolComponent
|
||||
{
|
||||
Name = "Application Inspector",
|
||||
InformationUri = new Uri("https://github.com/microsoft/ApplicationInspector/"),
|
||||
Organization = "Microsoft",
|
||||
Version = Helpers.GetVersionString()
|
||||
}
|
||||
};
|
||||
|
||||
var reportingDescriptors = new List<ReportingDescriptor>();
|
||||
run.Results = new List<CodeAnalysis.Sarif.Result>();
|
||||
foreach (var match in analyzeResult.Metadata.Matches)
|
||||
|
@ -114,14 +146,15 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
Name = match.Rule.Name,
|
||||
DefaultConfiguration = new ReportingConfiguration
|
||||
{
|
||||
Level = GetSarifFailureLevel(match.Rule.Severity)
|
||||
Level = FailureLevel.Note
|
||||
}
|
||||
};
|
||||
reportingDescriptor.Tags.AddRange(match.Rule.Tags);
|
||||
reportingDescriptor.SetProperty("AppInspector:Severity", match.Rule.Severity.ToString());
|
||||
reportingDescriptors.Add(reportingDescriptor);
|
||||
}
|
||||
|
||||
sarifResult.Level = GetSarifFailureLevel(match.Rule.Severity);
|
||||
sarifResult.Level = FailureLevel.Note;
|
||||
sarifResult.RuleId = match.Rule.Id;
|
||||
sarifResult.Tags.AddRange(match.Rule.Tags);
|
||||
sarifResult.Message = new Message
|
||||
|
@ -134,7 +167,7 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
var fileName = match.FileName;
|
||||
if (basePath is not null)
|
||||
{
|
||||
fileName = Path.GetRelativePath(basePath, fileName);
|
||||
fileName = Path.GetRelativePath(basePath, fileName).Replace("\\","/");
|
||||
}
|
||||
|
||||
if (Uri.TryCreate(fileName, UriKind.RelativeOrAbsolute, out var outUri))
|
||||
|
@ -150,6 +183,10 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
Uri = outUri
|
||||
}
|
||||
};
|
||||
if (basePath != null)
|
||||
{
|
||||
artifact.Location.UriBaseId = "ROOT";
|
||||
}
|
||||
artifactIndex = artifact.Location.Index;
|
||||
artifact.Tags.AddRange(match.Rule.Tags);
|
||||
if (match.LanguageInfo is { } languageInfo)
|
||||
|
@ -164,30 +201,37 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
artifacts[artifactIndex].Tags.AddRange(match.Rule.Tags);
|
||||
}
|
||||
|
||||
sarifResult.Locations = new List<Location>
|
||||
Location location = new()
|
||||
{
|
||||
new()
|
||||
PhysicalLocation = new PhysicalLocation
|
||||
{
|
||||
PhysicalLocation = new PhysicalLocation
|
||||
ArtifactLocation = new ArtifactLocation
|
||||
{
|
||||
ArtifactLocation = new ArtifactLocation
|
||||
Index = artifactIndex,
|
||||
Uri = outUri
|
||||
},
|
||||
Region = new Region
|
||||
{
|
||||
StartLine = match.StartLocationLine,
|
||||
StartColumn = match.StartLocationColumn,
|
||||
EndLine = match.EndLocationLine,
|
||||
EndColumn = match.EndLocationColumn,
|
||||
Snippet = new ArtifactContent
|
||||
{
|
||||
Index = artifactIndex
|
||||
},
|
||||
Region = new Region
|
||||
{
|
||||
StartLine = match.StartLocationLine,
|
||||
StartColumn = match.StartLocationColumn,
|
||||
EndLine = match.EndLocationLine,
|
||||
EndColumn = match.EndLocationColumn,
|
||||
Snippet = new ArtifactContent
|
||||
{
|
||||
Text = match.Sample
|
||||
}
|
||||
Text = match.Sample
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
if (basePath != null)
|
||||
{
|
||||
location.PhysicalLocation.ArtifactLocation.UriBaseId = "ROOT";
|
||||
}
|
||||
sarifResult.SetProperty("AppInspector:Severity", match.Rule.Severity.ToString());
|
||||
sarifResult.Locations = new List<Location>
|
||||
{
|
||||
location
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +244,7 @@ public class AnalyzeSarifWriter : CommandResultsWriter
|
|||
log.Runs.Add(run);
|
||||
try
|
||||
{
|
||||
JsonSerializer.Serialize(StreamWriter.BaseStream, log);
|
||||
log.Save(StreamWriter.BaseStream);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
|
@ -181,7 +181,7 @@ public class RuleProcessor
|
|||
EndLocationColumn = endLocation.Column,
|
||||
MatchingPattern = oatRule.AppInspectorRule.Patterns[patternIndex],
|
||||
Excerpt = numLinesContext > 0
|
||||
? ExtractExcerpt(textContainer, startLocation.Line, numLinesContext)
|
||||
? ExtractExcerpt(textContainer, startLocation, endLocation, boundary, numLinesContext)
|
||||
: string.Empty,
|
||||
Sample = numLinesContext > -1
|
||||
? ExtractTextSample(textContainer.FullContent, boundary.Index, boundary.Length)
|
||||
|
@ -399,7 +399,7 @@ public class RuleProcessor
|
|||
: startLocation.Line + 1, //match is on last line
|
||||
MatchingPattern = oatRule.AppInspectorRule.Patterns[patternIndex],
|
||||
Excerpt = numLinesContext > 0
|
||||
? ExtractExcerpt(textContainer, startLocation.Line, numLinesContext)
|
||||
? ExtractExcerpt(textContainer, startLocation, endLocation, boundary, numLinesContext)
|
||||
: string.Empty,
|
||||
Sample = numLinesContext > -1
|
||||
? ExtractTextSample(textContainer.FullContent, boundary.Index, boundary.Length)
|
||||
|
@ -554,37 +554,30 @@ public class RuleProcessor
|
|||
/// from the template
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string ExtractExcerpt(TextContainer text, int startLineNumber, int context = 3)
|
||||
private static string ExtractExcerpt(TextContainer text, Location start, Location end, Boundary matchBoundary, int context = 3)
|
||||
{
|
||||
if (context == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (startLineNumber < 0)
|
||||
{
|
||||
startLineNumber = 0;
|
||||
}
|
||||
|
||||
if (startLineNumber >= text.LineEnds.Count)
|
||||
{
|
||||
startLineNumber = text.LineEnds.Count - 1;
|
||||
}
|
||||
|
||||
int startLineNumber =
|
||||
start.Line < 0 ? 0 : start.Line > text.LineEnds.Count ? text.LineEnds.Count - 1 : start.Line;
|
||||
int endLineNUmber =
|
||||
end.Line < 0 ? 0 : end.Line > text.LineEnds.Count ? text.LineEnds.Count - 1 : end.Line;
|
||||
// First we try to include the number of lines of context requested
|
||||
var excerptStartLine = Math.Max(0, startLineNumber - context);
|
||||
var excerptEndLine = Math.Min(text.LineEnds.Count - 1, startLineNumber + context);
|
||||
var excerptEndLine = Math.Min(text.LineEnds.Count - 1, endLineNUmber + context);
|
||||
var startIndex = text.LineStarts[excerptStartLine];
|
||||
var endIndex = text.LineEnds[excerptEndLine] + 1;
|
||||
// Maximum number of characters to capture on each side
|
||||
var maxCharacterContext = context * 100;
|
||||
// Only gather 100*lines context characters to avoid gathering super long lines
|
||||
if (text.LineStarts[startLineNumber] - startIndex > maxCharacterContext)
|
||||
// If the number of characters captured for context is larger than 100*number of lines,
|
||||
// instead gather an appropriate number of characters
|
||||
if (endIndex - startIndex - matchBoundary.Length > maxCharacterContext * 2)
|
||||
{
|
||||
startIndex = Math.Max(0, startIndex - maxCharacterContext);
|
||||
}
|
||||
|
||||
if (endIndex - text.LineEnds[startLineNumber] > maxCharacterContext)
|
||||
{
|
||||
endIndex = Math.Min(text.FullContent.Length - 1, endIndex + maxCharacterContext);
|
||||
startIndex = Math.Max(0, matchBoundary.Index - maxCharacterContext);
|
||||
endIndex = Math.Max(0, matchBoundary.Index + matchBoundary.Length + maxCharacterContext);
|
||||
}
|
||||
|
||||
return text.FullContent[startIndex..endIndex];
|
||||
|
|
Загрузка…
Ссылка в новой задаче