From 89559ba99f6c5b9be87aaff9a41b27d47af21e04 Mon Sep 17 00:00:00 2001 From: andream16 Date: Mon, 2 Dec 2024 16:09:25 +0000 Subject: [PATCH] Generating sarif bindings. --- sarif/Dockerfile.gojsonschema | 8 + sarif/Makefile | 25 + sarif/README.md | 66 + sarif/go.mod | 5 + sarif/go.sum | 2 + sarif/sarif_test.go | 212 + .../contracts/sarif-schema/v2-1-0/schema.json | 3389 ++++++++++++++++ .../contracts/sarif-schema/v2-2-0/schema.json | 3058 ++++++++++++++ sarif/spec/gen/sarif-schema/v2-1-0/schema.go | 3506 ++++++++++++++++ sarif/spec/gen/sarif-schema/v2-2-0/schema.go | 3584 +++++++++++++++++ sarif/testdata/gosec_v2.1.0.json | 1314 ++++++ .../mitchellh/mapstructure/CHANGELOG.md | 96 + .../github.com/mitchellh/mapstructure/LICENSE | 21 + .../mitchellh/mapstructure/README.md | 46 + .../mitchellh/mapstructure/decode_hooks.go | 279 ++ .../mitchellh/mapstructure/error.go | 50 + .../mitchellh/mapstructure/mapstructure.go | 1540 +++++++ sarif/vendor/modules.txt | 3 + 18 files changed, 17204 insertions(+) create mode 100644 sarif/Dockerfile.gojsonschema create mode 100644 sarif/Makefile create mode 100644 sarif/README.md create mode 100644 sarif/go.mod create mode 100644 sarif/go.sum create mode 100644 sarif/sarif_test.go create mode 100644 sarif/spec/contracts/sarif-schema/v2-1-0/schema.json create mode 100644 sarif/spec/contracts/sarif-schema/v2-2-0/schema.json create mode 100644 sarif/spec/gen/sarif-schema/v2-1-0/schema.go create mode 100644 sarif/spec/gen/sarif-schema/v2-2-0/schema.go create mode 100644 sarif/testdata/gosec_v2.1.0.json create mode 100644 sarif/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md create mode 100644 sarif/vendor/github.com/mitchellh/mapstructure/LICENSE create mode 100644 sarif/vendor/github.com/mitchellh/mapstructure/README.md create mode 100644 sarif/vendor/github.com/mitchellh/mapstructure/decode_hooks.go create mode 100644 sarif/vendor/github.com/mitchellh/mapstructure/error.go create mode 100644 sarif/vendor/github.com/mitchellh/mapstructure/mapstructure.go create mode 100644 sarif/vendor/modules.txt diff --git a/sarif/Dockerfile.gojsonschema b/sarif/Dockerfile.gojsonschema new file mode 100644 index 0000000..6d64ff5 --- /dev/null +++ b/sarif/Dockerfile.gojsonschema @@ -0,0 +1,8 @@ +FROM golang:1.23-alpine + +RUN apk add --no-cache ca-certificates +RUN go install github.com/atombender/go-jsonschema@v0.17.0 + +WORKDIR /app + +ENTRYPOINT ["go-jsonschema"] diff --git a/sarif/Makefile b/sarif/Makefile new file mode 100644 index 0000000..98ba219 --- /dev/null +++ b/sarif/Makefile @@ -0,0 +1,25 @@ +.PHONY: build-image generate-schemas + +# Schema versions. +VERSIONS := v2-1-0 v2-2-0 +# Base paths. +SPEC_DIR := spec/contracts/sarif-schema +GEN_DIR := gen/sarif-schema + +build-image: + @echo "Building the Docker image..." + docker build \ + --platform linux/amd64 \ + -t gojsonschema . -f Dockerfile.gojsonschema + +generate-schemas: build-image + @for version in $(VERSIONS); do \ + echo "Generating schema for $$version..."; \ + rm -rf $(GEN_DIR)/$$version; \ + mkdir -p $(GEN_DIR)/$$version; \ + docker run \ + --platform linux/amd64 \ + -v ./spec:/app/spec \ + -it gojsonschema:latest \ + -p schema $(SPEC_DIR)/$$version/schema.json > $(GEN_DIR)/$$version/schema.go; \ + done \ No newline at end of file diff --git a/sarif/README.md b/sarif/README.md new file mode 100644 index 0000000..78e337f --- /dev/null +++ b/sarif/README.md @@ -0,0 +1,66 @@ +# sarif + +Utilities for [sarif](https://sarifweb.azurewebsites.net/) that leverage generated code for +[sarif-spec](https://github.com/oasis-tcs/sarif-spec/tree/main). + +## Why? + +Other packages are not well maintained and don't leverage generated code. + +This means that updates to the specification are not often backported into the packages. + +## How to use + +### V2.1.0 +For [v2.1.0](https://github.com/oasis-tcs/sarif-spec/tree/main/sarif-2.1): + +```go +package main + +import ( + "log" + + schemav1 "github.com/smithy-security/pkg/sarif/spec/gen/sarif-schema/v2-1-0" +) + +//go:embed testdata/gosec_v2.1.0.json +var reportV2_1_0 []byte + +func main() { + report := schemav1.SchemaJson{} + if err := report.UnmarshalJSON(reportV2_1_0); err != nil { + log.Fatalf("report unmarshalling failed: %v", err) + } +} +``` + +### V2.2.0 +For [v2.2.0](https://github.com/oasis-tcs/sarif-spec/tree/main/sarif-2.2): + +```go +package main + +import ( + "log" + + schemav2 "github.com/smithy-security/pkg/sarif/spec/gen/sarif-schema/v2-2-0" +) + +//go:embed testdata/gosec_v2.2.0.json +var reportV2_2_0 []byte + +func main() { + report := schemav2.SchemaJson{} + if err := report.UnmarshalJSON(reportV2_2_0); err != nil { + log.Fatalf("report unmarshalling failed: %v", err) + } +} +``` + +## Generate code + +To generate the code from the jsonschema specs, please run: + +```shell +make generate-schemas +``` \ No newline at end of file diff --git a/sarif/go.mod b/sarif/go.mod new file mode 100644 index 0000000..5cd8fa3 --- /dev/null +++ b/sarif/go.mod @@ -0,0 +1,5 @@ +module github.com/smithy-security/pkg/sarif + +go 1.23.2 + +require github.com/mitchellh/mapstructure v1.5.0 diff --git a/sarif/go.sum b/sarif/go.sum new file mode 100644 index 0000000..59f4b8e --- /dev/null +++ b/sarif/go.sum @@ -0,0 +1,2 @@ +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= diff --git a/sarif/sarif_test.go b/sarif/sarif_test.go new file mode 100644 index 0000000..ebd8f82 --- /dev/null +++ b/sarif/sarif_test.go @@ -0,0 +1,212 @@ +package sarif_test + +import ( + _ "embed" + "testing" + + schemav1 "github.com/smithy-security/pkg/sarif/spec/gen/sarif-schema/v2-1-0" +) + +var ( + //go:embed testdata/gosec_v2.1.0.json + reportV2_1_0 []byte +) + +func TestReportFromBytesV2_1_0(t *testing.T) { + const ( + expectedNumOfRuns = 1 + expectedNumResults = 21 + expectedNumTaxonomies = 1 + expectedNumTaxas = 12 + expectedNumDriverRules = 15 + ) + + report := schemav1.SchemaJson{} + if err := report.UnmarshalJSON(reportV2_1_0); err != nil { + t.Fatalf("report unmarshalling failed: %v", err) + } + + switch { + case *report.Schema != "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json": + t.Fatalf("unexpected schema '%s'", *report.Schema) + case report.Version != "2.1.0": + t.Fatalf("Expected version '2.1.0', got '%s'", report.Version) + case expectedNumOfRuns != len(report.Runs): + t.Fatalf("expected %d runs. Expected %d", len(report.Runs), expectedNumOfRuns) + case expectedNumResults != len(report.Runs[0].Results): + t.Fatalf("expected %d results. Expected %d", len(report.Runs[0].Results), expectedNumResults) + case expectedNumTaxonomies != len(report.Runs[0].Taxonomies): + t.Fatalf("expected %d taxonomies. Expected %d", len(report.Runs[0].Taxonomies), expectedNumTaxonomies) + } + + run := report.Runs[0] + + for _, res := range run.Results { + switch { + case res.Level != "error" && res.Level != "warning": + t.Fatalf("Expected level 'error', got '%s'", res.Level) + case *res.Message.Text == "": + t.Fatal("Expected message text to not be empty") + case *res.RuleId == "": + t.Fatal("Expected rule id to not be empty") + } + + for _, loc := range res.Locations { + if loc.PhysicalLocation == nil { + t.Fatal("Expected physical location not to be nil") + } + + switch { + case loc.PhysicalLocation.ArtifactLocation == nil: + t.Fatal("Expected PhysicalLocation ArtifactLocation to not be nil") + case loc.PhysicalLocation.ArtifactLocation.Uri == nil || *loc.PhysicalLocation.ArtifactLocation.Uri == "": + t.Fatalf("Expected PhysicalLocation ArtifactLocation Uri to not be empty") + case loc.PhysicalLocation.Region == nil: + t.Fatal("Expected PhysicalLocation ArtifactLocation Region to not be empty") + case loc.PhysicalLocation.Region.EndColumn == nil: + t.Fatal("Expected PhysicalLocation ArtifactLocation Region EndColumn to not be empty") + case loc.PhysicalLocation.Region.StartColumn == nil: + t.Fatal("Expected PhysicalLocation ArtifactLocation Region StartColumn to not be empty") + case loc.PhysicalLocation.Region.EndLine == nil: + t.Fatal("Expected PhysicalLocation ArtifactLocation Region EndLine to not be empty") + case loc.PhysicalLocation.Region.StartLine == nil: + t.Fatal("Expected PhysicalLocation ArtifactLocation Region StartLine to not be empty") + case loc.PhysicalLocation.Region.Snippet == nil: + t.Fatal("Expected PhysicalLocation ArtifactLocation Region Snippet to not be empty") + case loc.PhysicalLocation.Region.Snippet.Text == nil || *loc.PhysicalLocation.Region.Snippet.Text == "": + t.Fatal("Expected PhysicalLocation ArtifactLocation Region Snippet Text to not be empty") + } + } + } + + for _, taxonomy := range run.Taxonomies { + switch { + case taxonomy.DownloadUri == nil || *taxonomy.DownloadUri == "": + t.Fatal("Expected taxonomy URI to not be empty") + case taxonomy.Guid == nil || *taxonomy.Guid == "": + t.Fatal("Expected taxonomy Guid to not be empty") + case taxonomy.InformationUri == nil || *taxonomy.InformationUri == "": + t.Fatal("Expected taxonomy InformationUri to not be empty") + case taxonomy.MinimumRequiredLocalizedDataSemanticVersion == nil || *taxonomy.MinimumRequiredLocalizedDataSemanticVersion == "": + t.Fatal("Expected taxonomy MinimumRequiredLocalizedDataSemanticVersion to not be empty") + case !taxonomy.IsComprehensive: + t.Fatal("Expected taxonomy to be comprehensive") + case taxonomy.Language == "": + t.Fatal("Expected taxonomy Language to not be empty") + case taxonomy.Name == "": + t.Fatal("Expected taxonomy Name to not be empty") + case taxonomy.Organization == nil || *taxonomy.Organization == "": + t.Fatal("Expected taxonomy Organization to not be empty") + case taxonomy.ReleaseDateUtc == nil || *taxonomy.ReleaseDateUtc == "": + t.Fatal("Expected taxonomy ReleaseDateUtc to not be empty") + case taxonomy.ShortDescription == nil: + t.Fatal("Expected taxonomy ShortDescription to not be nil") + case taxonomy.ShortDescription.Text == "": + t.Fatal("Expected taxonomy ShortDescription Text to not be nil") + case taxonomy.Version == nil || *taxonomy.Version == "": + t.Fatal("Expected taxonomy Version to not be empty") + case expectedNumTaxas != len(taxonomy.Taxa): + t.Fatalf("Expected %d taxonomy taxas. Found %d instead", expectedNumTaxas, len(taxonomy.Taxa)) + } + + for _, taxa := range taxonomy.Taxa { + switch { + case taxa.FullDescription == nil: + t.Fatal("Expected taxa FullDescription to not be nil") + case taxa.FullDescription.Text == "": + t.Fatal("Expected taxa FullDescription Text to not be empty") + case taxa.Guid == nil || *taxa.Guid == "": + t.Fatal("Expected taxa Guid to not be empty") + case taxa.HelpUri == nil || *taxa.HelpUri == "": + t.Fatal("Expected taxa HelpUri to not be empty") + case taxa.ShortDescription == nil: + t.Fatal("Expected taxa ShortDescription to not be nil") + case taxa.ShortDescription.Text == "": + t.Fatal("Expected taxa ShortDescription Text to not be nil") + case taxa.Id == "": + t.Fatal("Expected taxa Id to not be empty") + } + } + } + + driver := run.Tool.Driver + switch { + case driver.Guid == nil || *driver.Guid == "": + t.Fatal("Expected Driver Guid to not be empty") + case driver.InformationUri == nil || *driver.InformationUri == "": + t.Fatal("Expected Driver InformationUri to not be empty") + case driver.SemanticVersion == nil || *driver.SemanticVersion == "": + t.Fatal("Expected Driver SemanticVersion to not be empty") + case driver.Version == nil || *driver.Version == "": + t.Fatal("Expected Driver Version to not be empty") + case driver.Name == "": + t.Fatal("Expected Driver Name to not be empty") + case len(driver.SupportedTaxonomies) != 1: + t.Fatalf("expected 1 Driver SupportedTaxonomy. Got %d instead", len(driver.SupportedTaxonomies)) + case len(driver.Rules) != expectedNumDriverRules: + t.Fatalf("expected 1 Driver Rules. Got %d instead", len(driver.Rules)) + } + + for _, rule := range driver.Rules { + switch { + case rule.DefaultConfiguration == nil: + t.Fatal("Expected rule DefaultConfiguration to not be nil") + case rule.FullDescription == nil: + t.Fatal("Expected rule FullDescription to not be nil") + case rule.Help == nil: + t.Fatal("Expected rule Help to not be nil") + case rule.Properties == nil: + t.Fatal("Expected rule Properties to not be nil") + case rule.ShortDescription == nil: + t.Fatal("Expected rule ShortDescription to not be nil") + case len(rule.Relationships) == 0: + t.Fatal("Expected rule Relationships to not be empty") + case rule.DefaultConfiguration.Level == "": + t.Fatal("Expected DefaultConfiguration Level to not be empty") + case rule.FullDescription.Text == "": + t.Fatal("Expected FullDescription Text to not be empty") + case rule.Help.Text == "": + t.Fatal("Expected Help Text to not be empty") + case rule.Id == "": + t.Fatal("Expected rule Id to not be empty") + case rule.Name == nil || *rule.Name == "": + t.Fatal("Expected rule Name to not be empty") + case rule.ShortDescription.Text == "": + t.Fatal("Expected rule ShortDescription Text to not be empty") + case rule.Properties.AdditionalProperties == nil: + t.Fatal("Expected rule Properties AdditionalProperties to not be nil") + case len(rule.Properties.Tags) != 2: + t.Fatal("Expected rule Properties Tags to have 2 elements") + } + + props, ok := rule.Properties.AdditionalProperties.(map[string]any) + if !ok { + t.Fatal("Expected rule Properties AdditionalProperties to be a map") + } + + precision, ok := props["precision"] + switch { + case !ok: + t.Fatal("Expected rule Precision to be found in properties") + case precision == "": + t.Fatal("Expected rule Precision to not be empty") + } + + for _, rel := range rule.Relationships { + switch { + case rel.Target.Id == nil || *rel.Target.Id == "": + t.Fatal("Expected rule Target Id to not be empty") + case rel.Target.Guid == nil || *rel.Target.Guid == "": + t.Fatal("Expected rule Target Guid to not be empty") + case rel.Target.ToolComponent == nil: + t.Fatal("Expected rule Target ToolComponent to not be nil") + case rel.Target.ToolComponent.Guid == nil: + t.Fatal("Expected rule Target ToolComponent Guid to not be empty") + case rel.Target.ToolComponent.Name == nil || *rel.Target.ToolComponent.Name == "": + t.Fatal("Expected rule Target ToolComponent Name to not be empty") + case len(rel.Kinds) == 0: + t.Fatal("Expected rule Kind to not be empty") + } + } + } +} diff --git a/sarif/spec/contracts/sarif-schema/v2-1-0/schema.json b/sarif/spec/contracts/sarif-schema/v2-1-0/schema.json new file mode 100644 index 0000000..f9c54b8 --- /dev/null +++ b/sarif/spec/contracts/sarif-schema/v2-1-0/schema.json @@ -0,0 +1,3389 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Static Analysis Results Format (SARIF) Version 2.1.0 JSON Schema", + "id": "https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json", + "description": "Static Analysis Results Format (SARIF) Version 2.1.0 JSON Schema: a standard format for the output of static analysis tools.", + "additionalProperties": false, + "type": "object", + "properties": { + + "$schema": { + "description": "The URI of the JSON schema corresponding to the version.", + "type": "string", + "format": "uri" + }, + + "version": { + "description": "The SARIF format version of this log file.", + "enum": [ "2.1.0" ], + "type": "string" + }, + + "runs": { + "description": "The set of runs contained in this log file.", + "type": [ "array", "null" ], + "minItems": 0, + "uniqueItems": false, + "items": { + "$ref": "#/definitions/run" + } + }, + + "inlineExternalProperties": { + "description": "References to external property files that share data between runs.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/externalProperties" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the log file.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "version", "runs" ], + + "definitions": { + + "address": { + "description": "A physical or virtual address, or a range of addresses, in an 'addressable region' (memory or a binary file).", + "additionalProperties": false, + "type": "object", + "properties": { + + "absoluteAddress": { + "description": "The address expressed as a byte offset from the start of the addressable region.", + "type": "integer", + "minimum": -1, + "default": -1 + + }, + + "relativeAddress": { + "description": "The address expressed as a byte offset from the absolute address of the top-most parent object.", + "type": "integer" + + }, + + "length": { + "description": "The number of bytes in this range of addresses.", + "type": "integer" + }, + + "kind": { + "description": "An open-ended string that identifies the address kind. 'data', 'function', 'header','instruction', 'module', 'page', 'section', 'segment', 'stack', 'stackFrame', 'table' are well-known values.", + "type": "string" + }, + + "name": { + "description": "A name that is associated with the address, e.g., '.text'.", + "type": "string" + }, + + "fullyQualifiedName": { + "description": "A human-readable fully qualified name that is associated with the address.", + "type": "string" + }, + + "offsetFromParent": { + "description": "The byte offset of this address from the absolute or relative address of the parent object.", + "type": "integer" + }, + + "index": { + "description": "The index within run.addresses of the cached object for this address.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "parentIndex": { + "description": "The index within run.addresses of the parent object.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the address.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "artifact": { + "description": "A single artifact. In some cases, this artifact might be nested within another artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + + "description": { + "description": "A short description of the artifact.", + "$ref": "#/definitions/message" + }, + + "location": { + "description": "The location of the artifact.", + "$ref": "#/definitions/artifactLocation" + }, + + "parentIndex": { + "description": "Identifies the index of the immediate parent of the artifact, if this artifact is nested.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "offset": { + "description": "The offset in bytes of the artifact within its containing artifact.", + "type": "integer", + "minimum": 0 + }, + + "length": { + "description": "The length of the artifact in bytes.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "roles": { + "description": "The role or roles played by the artifact in the analysis.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "enum": [ + "analysisTarget", + "attachment", + "responseFile", + "resultFile", + "standardStream", + "tracedFile", + "unmodified", + "modified", + "added", + "deleted", + "renamed", + "uncontrolled", + "driver", + "extension", + "translation", + "taxonomy", + "policy", + "referencedOnCommandLine", + "memoryContents", + "directory", + "userSpecifiedConfiguration", + "toolSpecifiedConfiguration", + "debugOutputFile" + ], + "type": "string" + } + }, + + "mimeType": { + "description": "The MIME type (RFC 2045) of the artifact.", + "type": "string", + "pattern": "[^/]+/.+" + }, + + "contents": { + "description": "The contents of the artifact.", + "$ref": "#/definitions/artifactContent" + }, + + "encoding": { + "description": "Specifies the encoding for an artifact object that refers to a text file.", + "type": "string" + }, + + "sourceLanguage": { + "description": "Specifies the source language for any artifact object that refers to a text file that contains source code.", + "type": "string" + }, + + "hashes": { + "description": "A dictionary, each of whose keys is the name of a hash function and each of whose values is the hashed value of the artifact produced by the specified hash function.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + + "lastModifiedTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the artifact was most recently modified. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the artifact.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "artifactChange": { + "description": "A change to a single artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + + "artifactLocation": { + "description": "The location of the artifact to change.", + "$ref": "#/definitions/artifactLocation" + }, + + "replacements": { + "description": "An array of replacement objects, each of which represents the replacement of a single region in a single artifact specified by 'artifactLocation'.", + "type": "array", + "minItems": 1, + "uniqueItems": false, + "items": { + "$ref": "#/definitions/replacement" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the change.", + "$ref": "#/definitions/propertyBag" + } + + }, + + "required": [ "artifactLocation", "replacements" ] + }, + + "artifactContent": { + "description": "Represents the contents of an artifact.", + "type": "object", + "additionalProperties": false, + "properties": { + + "text": { + "description": "UTF-8-encoded content from a text artifact.", + "type": "string" + }, + + "binary": { + "description": "MIME Base64-encoded content from a binary artifact, or from a text artifact in its original encoding.", + "type": "string" + }, + + "rendered": { + "description": "An alternate rendered representation of the artifact (e.g., a decompiled representation of a binary region).", + "$ref": "#/definitions/multiformatMessageString" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the artifact content.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "artifactLocation": { + "description": "Specifies the location of an artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + + "uri": { + "description": "A string containing a valid relative or absolute URI.", + "type": "string", + "format": "uri-reference" + }, + + "uriBaseId": { + "description": "A string which indirectly specifies the absolute URI with respect to which a relative URI in the \"uri\" property is interpreted.", + "type": "string" + }, + + "index": { + "description": "The index within the run artifacts array of the artifact object associated with the artifact location.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "description": { + "description": "A short description of the artifact location.", + "$ref": "#/definitions/message" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the artifact location.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "attachment": { + "description": "An artifact relevant to a result.", + "type": "object", + "additionalProperties": false, + "properties": { + + "description": { + "description": "A message describing the role played by the attachment.", + "$ref": "#/definitions/message" + }, + + "artifactLocation": { + "description": "The location of the attachment.", + "$ref": "#/definitions/artifactLocation" + }, + + "regions": { + "description": "An array of regions of interest within the attachment.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/region" + } + }, + + "rectangles": { + "description": "An array of rectangles specifying areas of interest within the image.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/rectangle" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the attachment.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "artifactLocation" ] + }, + + "codeFlow": { + "description": "A set of threadFlows which together describe a pattern of code execution relevant to detecting a result.", + "additionalProperties": false, + "type": "object", + "properties": { + + "message": { + "description": "A message relevant to the code flow.", + "$ref": "#/definitions/message" + }, + + "threadFlows": { + "description": "An array of one or more unique threadFlow objects, each of which describes the progress of a program through a thread of execution.", + "type": "array", + "minItems": 1, + "uniqueItems": false, + "items": { + "$ref": "#/definitions/threadFlow" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the code flow.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "threadFlows" ] + }, + + "configurationOverride": { + "description": "Information about how a specific rule or notification was reconfigured at runtime.", + "type": "object", + "additionalProperties": false, + "properties": { + + "configuration": { + "description": "Specifies how the rule or notification was configured during the scan.", + "$ref": "#/definitions/reportingConfiguration" + }, + + "descriptor": { + "description": "A reference used to locate the descriptor whose configuration was overridden.", + "$ref": "#/definitions/reportingDescriptorReference" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the configuration override.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "configuration", "descriptor" ] + }, + + "conversion": { + "description": "Describes how a converter transformed the output of a static analysis tool from the analysis tool's native output format into the SARIF format.", + "additionalProperties": false, + "type": "object", + "properties": { + + "tool": { + "description": "A tool object that describes the converter.", + "$ref": "#/definitions/tool" + }, + + "invocation": { + "description": "An invocation object that describes the invocation of the converter.", + "$ref": "#/definitions/invocation" + }, + + "analysisToolLogFiles": { + "description": "The locations of the analysis tool's per-run log files.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/artifactLocation" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the conversion.", + "$ref": "#/definitions/propertyBag" + } + + }, + + "required": [ "tool" ] + }, + + "edge": { + "description": "Represents a directed edge in a graph.", + "type": "object", + "additionalProperties": false, + "properties": { + + "id": { + "description": "A string that uniquely identifies the edge within its graph.", + "type": "string" + }, + + "label": { + "description": "A short description of the edge.", + "$ref": "#/definitions/message" + }, + + "sourceNodeId": { + "description": "Identifies the source node (the node at which the edge starts).", + "type": "string" + }, + + "targetNodeId": { + "description": "Identifies the target node (the node at which the edge ends).", + "type": "string" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the edge.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "id", "sourceNodeId", "targetNodeId" ] + }, + + "edgeTraversal": { + "description": "Represents the traversal of a single edge during a graph traversal.", + "type": "object", + "additionalProperties": false, + "properties": { + + "edgeId": { + "description": "Identifies the edge being traversed.", + "type": "string" + }, + + "message": { + "description": "A message to display to the user as the edge is traversed.", + "$ref": "#/definitions/message" + }, + + "finalState": { + "description": "The values of relevant expressions after the edge has been traversed.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "stepOverEdgeCount": { + "description": "The number of edge traversals necessary to return from a nested graph.", + "type": "integer", + "minimum": 0 + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the edge traversal.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "edgeId" ] + }, + + "exception": { + "description": "Describes a runtime exception encountered during the execution of an analysis tool.", + "type": "object", + "additionalProperties": false, + "properties": { + + "kind": { + "type": "string", + "description": "A string that identifies the kind of exception, for example, the fully qualified type name of an object that was thrown, or the symbolic name of a signal." + }, + + "message": { + "description": "A message that describes the exception.", + "type": "string" + }, + + "stack": { + "description": "The sequence of function calls leading to the exception.", + "$ref": "#/definitions/stack" + }, + + "innerExceptions": { + "description": "An array of exception objects each of which is considered a cause of this exception.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/exception" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the exception.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "externalProperties": { + "description": "The top-level element of an external property file.", + "type": "object", + "additionalProperties": false, + "properties": { + + "schema": { + "description": "The URI of the JSON schema corresponding to the version of the external property file format.", + "type": "string", + "format": "uri" + }, + + "version": { + "description": "The SARIF format version of this external properties object.", + "enum": [ "2.1.0" ], + "type": "string" + }, + + "guid": { + "description": "A stable, unique identifier for this external properties object, in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "runGuid": { + "description": "A stable, unique identifier for the run associated with this external properties object, in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "conversion": { + "description": "A conversion object that will be merged with a separate run.", + "$ref": "#/definitions/conversion" + }, + + "graphs": { + "description": "An array of graph objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "default": [], + "uniqueItems": true, + "items": { + "$ref": "#/definitions/graph" + } + }, + + "externalizedProperties": { + "description": "Key/value pairs that provide additional information that will be merged with a separate run.", + "$ref": "#/definitions/propertyBag" + }, + + "artifacts": { + "description": "An array of artifact objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/artifact" + } + }, + + "invocations": { + "description": "Describes the invocation of the analysis tool that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/invocation" + } + }, + + "logicalLocations": { + "description": "An array of logical locations such as namespaces, types or functions that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/logicalLocation" + } + }, + + "threadFlowLocations": { + "description": "An array of threadFlowLocation objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/threadFlowLocation" + } + }, + + "results": { + "description": "An array of result objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/result" + } + }, + + "taxonomies": { + "description": "Tool taxonomies that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "driver": { + "description": "The analysis tool object that will be merged with a separate run.", + "$ref": "#/definitions/toolComponent" + }, + + "extensions": { + "description": "Tool extensions that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "policies": { + "description": "Tool policies that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "translations": { + "description": "Tool translations that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "addresses": { + "description": "Addresses that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/address" + } + }, + + "webRequests": { + "description": "Requests that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/webRequest" + } + }, + + "webResponses": { + "description": "Responses that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/webResponse" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the external properties.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "externalPropertyFileReference": { + "description": "Contains information that enables a SARIF consumer to locate the external property file that contains the value of an externalized property associated with the run.", + "type": "object", + "additionalProperties": false, + "properties": { + + "location": { + "description": "The location of the external property file.", + "$ref": "#/definitions/artifactLocation" + }, + + "guid": { + "description": "A stable, unique identifier for the external property file in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "itemCount": { + "description": "A non-negative integer specifying the number of items contained in the external property file.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the external property file.", + "$ref": "#/definitions/propertyBag" + } + }, + "anyOf": [ + { "required": [ "location" ] }, + { "required": [ "guid" ] } + ] + }, + + "externalPropertyFileReferences": { + "description": "References to external property files that should be inlined with the content of a root log file.", + "additionalProperties": false, + "type": "object", + "properties": { + + "conversion": { + "description": "An external property file containing a run.conversion object to be merged with the root log file.", + "$ref": "#/definitions/externalPropertyFileReference" + }, + + "graphs": { + "description": "An array of external property files containing a run.graphs object to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "externalizedProperties": { + "description": "An external property file containing a run.properties object to be merged with the root log file.", + "$ref": "#/definitions/externalPropertyFileReference" + }, + + "artifacts": { + "description": "An array of external property files containing run.artifacts arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "invocations": { + "description": "An array of external property files containing run.invocations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "logicalLocations": { + "description": "An array of external property files containing run.logicalLocations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "threadFlowLocations": { + "description": "An array of external property files containing run.threadFlowLocations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "results": { + "description": "An array of external property files containing run.results arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "taxonomies": { + "description": "An array of external property files containing run.taxonomies arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "addresses": { + "description": "An array of external property files containing run.addresses arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "driver": { + "description": "An external property file containing a run.driver object to be merged with the root log file.", + "$ref": "#/definitions/externalPropertyFileReference" + }, + + "extensions": { + "description": "An array of external property files containing run.extensions arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "policies": { + "description": "An array of external property files containing run.policies arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "translations": { + "description": "An array of external property files containing run.translations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "webRequests": { + "description": "An array of external property files containing run.requests arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "webResponses": { + "description": "An array of external property files containing run.responses arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/externalPropertyFileReference" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the external property files.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "fix": { + "description": "A proposed fix for the problem represented by a result object. A fix specifies a set of artifacts to modify. For each artifact, it specifies a set of bytes to remove, and provides a set of new bytes to replace them.", + "additionalProperties": false, + "type": "object", + "properties": { + + "description": { + "description": "A message that describes the proposed fix, enabling viewers to present the proposed change to an end user.", + "$ref": "#/definitions/message" + }, + + "artifactChanges": { + "description": "One or more artifact changes that comprise a fix for a result.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/artifactChange" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the fix.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "artifactChanges" ] + }, + + "graph": { + "description": "A network of nodes and directed edges that describes some aspect of the structure of the code (for example, a call graph).", + "type": "object", + "additionalProperties": false, + "properties": { + + "description": { + "description": "A description of the graph.", + "$ref": "#/definitions/message" + }, + + "nodes": { + "description": "An array of node objects representing the nodes of the graph.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/node" + } + }, + + "edges": { + "description": "An array of edge objects representing the edges of the graph.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/edge" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the graph.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "graphTraversal": { + "description": "Represents a path through a graph.", + "type": "object", + "additionalProperties": false, + "properties": { + + "runGraphIndex": { + "description": "The index within the run.graphs to be associated with the result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "resultGraphIndex": { + "description": "The index within the result.graphs to be associated with the result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "description": { + "description": "A description of this graph traversal.", + "$ref": "#/definitions/message" + }, + + "initialState": { + "description": "Values of relevant expressions at the start of the graph traversal that may change during graph traversal.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "immutableState": { + "description": "Values of relevant expressions at the start of the graph traversal that remain constant for the graph traversal.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "edgeTraversals": { + "description": "The sequences of edges traversed by this graph traversal.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/edgeTraversal" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the graph traversal.", + "$ref": "#/definitions/propertyBag" + } + }, + "oneOf": [ + { "required": [ "runGraphIndex" ] }, + { "required": [ "resultGraphIndex" ] } + ] + }, + + "invocation": { + "description": "The runtime environment of the analysis tool run.", + "additionalProperties": false, + "type": "object", + "properties": { + + "commandLine": { + "description": "The command line used to invoke the tool.", + "type": "string" + }, + + "arguments": { + "description": "An array of strings, containing in order the command line arguments passed to the tool from the operating system.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "items": { + "type": "string" + } + }, + + "responseFiles": { + "description": "The locations of any response files specified on the tool's command line.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/artifactLocation" + } + }, + + "startTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the invocation started. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + + "endTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the invocation ended. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + + "exitCode": { + "description": "The process exit code.", + "type": "integer" + }, + + "ruleConfigurationOverrides": { + "description": "An array of configurationOverride objects that describe rules related runtime overrides.", + "type": "array", + "minItems": 0, + "default": [], + "uniqueItems": true, + "items": { + "$ref": "#/definitions/configurationOverride" + } + }, + + "notificationConfigurationOverrides": { + "description": "An array of configurationOverride objects that describe notifications related runtime overrides.", + "type": "array", + "minItems": 0, + "default": [], + "uniqueItems": true, + "items": { + "$ref": "#/definitions/configurationOverride" + } + }, + + "toolExecutionNotifications": { + "description": "A list of runtime conditions detected by the tool during the analysis.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/notification" + } + }, + + "toolConfigurationNotifications": { + "description": "A list of conditions detected by the tool that are relevant to the tool's configuration.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/notification" + } + }, + + "exitCodeDescription": { + "description": "The reason for the process exit.", + "type": "string" + }, + + "exitSignalName": { + "description": "The name of the signal that caused the process to exit.", + "type": "string" + }, + + "exitSignalNumber": { + "description": "The numeric value of the signal that caused the process to exit.", + "type": "integer" + }, + + "processStartFailureMessage": { + "description": "The reason given by the operating system that the process failed to start.", + "type": "string" + }, + + "executionSuccessful": { + "description": "Specifies whether the tool's execution completed successfully.", + "type": "boolean" + }, + + "machine": { + "description": "The machine on which the invocation occurred.", + "type": "string" + }, + + "account": { + "description": "The account under which the invocation occurred.", + "type": "string" + }, + + "processId": { + "description": "The id of the process in which the invocation occurred.", + "type": "integer" + }, + + "executableLocation": { + "description": "An absolute URI specifying the location of the executable that was invoked.", + "$ref": "#/definitions/artifactLocation" + }, + + "workingDirectory": { + "description": "The working directory for the invocation.", + "$ref": "#/definitions/artifactLocation" + }, + + "environmentVariables": { + "description": "The environment variables associated with the analysis tool process, expressed as key/value pairs.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + + "stdin": { + "description": "A file containing the standard input stream to the process that was invoked.", + "$ref": "#/definitions/artifactLocation" + }, + + "stdout": { + "description": "A file containing the standard output stream from the process that was invoked.", + "$ref": "#/definitions/artifactLocation" + }, + + "stderr": { + "description": "A file containing the standard error stream from the process that was invoked.", + "$ref": "#/definitions/artifactLocation" + }, + + "stdoutStderr": { + "description": "A file containing the interleaved standard output and standard error stream from the process that was invoked.", + "$ref": "#/definitions/artifactLocation" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the invocation.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "executionSuccessful" ] + }, + + "location": { + "description": "A location within a programming artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + + "id": { + "description": "Value that distinguishes this location from all other locations within a single result object.", + "type": "integer", + "minimum": -1, + "default": -1 + }, + + "physicalLocation": { + "description": "Identifies the artifact and region.", + "$ref": "#/definitions/physicalLocation" + }, + + "logicalLocations": { + "description": "The logical locations associated with the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/logicalLocation" + } + }, + + "message": { + "description": "A message relevant to the location.", + "$ref": "#/definitions/message" + }, + + "annotations": { + "description": "A set of regions relevant to the location.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/region" + } + }, + + "relationships": { + "description": "An array of objects that describe relationships between this location and others.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/locationRelationship" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the location.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "locationRelationship": { + "description": "Information about the relation of one location to another.", + "type": "object", + "additionalProperties": false, + "properties": { + + "target": { + "description": "A reference to the related location.", + "type": "integer", + "minimum": 0 + }, + + "kinds": { + "description": "A set of distinct strings that categorize the relationship. Well-known kinds include 'includes', 'isIncludedBy' and 'relevant'.", + "type": "array", + "default": [ "relevant" ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + + "description": { + "description": "A description of the location relationship.", + "$ref": "#/definitions/message" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the location relationship.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "target" ] + }, + + "logicalLocation": { + "description": "A logical location of a construct that produced a result.", + "additionalProperties": false, + "type": "object", + "properties": { + + "name": { + "description": "Identifies the construct in which the result occurred. For example, this property might contain the name of a class or a method.", + "type": "string" + }, + + "index": { + "description": "The index within the logical locations array.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "fullyQualifiedName": { + "description": "The human-readable fully qualified name of the logical location.", + "type": "string" + }, + + "decoratedName": { + "description": "The machine-readable name for the logical location, such as a mangled function name provided by a C++ compiler that encodes calling convention, return type and other details along with the function name.", + "type": "string" + }, + + "parentIndex": { + "description": "Identifies the index of the immediate parent of the construct in which the result was detected. For example, this property might point to a logical location that represents the namespace that holds a type.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "kind": { + "description": "The type of construct this logical location component refers to. Should be one of 'function', 'member', 'module', 'namespace', 'parameter', 'resource', 'returnType', 'type', 'variable', 'object', 'array', 'property', 'value', 'element', 'text', 'attribute', 'comment', 'declaration', 'dtd' or 'processingInstruction', if any of those accurately describe the construct.", + "type": "string" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the logical location.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "message": { + "description": "Encapsulates a message intended to be read by the end user.", + "type": "object", + "additionalProperties": false, + + "properties": { + + "text": { + "description": "A plain text message string.", + "type": "string" + }, + + "markdown": { + "description": "A Markdown message string.", + "type": "string" + }, + + "id": { + "description": "The identifier for this message.", + "type": "string" + }, + + "arguments": { + "description": "An array of strings to substitute into the message string.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "type": "string" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the message.", + "$ref": "#/definitions/propertyBag" + } + }, + "anyOf": [ + { "required": [ "text" ] }, + { "required": [ "id" ] } + ] + }, + + "multiformatMessageString": { + "description": "A message string or message format string rendered in multiple formats.", + "type": "object", + "additionalProperties": false, + + "properties": { + + "text": { + "description": "A plain text message string or format string.", + "type": "string" + }, + + "markdown": { + "description": "A Markdown message string or format string.", + "type": "string" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the message.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "text" ] + }, + + "node": { + "description": "Represents a node in a graph.", + "type": "object", + "additionalProperties": false, + + "properties": { + + "id": { + "description": "A string that uniquely identifies the node within its graph.", + "type": "string" + }, + + "label": { + "description": "A short description of the node.", + "$ref": "#/definitions/message" + }, + + "location": { + "description": "A code location associated with the node.", + "$ref": "#/definitions/location" + }, + + "children": { + "description": "Array of child nodes.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/node" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the node.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "id" ] + }, + + "notification": { + "description": "Describes a condition relevant to the tool itself, as opposed to being relevant to a target being analyzed by the tool.", + "type": "object", + "additionalProperties": false, + "properties": { + + "locations": { + "description": "The locations relevant to this notification.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/location" + } + }, + + "message": { + "description": "A message that describes the condition that was encountered.", + "$ref": "#/definitions/message" + }, + + "level": { + "description": "A value specifying the severity level of the notification.", + "default": "warning", + "enum": [ "none", "note", "warning", "error" ], + "type": "string" + }, + + "threadId": { + "description": "The thread identifier of the code that generated the notification.", + "type": "integer" + }, + + "timeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the analysis tool generated the notification.", + "type": "string", + "format": "date-time" + }, + + "exception": { + "description": "The runtime exception, if any, relevant to this notification.", + "$ref": "#/definitions/exception" + }, + + "descriptor": { + "description": "A reference used to locate the descriptor relevant to this notification.", + "$ref": "#/definitions/reportingDescriptorReference" + }, + + "associatedRule": { + "description": "A reference used to locate the rule descriptor associated with this notification.", + "$ref": "#/definitions/reportingDescriptorReference" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the notification.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "message" ] + }, + + "physicalLocation": { + "description": "A physical location relevant to a result. Specifies a reference to a programming artifact together with a range of bytes or characters within that artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + + "address": { + "description": "The address of the location.", + "$ref": "#/definitions/address" + }, + + "artifactLocation": { + "description": "The location of the artifact.", + "$ref": "#/definitions/artifactLocation" + }, + + "region": { + "description": "Specifies a portion of the artifact.", + "$ref": "#/definitions/region" + }, + + "contextRegion": { + "description": "Specifies a portion of the artifact that encloses the region. Allows a viewer to display additional context around the region.", + "$ref": "#/definitions/region" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the physical location.", + "$ref": "#/definitions/propertyBag" + } + }, + + "anyOf": [ + { + "required": [ "address" ] + }, + { + "required": [ "artifactLocation" ] + } + ] + }, + + "propertyBag": { + "description": "Key/value pairs that provide additional information about the object.", + "type": "object", + "additionalProperties": true, + "properties": { + "tags": { + + "description": "A set of distinct strings that provide additional information.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "type": "string" + } + } + } + }, + + "rectangle": { + "description": "An area within an image.", + "additionalProperties": false, + "type": "object", + "properties": { + + "top": { + "description": "The Y coordinate of the top edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + + "left": { + "description": "The X coordinate of the left edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + + "bottom": { + "description": "The Y coordinate of the bottom edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + + "right": { + "description": "The X coordinate of the right edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + + "message": { + "description": "A message relevant to the rectangle.", + "$ref": "#/definitions/message" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the rectangle.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "region": { + "description": "A region within an artifact where a result was detected.", + "additionalProperties": false, + "type": "object", + "properties": { + + "startLine": { + "description": "The line number of the first character in the region.", + "type": "integer", + "minimum": 1 + }, + + "startColumn": { + "description": "The column number of the first character in the region.", + "type": "integer", + "minimum": 1 + }, + + "endLine": { + "description": "The line number of the last character in the region.", + "type": "integer", + "minimum": 1 + }, + + "endColumn": { + "description": "The column number of the character following the end of the region.", + "type": "integer", + "minimum": 1 + }, + + "charOffset": { + "description": "The zero-based offset from the beginning of the artifact of the first character in the region.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "charLength": { + "description": "The length of the region in characters.", + "type": "integer", + "minimum": 0 + }, + + "byteOffset": { + "description": "The zero-based offset from the beginning of the artifact of the first byte in the region.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "byteLength": { + "description": "The length of the region in bytes.", + "type": "integer", + "minimum": 0 + }, + + "snippet": { + "description": "The portion of the artifact contents within the specified region.", + "$ref": "#/definitions/artifactContent" + }, + + "message": { + "description": "A message relevant to the region.", + "$ref": "#/definitions/message" + }, + + "sourceLanguage": { + "description": "Specifies the source language, if any, of the portion of the artifact specified by the region object.", + "type": "string" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the region.", + "$ref": "#/definitions/propertyBag" + } + }, + + "anyOf": [ + { "required": [ "startLine" ] }, + { "required": [ "charOffset" ] }, + { "required": [ "byteOffset" ] } + ] + }, + + "replacement": { + "description": "The replacement of a single region of an artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + + "deletedRegion": { + "description": "The region of the artifact to delete.", + "$ref": "#/definitions/region" + }, + + "insertedContent": { + "description": "The content to insert at the location specified by the 'deletedRegion' property.", + "$ref": "#/definitions/artifactContent" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the replacement.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "deletedRegion" ] + }, + + "reportingDescriptor": { + "description": "Metadata that describes a specific report produced by the tool, as part of the analysis it provides or its runtime reporting.", + "additionalProperties": false, + "type": "object", + "properties": { + + "id": { + "description": "A stable, opaque identifier for the report.", + "type": "string" + }, + + "deprecatedIds": { + "description": "An array of stable, opaque identifiers by which this report was known in some previous version of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string" + } + }, + + "guid": { + "description": "A unique identifier for the reporting descriptor in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "deprecatedGuids": { + "description": "An array of unique identifies in the form of a GUID by which this report was known in some previous version of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + } + }, + + "name": { + "description": "A report identifier that is understandable to an end user.", + "type": "string" + }, + + "deprecatedNames": { + "description": "An array of readable identifiers by which this report was known in some previous version of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string" + } + }, + + "shortDescription": { + "description": "A concise description of the report. Should be a single sentence that is understandable when visible space is limited to a single line of text.", + "$ref": "#/definitions/multiformatMessageString" + }, + + "fullDescription": { + "description": "A description of the report. Should, as far as possible, provide details sufficient to enable resolution of any problem indicated by the result.", + "$ref": "#/definitions/multiformatMessageString" + }, + + "messageStrings": { + "description": "A set of name/value pairs with arbitrary names. Each value is a multiformatMessageString object, which holds message strings in plain text and (optionally) Markdown format. The strings can include placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "defaultConfiguration": { + "description": "Default reporting configuration information.", + "$ref": "#/definitions/reportingConfiguration" + }, + + "helpUri": { + "description": "A URI where the primary documentation for the report can be found.", + "type": "string", + "format": "uri" + }, + + "help": { + "description": "Provides the primary documentation for the report, useful when there is no online documentation.", + "$ref": "#/definitions/multiformatMessageString" + }, + + "relationships": { + "description": "An array of objects that describe relationships between this reporting descriptor and others.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/reportingDescriptorRelationship" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the report.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "id" ] + }, + + "reportingConfiguration": { + "description": "Information about a rule or notification that can be configured at runtime.", + "type": "object", + "additionalProperties": false, + "properties": { + + "enabled": { + "description": "Specifies whether the report may be produced during the scan.", + "type": "boolean", + "default": true + }, + + "level": { + "description": "Specifies the failure level for the report.", + "default": "warning", + "enum": [ "none", "note", "warning", "error" ], + "type": "string" + }, + + "rank": { + "description": "Specifies the relative priority of the report. Used for analysis output only.", + "type": "number", + "default": -1.0, + "minimum": -1.0, + "maximum": 100.0 + }, + + "parameters": { + "description": "Contains configuration information specific to a report.", + "$ref": "#/definitions/propertyBag" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the reporting configuration.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "reportingDescriptorReference": { + "description": "Information about how to locate a relevant reporting descriptor.", + "type": "object", + "additionalProperties": false, + "properties": { + + "id": { + "description": "The id of the descriptor.", + "type": "string" + }, + + "index": { + "description": "The index into an array of descriptors in toolComponent.ruleDescriptors, toolComponent.notificationDescriptors, or toolComponent.taxonomyDescriptors, depending on context.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "guid": { + "description": "A guid that uniquely identifies the descriptor.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "toolComponent": { + "description": "A reference used to locate the toolComponent associated with the descriptor.", + "$ref": "#/definitions/toolComponentReference" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the reporting descriptor reference.", + "$ref": "#/definitions/propertyBag" + } + }, + "anyOf": [ + { "required": [ "index" ] }, + { "required": [ "guid" ] }, + { "required": [ "id" ] } + ] + }, + + "reportingDescriptorRelationship": { + "description": "Information about the relation of one reporting descriptor to another.", + "type": "object", + "additionalProperties": false, + "properties": { + + "target": { + "description": "A reference to the related reporting descriptor.", + "$ref": "#/definitions/reportingDescriptorReference" + }, + + "kinds": { + "description": "A set of distinct strings that categorize the relationship. Well-known kinds include 'canPrecede', 'canFollow', 'willPrecede', 'willFollow', 'superset', 'subset', 'equal', 'disjoint', 'relevant', and 'incomparable'.", + "type": "array", + "default": [ "relevant" ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + + "description": { + "description": "A description of the reporting descriptor relationship.", + "$ref": "#/definitions/message" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the reporting descriptor reference.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "target" ] + }, + + "result": { + "description": "A result produced by an analysis tool.", + "additionalProperties": false, + "type": "object", + "properties": { + + "ruleId": { + "description": "The stable, unique identifier of the rule, if any, to which this result is relevant.", + "type": "string" + }, + + "ruleIndex": { + "description": "The index within the tool component rules array of the rule object associated with this result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "rule": { + "description": "A reference used to locate the rule descriptor relevant to this result.", + "$ref": "#/definitions/reportingDescriptorReference" + }, + + "kind": { + "description": "A value that categorizes results by evaluation state.", + "default": "fail", + "enum": [ "notApplicable", "pass", "fail", "review", "open", "informational" ], + "type": "string" + }, + + "level": { + "description": "A value specifying the severity level of the result.", + "default": "warning", + "enum": [ "none", "note", "warning", "error" ], + "type": "string" + }, + + "message": { + "description": "A message that describes the result. The first sentence of the message only will be displayed when visible space is limited.", + "$ref": "#/definitions/message" + }, + + "analysisTarget": { + "description": "Identifies the artifact that the analysis tool was instructed to scan. This need not be the same as the artifact where the result actually occurred.", + "$ref": "#/definitions/artifactLocation" + }, + + "locations": { + "description": "The set of locations where the result was detected. Specify only one location unless the problem indicated by the result can only be corrected by making a change at every specified location.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/location" + } + }, + + "guid": { + "description": "A stable, unique identifier for the result in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "correlationGuid": { + "description": "A stable, unique identifier for the equivalence class of logically identical results to which this result belongs, in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "occurrenceCount": { + "description": "A positive integer specifying the number of times this logically unique result was observed in this run.", + "type": "integer", + "minimum": 1 + }, + + "partialFingerprints": { + "description": "A set of strings that contribute to the stable, unique identity of the result.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + + "fingerprints": { + "description": "A set of strings each of which individually defines a stable, unique identity for the result.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + + "stacks": { + "description": "An array of 'stack' objects relevant to the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/stack" + } + }, + + "codeFlows": { + "description": "An array of 'codeFlow' objects relevant to the result.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/codeFlow" + } + }, + + "graphs": { + "description": "An array of zero or more unique graph objects associated with the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/graph" + } + }, + + "graphTraversals": { + "description": "An array of one or more unique 'graphTraversal' objects.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/graphTraversal" + } + }, + + "relatedLocations": { + "description": "A set of locations relevant to this result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/location" + } + }, + + "suppressions": { + "description": "A set of suppressions relevant to this result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/suppression" + } + }, + + "baselineState": { + "description": "The state of a result relative to a baseline of a previous run.", + "enum": [ + "new", + "unchanged", + "updated", + "absent" + ], + "type": "string" + }, + + "rank": { + "description": "A number representing the priority or importance of the result.", + "type": "number", + "default": -1.0, + "minimum": -1.0, + "maximum": 100.0 + }, + + "attachments": { + "description": "A set of artifacts relevant to the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/attachment" + } + }, + + "hostedViewerUri": { + "description": "An absolute URI at which the result can be viewed.", + "type": "string", + "format": "uri" + }, + + "workItemUris": { + "description": "The URIs of the work items associated with this result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string", + "format": "uri" + } + }, + + "provenance": { + "description": "Information about how and when the result was detected.", + "$ref": "#/definitions/resultProvenance" + }, + + "fixes": { + "description": "An array of 'fix' objects, each of which represents a proposed fix to the problem indicated by the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/fix" + } + }, + + "taxa": { + "description": "An array of references to taxonomy reporting descriptors that are applicable to the result.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/reportingDescriptorReference" + } + }, + + "webRequest": { + "description": "A web request associated with this result.", + "$ref": "#/definitions/webRequest" + }, + + "webResponse": { + "description": "A web response associated with this result.", + "$ref": "#/definitions/webResponse" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the result.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "message" ] + }, + + "resultProvenance": { + "description": "Contains information about how and when a result was detected.", + "additionalProperties": false, + "type": "object", + "properties": { + + "firstDetectionTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the result was first detected. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + + "lastDetectionTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the result was most recently detected. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + + "firstDetectionRunGuid": { + "description": "A GUID-valued string equal to the automationDetails.guid property of the run in which the result was first detected.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "lastDetectionRunGuid": { + "description": "A GUID-valued string equal to the automationDetails.guid property of the run in which the result was most recently detected.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "invocationIndex": { + "description": "The index within the run.invocations array of the invocation object which describes the tool invocation that detected the result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "conversionSources": { + "description": "An array of physicalLocation objects which specify the portions of an analysis tool's output that a converter transformed into the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/physicalLocation" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the result.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "run": { + "description": "Describes a single run of an analysis tool, and contains the reported output of that run.", + "additionalProperties": false, + "type": "object", + "properties": { + + "tool": { + "description": "Information about the tool or tool pipeline that generated the results in this run. A run can only contain results produced by a single tool or tool pipeline. A run can aggregate results from multiple log files, as long as context around the tool run (tool command-line arguments and the like) is identical for all aggregated files.", + "$ref": "#/definitions/tool" + }, + + "invocations": { + "description": "Describes the invocation of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/invocation" + } + }, + + "conversion": { + "description": "A conversion object that describes how a converter transformed an analysis tool's native reporting format into the SARIF format.", + "$ref": "#/definitions/conversion" + }, + + "language": { + "description": "The language of the messages emitted into the log file during this run (expressed as an ISO 639-1 two-letter lowercase culture code) and an optional region (expressed as an ISO 3166-1 two-letter uppercase subculture code associated with a country or region). The casing is recommended but not required (in order for this data to conform to RFC5646).", + "type": "string", + "default": "en-US", + "pattern": "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$" + }, + + "versionControlProvenance": { + "description": "Specifies the revision in version control of the artifacts that were scanned.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/versionControlDetails" + } + }, + + "originalUriBaseIds": { + "description": "The artifact location specified by each uriBaseId symbol on the machine where the tool originally ran.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/artifactLocation" + } + }, + + "artifacts": { + "description": "An array of artifact objects relevant to the run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/artifact" + } + }, + + "logicalLocations": { + "description": "An array of logical locations such as namespaces, types or functions.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/logicalLocation" + } + }, + + "graphs": { + "description": "An array of zero or more unique graph objects associated with the run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/graph" + } + }, + + "results": { + "description": "The set of results contained in an SARIF log. The results array can be omitted when a run is solely exporting rules metadata. It must be present (but may be empty) if a log file represents an actual scan.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "items": { + "$ref": "#/definitions/result" + } + }, + + "automationDetails": { + "description": "Automation details that describe this run.", + "$ref": "#/definitions/runAutomationDetails" + }, + + "runAggregates": { + "description": "Automation details that describe the aggregate of runs to which this run belongs.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/runAutomationDetails" + } + }, + + "baselineGuid": { + "description": "The 'guid' property of a previous SARIF 'run' that comprises the baseline that was used to compute result 'baselineState' properties for the run.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "redactionTokens": { + "description": "An array of strings used to replace sensitive information in a redaction-aware property.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "type": "string" + } + }, + + "defaultEncoding": { + "description": "Specifies the default encoding for any artifact object that refers to a text file.", + "type": "string" + }, + + "defaultSourceLanguage": { + "description": "Specifies the default source language for any artifact object that refers to a text file that contains source code.", + "type": "string" + }, + + "newlineSequences": { + "description": "An ordered list of character sequences that were treated as line breaks when computing region information for the run.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "default": [ "\r\n", "\n" ], + "items": { + "type": "string" + } + }, + + "columnKind": { + "description": "Specifies the unit in which the tool measures columns.", + "enum": [ "utf16CodeUnits", "unicodeCodePoints" ], + "type": "string" + }, + + "externalPropertyFileReferences": { + "description": "References to external property files that should be inlined with the content of a root log file.", + "$ref": "#/definitions/externalPropertyFileReferences" + }, + + "threadFlowLocations": { + "description": "An array of threadFlowLocation objects cached at run level.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/threadFlowLocation" + } + }, + + "taxonomies": { + "description": "An array of toolComponent objects relevant to a taxonomy in which results are categorized.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "addresses": { + "description": "Addresses associated with this run instance, if any.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/definitions/address" + } + }, + + "translations": { + "description": "The set of available translations of the localized data provided by the tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "policies": { + "description": "Contains configurations that may potentially override both reportingDescriptor.defaultConfiguration (the tool's default severities) and invocation.configurationOverrides (severities established at run-time from the command line).", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "webRequests": { + "description": "An array of request objects cached at run level.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/webRequest" + } + }, + + "webResponses": { + "description": "An array of response objects cached at run level.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/webResponse" + } + }, + + "specialLocations": { + "description": "A specialLocations object that defines locations of special significance to SARIF consumers.", + "$ref": "#/definitions/specialLocations" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the run.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "tool" ] + }, + + "runAutomationDetails": { + "description": "Information that describes a run's identity and role within an engineering system process.", + "additionalProperties": false, + "type": "object", + "properties": { + + "description": { + "description": "A description of the identity and role played within the engineering system by this object's containing run object.", + "$ref": "#/definitions/message" + }, + + "id": { + "description": "A hierarchical string that uniquely identifies this object's containing run object.", + "type": "string" + }, + + "guid": { + "description": "A stable, unique identifier for this object's containing run object in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "correlationGuid": { + "description": "A stable, unique identifier for the equivalence class of runs to which this object's containing run object belongs in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the run automation details.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "specialLocations": { + "description": "Defines locations of special significance to SARIF consumers.", + "type": "object", + "additionalProperties": false, + "properties": { + + "displayBase": { + "description": "Provides a suggestion to SARIF consumers to display file paths relative to the specified location.", + "$ref": "#/definitions/artifactLocation" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the special locations.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "stack": { + "description": "A call stack that is relevant to a result.", + "additionalProperties": false, + "type": "object", + "properties": { + + "message": { + "description": "A message relevant to this call stack.", + "$ref": "#/definitions/message" + }, + + "frames": { + "description": "An array of stack frames that represents a sequence of calls, rendered in reverse chronological order, that comprise the call stack.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "items": { + "$ref": "#/definitions/stackFrame" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the stack.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "frames" ] + }, + + "stackFrame": { + "description": "A function call within a stack trace.", + "additionalProperties": false, + "type": "object", + "properties": { + + "location": { + "description": "The location to which this stack frame refers.", + "$ref": "#/definitions/location" + }, + + "module": { + "description": "The name of the module that contains the code of this stack frame.", + "type": "string" + }, + + "threadId": { + "description": "The thread identifier of the stack frame.", + "type": "integer" + }, + + "parameters": { + "description": "The parameters of the call that is executing.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "type": "string", + "default": [] + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the stack frame.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "suppression": { + "description": "A suppression that is relevant to a result.", + "additionalProperties": false, + "type": "object", + "properties": { + + "guid": { + "description": "A stable, unique identifier for the suprression in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "kind": { + "description": "A string that indicates where the suppression is persisted.", + "enum": [ + "inSource", + "external" + ], + "type": "string" + }, + + "status": { + "description": "A string that indicates the review status of the suppression.", + "enum": [ + "accepted", + "underReview", + "rejected" + ], + "type": "string" + }, + + "justification": { + "description": "A string representing the justification for the suppression.", + "type": "string" + }, + + "location": { + "description": "Identifies the location associated with the suppression.", + "$ref": "#/definitions/location" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the suppression.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "kind" ] + }, + + "threadFlow": { + "description": "Describes a sequence of code locations that specify a path through a single thread of execution such as an operating system or fiber.", + "type": "object", + "additionalProperties": false, + "properties": { + + "id": { + "description": "An string that uniquely identifies the threadFlow within the codeFlow in which it occurs.", + "type": "string" + }, + + "message": { + "description": "A message relevant to the thread flow.", + "$ref": "#/definitions/message" + }, + + + "initialState": { + "description": "Values of relevant expressions at the start of the thread flow that may change during thread flow execution.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "immutableState": { + "description": "Values of relevant expressions at the start of the thread flow that remain constant.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "locations": { + "description": "A temporally ordered array of 'threadFlowLocation' objects, each of which describes a location visited by the tool while producing the result.", + "type": "array", + "minItems": 1, + "uniqueItems": false, + "items": { + "$ref": "#/definitions/threadFlowLocation" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the thread flow.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "locations" ] + }, + + "threadFlowLocation": { + "description": "A location visited by an analysis tool while simulating or monitoring the execution of a program.", + "additionalProperties": false, + "type": "object", + "properties": { + + "index": { + "description": "The index within the run threadFlowLocations array.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "location": { + "description": "The code location.", + "$ref": "#/definitions/location" + }, + + "stack": { + "description": "The call stack leading to this location.", + "$ref": "#/definitions/stack" + }, + + "kinds": { + "description": "A set of distinct strings that categorize the thread flow location. Well-known kinds include 'acquire', 'release', 'enter', 'exit', 'call', 'return', 'branch', 'implicit', 'false', 'true', 'caution', 'danger', 'unknown', 'unreachable', 'taint', 'function', 'handler', 'lock', 'memory', 'resource', 'scope' and 'value'.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "type": "string" + } + }, + + "taxa": { + "description": "An array of references to rule or taxonomy reporting descriptors that are applicable to the thread flow location.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/definitions/reportingDescriptorReference" + } + }, + + "module": { + "description": "The name of the module that contains the code that is executing.", + "type": "string" + }, + + "state": { + "description": "A dictionary, each of whose keys specifies a variable or expression, the associated value of which represents the variable or expression value. For an annotation of kind 'continuation', for example, this dictionary might hold the current assumed values of a set of global variables.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "nestingLevel": { + "description": "An integer representing a containment hierarchy within the thread flow.", + "type": "integer", + "minimum": 0 + }, + + "executionOrder": { + "description": "An integer representing the temporal order in which execution reached this location.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "executionTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which this location was executed.", + "type": "string", + "format": "date-time" + }, + + "importance": { + "description": "Specifies the importance of this location in understanding the code flow in which it occurs. The order from most to least important is \"essential\", \"important\", \"unimportant\". Default: \"important\".", + "enum": [ "important", "essential", "unimportant" ], + "default": "important", + "type": "string" + }, + + "webRequest": { + "description": "A web request associated with this thread flow location.", + "$ref": "#/definitions/webRequest" + }, + + "webResponse": { + "description": "A web response associated with this thread flow location.", + "$ref": "#/definitions/webResponse" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the threadflow location.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "tool": { + "description": "The analysis tool that was run.", + "additionalProperties": false, + "type": "object", + "properties": { + + "driver": { + "description": "The analysis tool that was run.", + "$ref": "#/definitions/toolComponent" + }, + + "extensions": { + "description": "Tool extensions that contributed to or reconfigured the analysis tool that was run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponent" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the tool.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "driver" ] + }, + + "toolComponent": { + "description": "A component, such as a plug-in or the driver, of the analysis tool that was run.", + "additionalProperties": false, + "type": "object", + "properties": { + + "guid": { + "description": "A unique identifier for the tool component in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "name": { + "description": "The name of the tool component.", + "type": "string" + }, + + "organization": { + "description": "The organization or company that produced the tool component.", + "type": "string" + }, + + "product": { + "description": "A product suite to which the tool component belongs.", + "type": "string" + }, + + "productSuite": { + "description": "A localizable string containing the name of the suite of products to which the tool component belongs.", + "type": "string" + }, + + "shortDescription": { + "description": "A brief description of the tool component.", + "$ref": "#/definitions/multiformatMessageString" + }, + + "fullDescription": { + "description": "A comprehensive description of the tool component.", + "$ref": "#/definitions/multiformatMessageString" + }, + + "fullName": { + "description": "The name of the tool component along with its version and any other useful identifying information, such as its locale.", + "type": "string" + }, + + "version": { + "description": "The tool component version, in whatever format the component natively provides.", + "type": "string" + }, + + "semanticVersion": { + "description": "The tool component version in the format specified by Semantic Versioning 2.0.", + "type": "string" + }, + + "dottedQuadFileVersion": { + "description": "The binary version of the tool component's primary executable file expressed as four non-negative integers separated by a period (for operating systems that express file versions in this way).", + "type": "string", + "pattern": "[0-9]+(\\.[0-9]+){3}" + }, + + "releaseDateUtc": { + "description": "A string specifying the UTC date (and optionally, the time) of the component's release.", + "type": "string" + }, + + "downloadUri": { + "description": "The absolute URI from which the tool component can be downloaded.", + "type": "string", + "format": "uri" + }, + + "informationUri": { + "description": "The absolute URI at which information about this version of the tool component can be found.", + "type": "string", + "format": "uri" + }, + + "globalMessageStrings": { + "description": "A dictionary, each of whose keys is a resource identifier and each of whose values is a multiformatMessageString object, which holds message strings in plain text and (optionally) Markdown format. The strings can include placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/multiformatMessageString" + } + }, + + "notifications": { + "description": "An array of reportingDescriptor objects relevant to the notifications related to the configuration and runtime execution of the tool component.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/reportingDescriptor" + } + }, + + "rules": { + "description": "An array of reportingDescriptor objects relevant to the analysis performed by the tool component.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/reportingDescriptor" + } + }, + + "taxa": { + "description": "An array of reportingDescriptor objects relevant to the definitions of both standalone and tool-defined taxonomies.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/reportingDescriptor" + } + }, + + "locations": { + "description": "An array of the artifactLocation objects associated with the tool component.", + "type": "array", + "minItems": 0, + "default": [], + "items": { + "$ref": "#/definitions/artifactLocation" + } + }, + + "language": { + "description": "The language of the messages emitted into the log file during this run (expressed as an ISO 639-1 two-letter lowercase language code) and an optional region (expressed as an ISO 3166-1 two-letter uppercase subculture code associated with a country or region). The casing is recommended but not required (in order for this data to conform to RFC5646).", + "type": "string", + "default": "en-US", + "pattern": "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$" + }, + + "contents": { + "description": "The kinds of data contained in this object.", + "type": "array", + "uniqueItems": true, + "default": [ "localizedData", "nonLocalizedData" ], + "items": { + "enum": [ + "localizedData", + "nonLocalizedData" + ], + "type": "string" + } + }, + + "isComprehensive": { + "description": "Specifies whether this object contains a complete definition of the localizable and/or non-localizable data for this component, as opposed to including only data that is relevant to the results persisted to this log file.", + "type": "boolean", + "default": false + }, + + "localizedDataSemanticVersion": { + "description": "The semantic version of the localized strings defined in this component; maintained by components that provide translations.", + "type": "string" + }, + + "minimumRequiredLocalizedDataSemanticVersion": { + "description": "The minimum value of localizedDataSemanticVersion required in translations consumed by this component; used by components that consume translations.", + "type": "string" + }, + + "associatedComponent": { + "description": "The component which is strongly associated with this component. For a translation, this refers to the component which has been translated. For an extension, this is the driver that provides the extension's plugin model.", + "$ref": "#/definitions/toolComponentReference" + }, + + "translationMetadata": { + "description": "Translation metadata, required for a translation, not populated by other component types.", + "$ref": "#/definitions/translationMetadata" + }, + + "supportedTaxonomies": { + "description": "An array of toolComponentReference objects to declare the taxonomies supported by the tool component.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/definitions/toolComponentReference" + } + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the tool component.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "name" ] + }, + + "toolComponentReference": { + "description": "Identifies a particular toolComponent object, either the driver or an extension.", + "type": "object", + "additionalProperties": false, + "properties": { + + "name": { + "description": "The 'name' property of the referenced toolComponent.", + "type": "string" + }, + + "index": { + "description": "An index into the referenced toolComponent in tool.extensions.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "guid": { + "description": "The 'guid' property of the referenced toolComponent.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the toolComponentReference.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "translationMetadata": { + "description": "Provides additional metadata related to translation.", + "type": "object", + "additionalProperties": false, + "properties": { + + "name": { + "description": "The name associated with the translation metadata.", + "type": "string" + }, + + "fullName": { + "description": "The full name associated with the translation metadata.", + "type": "string" + }, + + "shortDescription": { + "description": "A brief description of the translation metadata.", + "$ref": "#/definitions/multiformatMessageString" + }, + + "fullDescription": { + "description": "A comprehensive description of the translation metadata.", + "$ref": "#/definitions/multiformatMessageString" + }, + + "downloadUri": { + "description": "The absolute URI from which the translation metadata can be downloaded.", + "type": "string", + "format": "uri" + }, + + "informationUri": { + "description": "The absolute URI from which information related to the translation metadata can be downloaded.", + "type": "string", + "format": "uri" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the translation metadata.", + "$ref": "#/definitions/propertyBag" + } + }, + "required": [ "name" ] + }, + + "versionControlDetails": { + "description": "Specifies the information necessary to retrieve a desired revision from a version control system.", + "type": "object", + "additionalProperties": false, + "properties": { + + "repositoryUri": { + "description": "The absolute URI of the repository.", + "type": "string", + "format": "uri" + }, + + "revisionId": { + "description": "A string that uniquely and permanently identifies the revision within the repository.", + "type": "string" + }, + + "branch": { + "description": "The name of a branch containing the revision.", + "type": "string" + }, + + "revisionTag": { + "description": "A tag that has been applied to the revision.", + "type": "string" + }, + + "asOfTimeUtc": { + "description": "A Coordinated Universal Time (UTC) date and time that can be used to synchronize an enlistment to the state of the repository at that time.", + "type": "string", + "format": "date-time" + }, + + "mappedTo": { + "description": "The location in the local file system to which the root of the repository was mapped at the time of the analysis.", + "$ref": "#/definitions/artifactLocation" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the version control details.", + "$ref": "#/definitions/propertyBag" + } + }, + + "required": [ "repositoryUri" ] + }, + + "webRequest": { + "description": "Describes an HTTP request.", + "type": "object", + "additionalProperties": false, + "properties": { + + "index": { + "description": "The index within the run.webRequests array of the request object associated with this result.", + "type": "integer", + "default": -1, + "minimum": -1 + + }, + + "protocol": { + "description": "The request protocol. Example: 'http'.", + "type": "string" + }, + + "version": { + "description": "The request version. Example: '1.1'.", + "type": "string" + }, + + "target": { + "description": "The target of the request.", + "type": "string" + }, + + "method": { + "description": "The HTTP method. Well-known values are 'GET', 'PUT', 'POST', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT'.", + "type": "string" + }, + + "headers": { + "description": "The request headers.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + + "parameters": { + "description": "The request parameters.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + + "body": { + "description": "The body of the request.", + "$ref": "#/definitions/artifactContent" + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the request.", + "$ref": "#/definitions/propertyBag" + } + } + }, + + "webResponse": { + "description": "Describes the response to an HTTP request.", + "type": "object", + "additionalProperties": false, + "properties": { + + "index": { + "description": "The index within the run.webResponses array of the response object associated with this result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + + "protocol": { + "description": "The response protocol. Example: 'http'.", + "type": "string" + }, + + "version": { + "description": "The response version. Example: '1.1'.", + "type": "string" + }, + + "statusCode": { + "description": "The response status code. Example: 451.", + "type": "integer" + }, + + "reasonPhrase": { + "description": "The response reason. Example: 'Not found'.", + "type": "string" + }, + + "headers": { + "description": "The response headers.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + + "body": { + "description": "The body of the response.", + "$ref": "#/definitions/artifactContent" + }, + + "noResponseReceived": { + "description": "Specifies whether a response was received from the server.", + "type": "boolean", + "default": false + }, + + "properties": { + "description": "Key/value pairs that provide additional information about the response.", + "$ref": "#/definitions/propertyBag" + } + } + } + } +} \ No newline at end of file diff --git a/sarif/spec/contracts/sarif-schema/v2-2-0/schema.json b/sarif/spec/contracts/sarif-schema/v2-2-0/schema.json new file mode 100644 index 0000000..1046496 --- /dev/null +++ b/sarif/spec/contracts/sarif-schema/v2-2-0/schema.json @@ -0,0 +1,3058 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Static Analysis Results Format (SARIF) Version 2.2 JSON Schema", + "$id": "https://docs.oasis-open.org/sarif/sarif/v2.2/schemas/sarif-2.2.schema.json", + "description": "Static Analysis Results Format (SARIF) Version 2.2 JSON Schema: a standard format for the output of static analysis tools.", + "additionalProperties": false, + "type": "object", + "properties": { + "$schema": { + "description": "The URI of the JSON schema corresponding to the version.", + "type": "string", + "format": "uri" + }, + "version": { + "description": "The SARIF format version of this log file.", + "enum": [ + "2.2" + ], + "type": "string" + }, + "runs": { + "description": "The set of runs contained in this log file.", + "type": [ + "array", + "null" + ], + "minItems": 0, + "uniqueItems": false, + "items": { + "$ref": "#/$defs/run" + } + }, + "inlineExternalProperties": { + "description": "References to external property files that share data between runs.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/externalProperties" + } + }, + "guid": { + "description": "A stable, unique identifier for the external property file in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the log file.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "version", + "runs" + ], + "$defs": { + "address": { + "description": "A physical or virtual address, or a range of addresses, in an 'addressable region' (memory or a binary file).", + "additionalProperties": false, + "type": "object", + "properties": { + "absoluteAddress": { + "description": "The address expressed as a byte offset from the start of the addressable region.", + "type": "integer", + "minimum": -1, + "default": -1 + }, + "relativeAddress": { + "description": "The address expressed as a byte offset from the absolute address of the top-most parent object.", + "type": "integer" + }, + "length": { + "description": "The number of bytes in this range of addresses.", + "type": "integer" + }, + "kind": { + "description": "An open-ended string that identifies the address kind. 'data', 'function', 'header','instruction', 'module', 'page', 'section', 'segment', 'stack', 'stackFrame', 'table' are well-known values.", + "type": "string" + }, + "name": { + "description": "A name that is associated with the address, e.g., '.text'.", + "type": "string" + }, + "fullyQualifiedName": { + "description": "A human-readable fully qualified name that is associated with the address.", + "type": "string" + }, + "offsetFromParent": { + "description": "The byte offset of this address from the absolute or relative address of the parent object.", + "type": "integer" + }, + "index": { + "description": "The index within run.addresses of the cached object for this address.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "parentIndex": { + "description": "The index within run.addresses of the parent object.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "properties": { + "description": "Key/value pairs that provide additional information about the address.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "artifact": { + "description": "A single artifact. In some cases, this artifact might be nested within another artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + "description": { + "description": "A short description of the artifact.", + "$ref": "#/$defs/message" + }, + "location": { + "description": "The location of the artifact.", + "$ref": "#/$defs/artifactLocation" + }, + "parentIndex": { + "description": "Identifies the index of the immediate parent of the artifact, if this artifact is nested.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "offset": { + "description": "The offset in bytes of the artifact within its containing artifact.", + "type": "integer", + "minimum": 0 + }, + "length": { + "description": "The length of the artifact in bytes.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "roles": { + "description": "The role or roles played by the artifact in the analysis.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "enum": [ + "analysisTarget", + "attachment", + "responseFile", + "resultFile", + "scannedFile", + "standardStream", + "tracedFile", + "unmodified", + "modified", + "added", + "deleted", + "renamed", + "uncontrolled", + "driver", + "extension", + "translation", + "taxonomy", + "policy", + "referencedOnCommandLine", + "memoryContents", + "directory", + "userSpecifiedConfiguration", + "toolSpecifiedConfiguration", + "debugOutputFile" + ], + "type": "string" + } + }, + "mimeType": { + "description": "The MIME type (RFC 2045) of the artifact.", + "type": "string", + "pattern": "[^/]+/.+" + }, + "contents": { + "description": "The contents of the artifact.", + "$ref": "#/$defs/artifactContent" + }, + "encoding": { + "description": "Specifies the encoding for an artifact object that refers to a text file.", + "type": "string" + }, + "sourceLanguage": { + "description": "Specifies the source language for any artifact object that refers to a text file that contains source code.", + "type": "string" + }, + "hashes": { + "description": "A dictionary, each of whose keys is the name of a hash function and each of whose values is the hashed value of the artifact produced by the specified hash function.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "lastModifiedTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the artifact was most recently modified. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the artifact.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "artifactChange": { + "description": "A change to a single artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + "artifactLocation": { + "description": "The location of the artifact to change.", + "$ref": "#/$defs/artifactLocation" + }, + "replacements": { + "description": "An array of replacement objects, each of which represents the replacement of a single region in a single artifact specified by 'artifactLocation'.", + "type": "array", + "minItems": 1, + "uniqueItems": false, + "items": { + "$ref": "#/$defs/replacement" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the change.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "artifactLocation", + "replacements" + ] + }, + "artifactContent": { + "description": "Represents the contents of an artifact.", + "type": "object", + "additionalProperties": false, + "properties": { + "text": { + "description": "UTF-8-encoded content from a text artifact.", + "type": "string" + }, + "binary": { + "description": "MIME Base64-encoded content from a binary artifact, or from a text artifact in its original encoding.", + "type": "string" + }, + "rendered": { + "description": "An alternate rendered representation of the artifact (e.g., a decompiled representation of a binary region).", + "$ref": "#/$defs/multiformatMessageString" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the artifact content.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "artifactLocation": { + "description": "Specifies the location of an artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + "uri": { + "description": "A string containing a valid relative or absolute URI.", + "type": "string", + "format": "uri-reference" + }, + "uriBaseId": { + "description": "A string which indirectly specifies the absolute URI with respect to which a relative URI in the \"uri\" property is interpreted.", + "type": "string" + }, + "index": { + "description": "The index within the run artifacts array of the artifact object associated with the artifact location.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "description": { + "description": "A short description of the artifact location.", + "$ref": "#/$defs/message" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the artifact location.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "attachment": { + "description": "An artifact relevant to a result.", + "type": "object", + "additionalProperties": false, + "properties": { + "description": { + "description": "A message describing the role played by the attachment.", + "$ref": "#/$defs/message" + }, + "artifactLocation": { + "description": "The location of the attachment.", + "$ref": "#/$defs/artifactLocation" + }, + "regions": { + "description": "An array of regions of interest within the attachment.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/region" + } + }, + "rectangles": { + "description": "An array of rectangles specifying areas of interest within the image.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/rectangle" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the attachment.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "artifactLocation" + ] + }, + "codeFlow": { + "description": "A set of threadFlows which together describe a pattern of code execution relevant to detecting a result.", + "additionalProperties": false, + "type": "object", + "properties": { + "message": { + "description": "A message relevant to the code flow.", + "$ref": "#/$defs/message" + }, + "threadFlows": { + "description": "An array of one or more unique threadFlow objects, each of which describes the progress of a program through a thread of execution.", + "type": "array", + "minItems": 1, + "uniqueItems": false, + "items": { + "$ref": "#/$defs/threadFlow" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the code flow.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "threadFlows" + ] + }, + "configurationOverride": { + "description": "Information about how a specific rule or notification was reconfigured at runtime.", + "type": "object", + "additionalProperties": false, + "properties": { + "configuration": { + "description": "Specifies how the rule or notification was configured during the scan.", + "$ref": "#/$defs/reportingConfiguration" + }, + "descriptor": { + "description": "A reference used to locate the descriptor whose configuration was overridden.", + "$ref": "#/$defs/reportingDescriptorReference" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the configuration override.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "configuration", + "descriptor" + ] + }, + "conversion": { + "description": "Describes how a converter transformed the output of a static analysis tool from the analysis tool's native output format into the SARIF format.", + "additionalProperties": false, + "type": "object", + "properties": { + "tool": { + "description": "A tool object that describes the converter.", + "$ref": "#/$defs/tool" + }, + "invocation": { + "description": "An invocation object that describes the invocation of the converter.", + "$ref": "#/$defs/invocation" + }, + "analysisToolLogFiles": { + "description": "The locations of the analysis tool's per-run log files.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/artifactLocation" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the conversion.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "tool" + ] + }, + "edge": { + "description": "Represents a directed edge in a graph.", + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "A string that uniquely identifies the edge within its graph.", + "type": "string" + }, + "label": { + "description": "A short description of the edge.", + "$ref": "#/$defs/message" + }, + "sourceNodeId": { + "description": "Identifies the source node (the node at which the edge starts).", + "type": "string" + }, + "targetNodeId": { + "description": "Identifies the target node (the node at which the edge ends).", + "type": "string" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the edge.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "id", + "sourceNodeId", + "targetNodeId" + ] + }, + "edgeTraversal": { + "description": "Represents the traversal of a single edge during a graph traversal.", + "type": "object", + "additionalProperties": false, + "properties": { + "edgeId": { + "description": "Identifies the edge being traversed.", + "type": "string" + }, + "message": { + "description": "A message to display to the user as the edge is traversed.", + "$ref": "#/$defs/message" + }, + "finalState": { + "description": "The values of relevant expressions after the edge has been traversed.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "stepOverEdgeCount": { + "description": "The number of edge traversals necessary to return from a nested graph.", + "type": "integer", + "minimum": 0 + }, + "properties": { + "description": "Key/value pairs that provide additional information about the edge traversal.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "edgeId" + ] + }, + "exception": { + "description": "Describes a runtime exception encountered during the execution of an analysis tool.", + "type": "object", + "additionalProperties": false, + "properties": { + "kind": { + "type": "string", + "description": "A string that identifies the kind of exception, for example, the fully qualified type name of an object that was thrown, or the symbolic name of a signal." + }, + "message": { + "description": "A message that describes the exception.", + "type": "string" + }, + "stack": { + "description": "The sequence of function calls leading to the exception.", + "$ref": "#/$defs/stack" + }, + "innerExceptions": { + "description": "An array of exception objects each of which is considered a cause of this exception.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/exception" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the exception.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "externalProperties": { + "description": "The top-level element of an external property file.", + "type": "object", + "additionalProperties": false, + "properties": { + "schema": { + "description": "The URI of the JSON schema corresponding to the version of the external property file format.", + "type": "string", + "format": "uri" + }, + "version": { + "description": "The SARIF format version of this external properties object.", + "enum": [ + "2.1.0" + ], + "type": "string" + }, + "guid": { + "description": "A stable, unique identifier for this external properties object, in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "runGuid": { + "description": "A stable, unique identifier for the run associated with this external properties object, in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + "conversion": { + "description": "A conversion object that will be merged with a separate run.", + "$ref": "#/$defs/conversion" + }, + "graphs": { + "description": "An array of graph objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "default": [], + "uniqueItems": true, + "items": { + "$ref": "#/$defs/graph" + } + }, + "externalizedProperties": { + "description": "Key/value pairs that provide additional information that will be merged with a separate run.", + "$ref": "#/$defs/propertyBag" + }, + "artifacts": { + "description": "An array of artifact objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/artifact" + } + }, + "invocations": { + "description": "Describes the invocation of the analysis tool that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/invocation" + } + }, + "logicalLocations": { + "description": "An array of logical locations such as namespaces, types or functions that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/logicalLocation" + } + }, + "threadFlowLocations": { + "description": "An array of threadFlowLocation objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/threadFlowLocation" + } + }, + "results": { + "description": "An array of result objects that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/result" + } + }, + "taxonomies": { + "description": "Tool taxonomies that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "driver": { + "description": "The analysis tool object that will be merged with a separate run.", + "$ref": "#/$defs/toolComponent" + }, + "extensions": { + "description": "Tool extensions that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "policies": { + "description": "Tool policies that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "translations": { + "description": "Tool translations that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "addresses": { + "description": "Addresses that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/address" + } + }, + "webRequests": { + "description": "Requests that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/webRequest" + } + }, + "webResponses": { + "description": "Responses that will be merged with a separate run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/webResponse" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the external properties.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "externalPropertyFileReference": { + "description": "Contains information that enables a SARIF consumer to locate the external property file that contains the value of an externalized property associated with the run.", + "type": "object", + "additionalProperties": false, + "properties": { + "location": { + "description": "The location of the external property file.", + "$ref": "#/$defs/artifactLocation" + }, + "guid": { + "description": "A stable, unique identifier for the external property file in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "itemCount": { + "description": "A non-negative integer specifying the number of items contained in the external property file.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "properties": { + "description": "Key/value pairs that provide additional information about the external property file.", + "$ref": "#/$defs/propertyBag" + } + }, + "anyOf": [ + { + "required": [ + "location" + ] + }, + { + "required": [ + "guid" + ] + } + ] + }, + "externalPropertyFileReferences": { + "description": "References to external property files that should be inlined with the content of a root log file.", + "additionalProperties": false, + "type": "object", + "properties": { + "conversion": { + "description": "An external property file containing a run.conversion object to be merged with the root log file.", + "$ref": "#/$defs/externalPropertyFileReference" + }, + "graphs": { + "description": "An array of external property files containing a run.graphs object to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "externalizedProperties": { + "description": "An external property file containing a run.properties object to be merged with the root log file.", + "$ref": "#/$defs/externalPropertyFileReference" + }, + "artifacts": { + "description": "An array of external property files containing run.artifacts arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "invocations": { + "description": "An array of external property files containing run.invocations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "logicalLocations": { + "description": "An array of external property files containing run.logicalLocations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "threadFlowLocations": { + "description": "An array of external property files containing run.threadFlowLocations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "results": { + "description": "An array of external property files containing run.results arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "taxonomies": { + "description": "An array of external property files containing run.taxonomies arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "addresses": { + "description": "An array of external property files containing run.addresses arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "driver": { + "description": "An external property file containing a run.driver object to be merged with the root log file.", + "$ref": "#/$defs/externalPropertyFileReference" + }, + "extensions": { + "description": "An array of external property files containing run.extensions arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "policies": { + "description": "An array of external property files containing run.policies arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "translations": { + "description": "An array of external property files containing run.translations arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "webRequests": { + "description": "An array of external property files containing run.requests arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "webResponses": { + "description": "An array of external property files containing run.responses arrays to be merged with the root log file.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/externalPropertyFileReference" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the external property files.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "fix": { + "description": "A proposed fix for the problem represented by a result object. A fix specifies a set of artifacts to modify. For each artifact, it specifies a set of bytes to remove, and provides a set of new bytes to replace them.", + "additionalProperties": false, + "type": "object", + "properties": { + "description": { + "description": "A message that describes the proposed fix, enabling viewers to present the proposed change to an end user.", + "$ref": "#/$defs/message" + }, + "artifactChanges": { + "description": "One or more artifact changes that comprise a fix for a result.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/artifactChange" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the fix.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "artifactChanges" + ] + }, + "graph": { + "description": "A network of nodes and directed edges that describes some aspect of the structure of the code (for example, a call graph).", + "type": "object", + "additionalProperties": false, + "properties": { + "description": { + "description": "A description of the graph.", + "$ref": "#/$defs/message" + }, + "nodes": { + "description": "An array of node objects representing the nodes of the graph.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/node" + } + }, + "edges": { + "description": "An array of edge objects representing the edges of the graph.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/edge" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the graph.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "graphTraversal": { + "description": "Represents a path through a graph.", + "type": "object", + "additionalProperties": false, + "properties": { + "runGraphIndex": { + "description": "The index within the run.graphs to be associated with the result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "resultGraphIndex": { + "description": "The index within the result.graphs to be associated with the result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "description": { + "description": "A description of this graph traversal.", + "$ref": "#/$defs/message" + }, + "initialState": { + "description": "Values of relevant expressions at the start of the graph traversal that may change during graph traversal.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "immutableState": { + "description": "Values of relevant expressions at the start of the graph traversal that remain constant for the graph traversal.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "edgeTraversals": { + "description": "The sequences of edges traversed by this graph traversal.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/edgeTraversal" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the graph traversal.", + "$ref": "#/$defs/propertyBag" + } + }, + "oneOf": [ + { + "required": [ + "runGraphIndex" + ] + }, + { + "required": [ + "resultGraphIndex" + ] + } + ] + }, + "guid": { + "description": "A stable, unique identifier for many entities in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + "invocation": { + "description": "The runtime environment of the analysis tool run.", + "additionalProperties": false, + "type": "object", + "properties": { + "commandLine": { + "description": "The command line used to invoke the tool.", + "type": "string" + }, + "arguments": { + "description": "An array of strings, containing in order the command line arguments passed to the tool from the operating system.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "items": { + "type": "string" + } + }, + "responseFiles": { + "description": "The locations of any response files specified on the tool's command line.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/artifactLocation" + } + }, + "startTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the invocation started. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + "endTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the invocation ended. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + "exitCode": { + "description": "The process exit code.", + "type": "integer" + }, + "ruleConfigurationOverrides": { + "description": "An array of configurationOverride objects that describe rules related runtime overrides.", + "type": "array", + "minItems": 0, + "default": [], + "uniqueItems": true, + "items": { + "$ref": "#/$defs/configurationOverride" + } + }, + "notificationConfigurationOverrides": { + "description": "An array of configurationOverride objects that describe notifications related runtime overrides.", + "type": "array", + "minItems": 0, + "default": [], + "uniqueItems": true, + "items": { + "$ref": "#/$defs/configurationOverride" + } + }, + "toolExecutionNotifications": { + "description": "A list of runtime conditions detected by the tool during the analysis.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/notification" + } + }, + "toolConfigurationNotifications": { + "description": "A list of conditions detected by the tool that are relevant to the tool's configuration.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/notification" + } + }, + "exitCodeDescription": { + "description": "The reason for the process exit.", + "type": "string" + }, + "exitSignalName": { + "description": "The name of the signal that caused the process to exit.", + "type": "string" + }, + "exitSignalNumber": { + "description": "The numeric value of the signal that caused the process to exit.", + "type": "integer" + }, + "processStartFailureMessage": { + "description": "The reason given by the operating system that the process failed to start.", + "type": "string" + }, + "executionSuccessful": { + "description": "Specifies whether the tool's execution completed successfully.", + "type": "boolean" + }, + "machine": { + "description": "The machine on which the invocation occurred.", + "type": "string" + }, + "account": { + "description": "The account under which the invocation occurred.", + "type": "string" + }, + "processId": { + "description": "The id of the process in which the invocation occurred.", + "type": "integer" + }, + "executableLocation": { + "description": "An absolute URI specifying the location of the executable that was invoked.", + "$ref": "#/$defs/artifactLocation" + }, + "workingDirectory": { + "description": "The working directory for the invocation.", + "$ref": "#/$defs/artifactLocation" + }, + "environmentVariables": { + "description": "The environment variables associated with the analysis tool process, expressed as key/value pairs.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "stdin": { + "description": "A file containing the standard input stream to the process that was invoked.", + "$ref": "#/$defs/artifactLocation" + }, + "stdout": { + "description": "A file containing the standard output stream from the process that was invoked.", + "$ref": "#/$defs/artifactLocation" + }, + "stderr": { + "description": "A file containing the standard error stream from the process that was invoked.", + "$ref": "#/$defs/artifactLocation" + }, + "stdoutStderr": { + "description": "A file containing the interleaved standard output and standard error stream from the process that was invoked.", + "$ref": "#/$defs/artifactLocation" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the invocation.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "executionSuccessful" + ] + }, + "language": { + "description": "The language of the messages emitted into the log file during this run (expressed as an ISO 639-1 two-letter lowercase culture code) and an optional region (expressed as an ISO 3166-1 two-letter uppercase subculture code associated with a country or region). The casing is recommended but not required (in order for this data to conform to RFC5646).", + "type": "string", + "default": "en-US", + "pattern": "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$" + }, + "location": { + "description": "A location within a programming artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + "id": { + "description": "Value that distinguishes this location from all other locations within a single result object.", + "type": "integer", + "minimum": -1, + "default": -1 + }, + "physicalLocation": { + "description": "Identifies the artifact and region.", + "$ref": "#/$defs/physicalLocation" + }, + "logicalLocations": { + "description": "The logical locations associated with the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/logicalLocation" + } + }, + "message": { + "description": "A message relevant to the location.", + "$ref": "#/$defs/message" + }, + "annotations": { + "description": "A set of regions relevant to the location.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/region" + } + }, + "relationships": { + "description": "An array of objects that describe relationships between this location and others.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/locationRelationship" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the location.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "locationRelationship": { + "description": "Information about the relation of one location to another.", + "type": "object", + "additionalProperties": false, + "properties": { + "target": { + "description": "A reference to the related location.", + "type": "integer", + "minimum": 0 + }, + "kinds": { + "description": "A set of distinct strings that categorize the relationship. Well-known kinds include 'includes', 'isIncludedBy' and 'relevant'.", + "type": "array", + "default": [ + "relevant" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "description": { + "description": "A description of the location relationship.", + "$ref": "#/$defs/message" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the location relationship.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "target" + ] + }, + "logicalLocation": { + "description": "A logical location of a construct that produced a result.", + "additionalProperties": false, + "type": "object", + "properties": { + "name": { + "description": "Identifies the construct in which the result occurred. For example, this property might contain the name of a class or a method.", + "type": "string" + }, + "index": { + "description": "The index within the logical locations array.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "fullyQualifiedName": { + "description": "The human-readable fully qualified name of the logical location.", + "type": "string" + }, + "decoratedName": { + "description": "The machine-readable name for the logical location, such as a mangled function name provided by a C++ compiler that encodes calling convention, return type and other details along with the function name.", + "type": "string" + }, + "parentIndex": { + "description": "Identifies the index of the immediate parent of the construct in which the result was detected. For example, this property might point to a logical location that represents the namespace that holds a type.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "kind": { + "description": "The type of construct this logical location component refers to. Should be one of 'function', 'member', 'module', 'namespace', 'parameter', 'resource', 'returnType', 'type', 'variable', 'object', 'array', 'property', 'value', 'element', 'text', 'attribute', 'comment', 'declaration', 'dtd' or 'processingInstruction', if any of those accurately describe the construct.", + "type": "string" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the logical location.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "message": { + "description": "Encapsulates a message intended to be read by the end user.", + "type": "object", + "additionalProperties": false, + "properties": { + "text": { + "description": "A plain text message string.", + "type": "string" + }, + "markdown": { + "description": "A Markdown message string.", + "type": "string" + }, + "id": { + "description": "The identifier for this message.", + "type": "string" + }, + "arguments": { + "description": "An array of strings to substitute into the message string.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "type": "string" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the message.", + "$ref": "#/$defs/propertyBag" + } + }, + "anyOf": [ + { + "required": [ + "text" + ] + }, + { + "required": [ + "id" + ] + } + ] + }, + "multiformatMessageString": { + "description": "A message string or message format string rendered in multiple formats.", + "type": "object", + "additionalProperties": false, + "properties": { + "text": { + "description": "A plain text message string or format string.", + "type": "string" + }, + "markdown": { + "description": "A Markdown message string or format string.", + "type": "string" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the message.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "text" + ] + }, + "node": { + "description": "Represents a node in a graph.", + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "A string that uniquely identifies the node within its graph.", + "type": "string" + }, + "label": { + "description": "A short description of the node.", + "$ref": "#/$defs/message" + }, + "location": { + "description": "A code location associated with the node.", + "$ref": "#/$defs/location" + }, + "children": { + "description": "Array of child nodes.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/node" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the node.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "id" + ] + }, + "notification": { + "description": "Describes a condition relevant to the tool itself, as opposed to being relevant to a target being analyzed by the tool.", + "type": "object", + "additionalProperties": false, + "properties": { + "locations": { + "description": "The locations relevant to this notification.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/location" + } + }, + "message": { + "description": "A message that describes the condition that was encountered.", + "$ref": "#/$defs/message" + }, + "level": { + "description": "A value specifying the severity level of the notification.", + "default": "warning", + "enum": [ + "none", + "note", + "warning", + "error" + ], + "type": "string" + }, + "threadId": { + "description": "The thread identifier of the code that generated the notification.", + "type": "integer" + }, + "timeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the analysis tool generated the notification.", + "type": "string", + "format": "date-time" + }, + "exception": { + "description": "The runtime exception, if any, relevant to this notification.", + "$ref": "#/$defs/exception" + }, + "relatedLocations": { + "description": "A set of locations relevant to this notification.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/location" + } + }, + "descriptor": { + "description": "A reference used to locate the descriptor relevant to this notification.", + "$ref": "#/$defs/reportingDescriptorReference" + }, + "associatedRule": { + "description": "A reference used to locate the rule descriptor associated with this notification.", + "$ref": "#/$defs/reportingDescriptorReference" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the notification.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "message" + ] + }, + "physicalLocation": { + "description": "A physical location relevant to a result. Specifies a reference to a programming artifact together with a range of bytes or characters within that artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + "address": { + "description": "The address of the location.", + "$ref": "#/$defs/address" + }, + "artifactLocation": { + "description": "The location of the artifact.", + "$ref": "#/$defs/artifactLocation" + }, + "region": { + "description": "Specifies a portion of the artifact.", + "$ref": "#/$defs/region" + }, + "contextRegion": { + "description": "Specifies a portion of the artifact that encloses the region. Allows a viewer to display additional context around the region.", + "$ref": "#/$defs/region" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the physical location.", + "$ref": "#/$defs/propertyBag" + } + }, + "anyOf": [ + { + "required": [ + "address" + ] + }, + { + "required": [ + "artifactLocation" + ] + } + ] + }, + "propertyBag": { + "description": "Key/value pairs that provide additional information about the object.", + "type": "object", + "additionalProperties": true, + "properties": { + "tags": { + "description": "A set of distinct strings that provide additional information.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "type": "string" + } + } + } + }, + "rectangle": { + "description": "An area within an image.", + "additionalProperties": false, + "type": "object", + "properties": { + "top": { + "description": "The Y coordinate of the top edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + "left": { + "description": "The X coordinate of the left edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + "bottom": { + "description": "The Y coordinate of the bottom edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + "right": { + "description": "The X coordinate of the right edge of the rectangle, measured in the image's natural units.", + "type": "number" + }, + "message": { + "description": "A message relevant to the rectangle.", + "$ref": "#/$defs/message" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the rectangle.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "region": { + "description": "A region within an artifact where a result was detected.", + "additionalProperties": false, + "type": "object", + "properties": { + "startLine": { + "description": "The line number of the first character in the region.", + "type": "integer", + "minimum": 1 + }, + "startColumn": { + "description": "The column number of the first character in the region.", + "type": "integer", + "minimum": 1 + }, + "endLine": { + "description": "The line number of the last character in the region.", + "type": "integer", + "minimum": 1 + }, + "endColumn": { + "description": "The column number of the character following the end of the region.", + "type": "integer", + "minimum": 1 + }, + "charOffset": { + "description": "The zero-based offset from the beginning of the artifact of the first character in the region.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "charLength": { + "description": "The length of the region in characters.", + "type": "integer", + "minimum": 0 + }, + "byteOffset": { + "description": "The zero-based offset from the beginning of the artifact of the first byte in the region.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "byteLength": { + "description": "The length of the region in bytes.", + "type": "integer", + "minimum": 0 + }, + "snippet": { + "description": "The portion of the artifact contents within the specified region.", + "$ref": "#/$defs/artifactContent" + }, + "message": { + "description": "A message relevant to the region.", + "$ref": "#/$defs/message" + }, + "sourceLanguage": { + "description": "Specifies the source language, if any, of the portion of the artifact specified by the region object.", + "type": "string" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the region.", + "$ref": "#/$defs/propertyBag" + } + }, + "anyOf": [ + { + "required": [ + "startLine" + ] + }, + { + "required": [ + "charOffset" + ] + }, + { + "required": [ + "byteOffset" + ] + } + ] + }, + "replacement": { + "description": "The replacement of a single region of an artifact.", + "additionalProperties": false, + "type": "object", + "properties": { + "deletedRegion": { + "description": "The region of the artifact to delete.", + "$ref": "#/$defs/region" + }, + "insertedContent": { + "description": "The content to insert at the location specified by the 'deletedRegion' property.", + "$ref": "#/$defs/artifactContent" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the replacement.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "deletedRegion" + ] + }, + "reportingDescriptor": { + "description": "Metadata that describes a specific report produced by the tool, as part of the analysis it provides or its runtime reporting.", + "additionalProperties": false, + "type": "object", + "properties": { + "id": { + "description": "A stable, opaque identifier for the report.", + "type": "string" + }, + "deprecatedIds": { + "description": "An array of stable, opaque identifiers by which this report was known in some previous version of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "guid": { + "description": "A unique identifier for the reporting descriptor in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "deprecatedGuids": { + "description": "An array of unique identifies in the form of a GUID by which this report was known in some previous version of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + } + }, + "name": { + "description": "A report identifier that is understandable to an end user.", + "type": "string" + }, + "deprecatedNames": { + "description": "An array of readable identifiers by which this report was known in some previous version of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "shortDescription": { + "description": "A concise description of the report. Should be a single sentence that is understandable when visible space is limited to a single line of text.", + "$ref": "#/$defs/multiformatMessageString" + }, + "fullDescription": { + "description": "A description of the report. Should, as far as possible, provide details sufficient to enable resolution of any problem indicated by the result.", + "$ref": "#/$defs/multiformatMessageString" + }, + "messageStrings": { + "description": "A set of name/value pairs with arbitrary names. Each value is a multiformatMessageString object, which holds message strings in plain text and (optionally) Markdown format. The strings can include placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "defaultConfiguration": { + "description": "Default reporting configuration information.", + "$ref": "#/$defs/reportingConfiguration" + }, + "helpUri": { + "description": "A URI where the primary documentation for the report can be found.", + "type": "string", + "format": "uri" + }, + "help": { + "description": "Provides the primary documentation for the report, useful when there is no online documentation.", + "$ref": "#/$defs/multiformatMessageString" + }, + "relationships": { + "description": "An array of objects that describe relationships between this reporting descriptor and others.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/reportingDescriptorRelationship" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the report.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "id" + ] + }, + "reportingConfiguration": { + "description": "Information about a rule or notification that can be configured at runtime.", + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "description": "Specifies whether the report may be produced during the scan.", + "type": "boolean", + "default": true + }, + "level": { + "description": "Specifies the failure level for the report.", + "default": "warning", + "enum": [ + "none", + "note", + "warning", + "error" + ], + "type": "string" + }, + "rank": { + "description": "Specifies the relative priority of the report. Used for analysis output only.", + "type": "number", + "default": -1.0, + "minimum": -1.0, + "maximum": 100.0 + }, + "parameters": { + "description": "Contains configuration information specific to a report.", + "$ref": "#/$defs/propertyBag" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the reporting configuration.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "reportingDescriptorReference": { + "description": "Information about how to locate a relevant reporting descriptor.", + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "The id of the descriptor.", + "type": "string" + }, + "index": { + "description": "The index into an array of descriptors in toolComponent.ruleDescriptors, toolComponent.notificationDescriptors, or toolComponent.taxonomyDescriptors, depending on context.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "guid": { + "description": "A guid that uniquely identifies the descriptor.", + "$ref": "#/$defs/guid" + }, + "toolComponent": { + "description": "A reference used to locate the toolComponent associated with the descriptor.", + "$ref": "#/$defs/toolComponentReference" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the reporting descriptor reference.", + "$ref": "#/$defs/propertyBag" + } + }, + "anyOf": [ + { + "required": [ + "index" + ] + }, + { + "required": [ + "guid" + ] + }, + { + "required": [ + "id" + ] + } + ] + }, + "reportingDescriptorRelationship": { + "description": "Information about the relation of one reporting descriptor to another.", + "type": "object", + "additionalProperties": false, + "properties": { + "target": { + "description": "A reference to the related reporting descriptor.", + "$ref": "#/$defs/reportingDescriptorReference" + }, + "kinds": { + "description": "A set of distinct strings that categorize the relationship. Well-known kinds include 'canPrecede', 'canFollow', 'willPrecede', 'willFollow', 'superset', 'subset', 'equal', 'disjoint', 'relevant', and 'incomparable'.", + "type": "array", + "default": [ + "relevant" + ], + "uniqueItems": true, + "items": { + "type": "string" + } + }, + "description": { + "description": "A description of the reporting descriptor relationship.", + "$ref": "#/$defs/message" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the reporting descriptor reference.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "target" + ] + }, + "result": { + "description": "A result produced by an analysis tool.", + "additionalProperties": false, + "type": "object", + "properties": { + "ruleId": { + "description": "The stable, unique identifier of the rule, if any, to which this result is relevant.", + "type": "string" + }, + "ruleIndex": { + "description": "The index within the tool component rules array of the rule object associated with this result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "rule": { + "description": "A reference used to locate the rule descriptor relevant to this result.", + "$ref": "#/$defs/reportingDescriptorReference" + }, + "kind": { + "description": "A value that categorizes results by evaluation state.", + "default": "fail", + "enum": [ + "notApplicable", + "pass", + "fail", + "review", + "open", + "informational" + ], + "type": "string" + }, + "level": { + "description": "A value specifying the severity level of the result.", + "default": "warning", + "enum": [ + "none", + "note", + "warning", + "error" + ], + "type": "string" + }, + "message": { + "description": "A message that describes the result. The first sentence of the message only will be displayed when visible space is limited.", + "$ref": "#/$defs/message" + }, + "analysisTarget": { + "description": "Identifies the artifact that the analysis tool was instructed to scan. This need not be the same as the artifact where the result actually occurred.", + "$ref": "#/$defs/artifactLocation" + }, + "locations": { + "description": "The set of locations where the result was detected. Specify only one location unless the problem indicated by the result can only be corrected by making a change at every specified location.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/location" + } + }, + "guid": { + "description": "A stable, unique identifier for the result in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "correlationGuid": { + "description": "A stable, unique identifier for the equivalence class of logically identical results to which this result belongs, in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + "occurrenceCount": { + "description": "A positive integer specifying the number of times this logically unique result was observed in this run.", + "type": "integer", + "minimum": 1 + }, + "partialFingerprints": { + "description": "A set of strings that contribute to the stable, unique identity of the result.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "fingerprints": { + "description": "A set of strings each of which individually defines a stable, unique identity for the result.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "stacks": { + "description": "An array of 'stack' objects relevant to the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/stack" + } + }, + "codeFlows": { + "description": "An array of 'codeFlow' objects relevant to the result.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/codeFlow" + } + }, + "graphs": { + "description": "An array of zero or more unique graph objects associated with the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/graph" + } + }, + "graphTraversals": { + "description": "An array of one or more unique 'graphTraversal' objects.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/graphTraversal" + } + }, + "relatedLocations": { + "description": "A set of locations relevant to this result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/location" + } + }, + "suppressions": { + "description": "A set of suppressions relevant to this result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/suppression" + } + }, + "baselineState": { + "description": "The state of a result relative to a baseline of a previous run.", + "enum": [ + "new", + "unchanged", + "updated", + "absent" + ], + "type": "string" + }, + "rank": { + "description": "A number representing the priority or importance of the result.", + "type": "number", + "default": -1.0, + "minimum": -1.0, + "maximum": 100.0 + }, + "attachments": { + "description": "A set of artifacts relevant to the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/attachment" + } + }, + "hostedViewerUri": { + "description": "An absolute URI at which the result can be viewed.", + "type": "string", + "format": "uri" + }, + "workItemUris": { + "description": "The URIs of the work items associated with this result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "type": "string", + "format": "uri" + } + }, + "provenance": { + "description": "Information about how and when the result was detected.", + "$ref": "#/$defs/resultProvenance" + }, + "fixes": { + "description": "An array of 'fix' objects, each of which represents a proposed fix to the problem indicated by the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/fix" + } + }, + "taxa": { + "description": "An array of references to taxonomy reporting descriptors that are applicable to the result.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/reportingDescriptorReference" + } + }, + "webRequest": { + "description": "A web request associated with this result.", + "$ref": "#/$defs/webRequest" + }, + "webResponse": { + "description": "A web response associated with this result.", + "$ref": "#/$defs/webResponse" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the result.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "message" + ] + }, + "resultProvenance": { + "description": "Contains information about how and when a result was detected.", + "additionalProperties": false, + "type": "object", + "properties": { + "firstDetectionTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the result was first detected. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + "lastDetectionTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which the result was most recently detected. See \"Date/time properties\" in the SARIF spec for the required format.", + "type": "string", + "format": "date-time" + }, + "firstDetectionRunGuid": { + "description": "A GUID-valued string equal to the automationDetails.guid property of the run in which the result was first detected.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + "lastDetectionRunGuid": { + "description": "A GUID-valued string equal to the automationDetails.guid property of the run in which the result was most recently detected.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + "invocationIndex": { + "description": "The index within the run.invocations array of the invocation object which describes the tool invocation that detected the result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "conversionSources": { + "description": "An array of physicalLocation objects which specify the portions of an analysis tool's output that a converter transformed into the result.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/physicalLocation" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the result.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "run": { + "description": "Describes a single run of an analysis tool, and contains the reported output of that run.", + "additionalProperties": false, + "type": "object", + "properties": { + "tool": { + "description": "Information about the tool or tool pipeline that generated the results in this run. A run can only contain results produced by a single tool or tool pipeline. A run can aggregate results from multiple log files, as long as context around the tool run (tool command-line arguments and the like) is identical for all aggregated files.", + "$ref": "#/$defs/tool" + }, + "invocations": { + "description": "Describes the invocation of the analysis tool.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/invocation" + } + }, + "conversion": { + "description": "A conversion object that describes how a converter transformed an analysis tool's native reporting format into the SARIF format.", + "$ref": "#/$defs/conversion" + }, + "language": { + "description": "The language of the messages emitted into the log file during this run (expressed as an ISO 639-1 two-letter lowercase culture code) and an optional region (expressed as an ISO 3166-1 two-letter uppercase subculture code associated with a country or region). The casing is recommended but not required (in order for this data to conform to RFC5646).", + "$ref": "#/$defs/language" + }, + "versionControlProvenance": { + "description": "Specifies the revision in version control of the artifacts that were scanned.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/versionControlDetails" + } + }, + "originalUriBaseIds": { + "description": "The artifact location specified by each uriBaseId symbol on the machine where the tool originally ran.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/artifactLocation" + } + }, + "artifacts": { + "description": "An array of artifact objects relevant to the run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/artifact" + } + }, + "logicalLocations": { + "description": "An array of logical locations such as namespaces, types or functions.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/logicalLocation" + } + }, + "graphs": { + "description": "An array of zero or more unique graph objects associated with the run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/graph" + } + }, + "results": { + "description": "The set of results contained in an SARIF log. The results array can be omitted when a run is solely exporting rules metadata. It must be present (but may be empty) if a log file represents an actual scan.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "items": { + "$ref": "#/$defs/result" + } + }, + "automationDetails": { + "description": "Automation details that describe this run.", + "$ref": "#/$defs/runAutomationDetails" + }, + "runAggregates": { + "description": "Automation details that describe the aggregate of runs to which this run belongs.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/runAutomationDetails" + } + }, + "baselineGuid": { + "description": "The 'guid' property of a previous SARIF 'run' that comprises the baseline that was used to compute result 'baselineState' properties for the run.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + "redactionTokens": { + "description": "An array of strings used to replace sensitive information in a redaction-aware property.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "type": "string" + } + }, + "defaultEncoding": { + "description": "Specifies the default encoding for any artifact object that refers to a text file.", + "type": "string" + }, + "defaultSourceLanguage": { + "description": "Specifies the default source language for any artifact object that refers to a text file that contains source code.", + "type": "string" + }, + "newlineSequences": { + "description": "An ordered list of character sequences that were treated as line breaks when computing region information for the run.", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "default": [ + "\r\n", + "\n" + ], + "items": { + "type": "string" + } + }, + "columnKind": { + "description": "Specifies the unit in which the tool measures columns.", + "enum": [ + "utf16CodeUnits", + "unicodeCodePoints" + ], + "type": "string" + }, + "externalPropertyFileReferences": { + "description": "References to external property files that should be inlined with the content of a root log file.", + "$ref": "#/$defs/externalPropertyFileReferences" + }, + "threadFlowLocations": { + "description": "An array of threadFlowLocation objects cached at run level.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/threadFlowLocation" + } + }, + "taxonomies": { + "description": "An array of toolComponent objects relevant to a taxonomy in which results are categorized.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "addresses": { + "description": "Addresses associated with this run instance, if any.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "$ref": "#/$defs/address" + } + }, + "translations": { + "description": "The set of available translations of the localized data provided by the tool.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "policies": { + "description": "Contains configurations that may potentially override both reportingDescriptor.defaultConfiguration (the tool's default severities) and invocation.configurationOverrides (severities established at run-time from the command line).", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "webRequests": { + "description": "An array of request objects cached at run level.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/webRequest" + } + }, + "webResponses": { + "description": "An array of response objects cached at run level.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/webResponse" + } + }, + "specialLocations": { + "description": "A specialLocations object that defines locations of special significance to SARIF consumers.", + "$ref": "#/$defs/specialLocations" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the run.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "tool" + ] + }, + "runAutomationDetails": { + "description": "Information that describes a run's identity and role within an engineering system process.", + "additionalProperties": false, + "type": "object", + "properties": { + "description": { + "description": "A description of the identity and role played within the engineering system by this object's containing run object.", + "$ref": "#/$defs/message" + }, + "id": { + "description": "A hierarchical string that uniquely identifies this object's containing run object.", + "type": "string" + }, + "guid": { + "description": "A stable, unique identifier for this object's containing run object in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "correlationGuid": { + "description": "A stable, unique identifier for the equivalence class of runs to which this object's containing run object belongs in the form of a GUID.", + "type": "string", + "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the run automation details.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "specialLocations": { + "description": "Defines locations of special significance to SARIF consumers.", + "type": "object", + "additionalProperties": false, + "properties": { + "displayBase": { + "description": "Provides a suggestion to SARIF consumers to display file paths relative to the specified location.", + "$ref": "#/$defs/artifactLocation" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the special locations.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "stack": { + "description": "A call stack that is relevant to a result.", + "additionalProperties": false, + "type": "object", + "properties": { + "message": { + "description": "A message relevant to this call stack.", + "$ref": "#/$defs/message" + }, + "frames": { + "description": "An array of stack frames that represents a sequence of calls, rendered in reverse chronological order, that comprise the call stack.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "items": { + "$ref": "#/$defs/stackFrame" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the stack.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "frames" + ] + }, + "stackFrame": { + "description": "A function call within a stack trace.", + "additionalProperties": false, + "type": "object", + "properties": { + "location": { + "description": "The location to which this stack frame refers.", + "$ref": "#/$defs/location" + }, + "module": { + "description": "The name of the module that contains the code of this stack frame.", + "type": "string" + }, + "threadId": { + "description": "The thread identifier of the stack frame.", + "type": "integer" + }, + "parameters": { + "description": "The parameters of the call that is executing.", + "type": "array", + "minItems": 0, + "uniqueItems": false, + "default": [], + "items": { + "type": "string", + "default": [] + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the stack frame.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "suppression": { + "description": "A suppression that is relevant to a result.", + "additionalProperties": false, + "type": "object", + "properties": { + "guid": { + "description": "A stable, unique identifier for the suprression in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "kind": { + "description": "A string that indicates where the suppression is persisted.", + "enum": [ + "inSource", + "external" + ], + "type": "string" + }, + "status": { + "description": "A string that indicates the review status of the suppression.", + "enum": [ + "accepted", + "underReview", + "rejected" + ], + "type": "string" + }, + "justification": { + "description": "A string representing the justification for the suppression.", + "type": "string" + }, + "location": { + "description": "Identifies the location associated with the suppression.", + "$ref": "#/$defs/location" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the suppression.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "kind" + ] + }, + "threadFlow": { + "description": "Describes a sequence of code locations that specify a path through a single thread of execution such as an operating system or fiber.", + "type": "object", + "additionalProperties": false, + "properties": { + "id": { + "description": "An string that uniquely identifies the threadFlow within the codeFlow in which it occurs.", + "type": "string" + }, + "message": { + "description": "A message relevant to the thread flow.", + "$ref": "#/$defs/message" + }, + "initialState": { + "description": "Values of relevant expressions at the start of the thread flow that may change during thread flow execution.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "immutableState": { + "description": "Values of relevant expressions at the start of the thread flow that remain constant.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "locations": { + "description": "A temporally ordered array of 'threadFlowLocation' objects, each of which describes a location visited by the tool while producing the result.", + "type": "array", + "minItems": 1, + "uniqueItems": false, + "items": { + "$ref": "#/$defs/threadFlowLocation" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the thread flow.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "locations" + ] + }, + "threadFlowLocation": { + "description": "A location visited by an analysis tool while simulating or monitoring the execution of a program.", + "additionalProperties": false, + "type": "object", + "properties": { + "index": { + "description": "The index within the run threadFlowLocations array.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "location": { + "description": "The code location.", + "$ref": "#/$defs/location" + }, + "stack": { + "description": "The call stack leading to this location.", + "$ref": "#/$defs/stack" + }, + "kinds": { + "description": "A set of distinct strings that categorize the thread flow location. Well-known kinds include 'acquire', 'release', 'enter', 'exit', 'call', 'return', 'branch', 'implicit', 'false', 'true', 'caution', 'danger', 'unknown', 'unreachable', 'taint', 'function', 'handler', 'lock', 'memory', 'resource', 'scope' and 'value'.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "type": "string" + } + }, + "taxa": { + "description": "An array of references to rule or taxonomy reporting descriptors that are applicable to the thread flow location.", + "type": "array", + "default": [], + "minItems": 0, + "uniqueItems": true, + "items": { + "$ref": "#/$defs/reportingDescriptorReference" + } + }, + "module": { + "description": "The name of the module that contains the code that is executing.", + "type": "string" + }, + "state": { + "description": "A dictionary, each of whose keys specifies a variable or expression, the associated value of which represents the variable or expression value. For an annotation of kind 'continuation', for example, this dictionary might hold the current assumed values of a set of global variables.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "nestingLevel": { + "description": "An integer representing a containment hierarchy within the thread flow.", + "type": "integer", + "minimum": 0 + }, + "executionOrder": { + "description": "An integer representing the temporal order in which execution reached this location.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "executionTimeUtc": { + "description": "The Coordinated Universal Time (UTC) date and time at which this location was executed.", + "type": "string", + "format": "date-time" + }, + "importance": { + "description": "Specifies the importance of this location in understanding the code flow in which it occurs. The order from most to least important is \"essential\", \"important\", \"unimportant\". Default: \"important\".", + "enum": [ + "important", + "essential", + "unimportant" + ], + "default": "important", + "type": "string" + }, + "webRequest": { + "description": "A web request associated with this thread flow location.", + "$ref": "#/$defs/webRequest" + }, + "webResponse": { + "description": "A web response associated with this thread flow location.", + "$ref": "#/$defs/webResponse" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the threadflow location.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "tool": { + "description": "The analysis tool that was run.", + "additionalProperties": false, + "type": "object", + "properties": { + "driver": { + "description": "The analysis tool that was run.", + "$ref": "#/$defs/toolComponent" + }, + "extensions": { + "description": "Tool extensions that contributed to or reconfigured the analysis tool that was run.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponent" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the tool.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "driver" + ] + }, + "toolComponent": { + "description": "A component, such as a plug-in or the driver, of the analysis tool that was run.", + "additionalProperties": false, + "type": "object", + "properties": { + "guid": { + "description": "A unique identifier for the tool component in the form of a GUID.", + "$ref": "#/$defs/guid" + }, + "name": { + "description": "The name of the tool component.", + "type": "string" + }, + "organization": { + "description": "The organization or company that produced the tool component.", + "type": "string" + }, + "product": { + "description": "A product suite to which the tool component belongs.", + "type": "string" + }, + "productSuite": { + "description": "A localizable string containing the name of the suite of products to which the tool component belongs.", + "type": "string" + }, + "shortDescription": { + "description": "A brief description of the tool component.", + "$ref": "#/$defs/multiformatMessageString" + }, + "fullDescription": { + "description": "A comprehensive description of the tool component.", + "$ref": "#/$defs/multiformatMessageString" + }, + "fullName": { + "description": "The name of the tool component along with its version and any other useful identifying information, such as its locale.", + "type": "string" + }, + "version": { + "description": "The tool component version, in whatever format the component natively provides.", + "type": "string" + }, + "semanticVersion": { + "description": "The tool component version in the format specified by Semantic Versioning 2.0.", + "type": "string" + }, + "dottedQuadFileVersion": { + "description": "The binary version of the tool component's primary executable file expressed as four non-negative integers separated by a period (for operating systems that express file versions in this way).", + "type": "string", + "pattern": "[0-9]+(\\.[0-9]+){3}" + }, + "releaseDateUtc": { + "description": "A string specifying the UTC date (and optionally, the time) of the component's release.", + "type": "string" + }, + "downloadUri": { + "description": "The absolute URI from which the tool component can be downloaded.", + "type": "string", + "format": "uri" + }, + "informationUri": { + "description": "The absolute URI at which information about this version of the tool component can be found.", + "type": "string", + "format": "uri" + }, + "globalMessageStrings": { + "description": "A dictionary, each of whose keys is a resource identifier and each of whose values is a multiformatMessageString object, which holds message strings in plain text and (optionally) Markdown format. The strings can include placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments.", + "type": "object", + "additionalProperties": { + "$ref": "#/$defs/multiformatMessageString" + } + }, + "notifications": { + "description": "An array of reportingDescriptor objects relevant to the notifications related to the configuration and runtime execution of the tool component.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/reportingDescriptor" + } + }, + "rules": { + "description": "An array of reportingDescriptor objects relevant to the analysis performed by the tool component.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/reportingDescriptor" + } + }, + "taxa": { + "description": "An array of reportingDescriptor objects relevant to the definitions of both standalone and tool-defined taxonomies.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/reportingDescriptor" + } + }, + "locations": { + "description": "An array of the artifactLocation objects associated with the tool component.", + "type": "array", + "minItems": 0, + "default": [], + "items": { + "$ref": "#/$defs/artifactLocation" + } + }, + "language": { + "description": "The language of the messages emitted into the log file during this run (expressed as an ISO 639-1 two-letter lowercase language code) and an optional region (expressed as an ISO 3166-1 two-letter uppercase subculture code associated with a country or region). The casing is recommended but not required (in order for this data to conform to RFC5646).", + "$ref": "#/$defs/language" + }, + "contents": { + "description": "The kinds of data contained in this object.", + "type": "array", + "uniqueItems": true, + "default": [ + "localizedData", + "nonLocalizedData" + ], + "items": { + "enum": [ + "localizedData", + "nonLocalizedData" + ], + "type": "string" + } + }, + "isComprehensive": { + "description": "Specifies whether this object contains a complete definition of the localizable and/or non-localizable data for this component, as opposed to including only data that is relevant to the results persisted to this log file.", + "type": "boolean", + "default": false + }, + "localizedDataSemanticVersion": { + "description": "The semantic version of the localized strings defined in this component; maintained by components that provide translations.", + "type": "string" + }, + "minimumRequiredLocalizedDataSemanticVersion": { + "description": "The minimum value of localizedDataSemanticVersion required in translations consumed by this component; used by components that consume translations.", + "type": "string" + }, + "associatedComponent": { + "description": "The component which is strongly associated with this component. For a translation, this refers to the component which has been translated. For an extension, this is the driver that provides the extension's plugin model.", + "$ref": "#/$defs/toolComponentReference" + }, + "translationMetadata": { + "description": "Translation metadata, required for a translation, not populated by other component types.", + "$ref": "#/$defs/translationMetadata" + }, + "supportedTaxonomies": { + "description": "An array of toolComponentReference objects to declare the taxonomies supported by the tool component.", + "type": "array", + "minItems": 0, + "uniqueItems": true, + "default": [], + "items": { + "$ref": "#/$defs/toolComponentReference" + } + }, + "properties": { + "description": "Key/value pairs that provide additional information about the tool component.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "name" + ] + }, + "toolComponentReference": { + "description": "Identifies a particular toolComponent object, either the driver or an extension.", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "description": "The 'name' property of the referenced toolComponent.", + "type": "string" + }, + "index": { + "description": "An index into the referenced toolComponent in tool.extensions.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "guid": { + "description": "The 'guid' property of the referenced toolComponent.", + "$ref": "#/$defs/guid" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the toolComponentReference.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "translationMetadata": { + "description": "Provides additional metadata related to translation.", + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "description": "The name associated with the translation metadata.", + "type": "string" + }, + "fullName": { + "description": "The full name associated with the translation metadata.", + "type": "string" + }, + "shortDescription": { + "description": "A brief description of the translation metadata.", + "$ref": "#/$defs/multiformatMessageString" + }, + "fullDescription": { + "description": "A comprehensive description of the translation metadata.", + "$ref": "#/$defs/multiformatMessageString" + }, + "downloadUri": { + "description": "The absolute URI from which the translation metadata can be downloaded.", + "type": "string", + "format": "uri" + }, + "informationUri": { + "description": "The absolute URI from which information related to the translation metadata can be downloaded.", + "type": "string", + "format": "uri" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the translation metadata.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "name" + ] + }, + "versionControlDetails": { + "description": "Specifies the information necessary to retrieve a desired revision from a version control system.", + "type": "object", + "additionalProperties": false, + "properties": { + "repositoryUri": { + "description": "The absolute URI of the repository.", + "type": "string", + "format": "uri" + }, + "revisionId": { + "description": "A string that uniquely and permanently identifies the revision within the repository.", + "type": "string" + }, + "branch": { + "description": "The name of a branch containing the revision.", + "type": "string" + }, + "revisionTag": { + "description": "A tag that has been applied to the revision.", + "type": "string" + }, + "asOfTimeUtc": { + "description": "A Coordinated Universal Time (UTC) date and time that can be used to synchronize an enlistment to the state of the repository at that time.", + "type": "string", + "format": "date-time" + }, + "mappedTo": { + "description": "The location in the local file system to which the root of the repository was mapped at the time of the analysis.", + "$ref": "#/$defs/artifactLocation" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the version control details.", + "$ref": "#/$defs/propertyBag" + } + }, + "required": [ + "repositoryUri" + ] + }, + "webRequest": { + "description": "Describes an HTTP request.", + "type": "object", + "additionalProperties": false, + "properties": { + "index": { + "description": "The index within the run.webRequests array of the request object associated with this result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "protocol": { + "description": "The request protocol. Example: 'http'.", + "type": "string" + }, + "version": { + "description": "The request version. Example: '1.1'.", + "type": "string" + }, + "target": { + "description": "The target of the request.", + "type": "string" + }, + "method": { + "description": "The HTTP method. Well-known values are 'GET', 'PUT', 'POST', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT'.", + "type": "string" + }, + "headers": { + "description": "The request headers.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "parameters": { + "description": "The request parameters.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "body": { + "description": "The body of the request.", + "$ref": "#/$defs/artifactContent" + }, + "properties": { + "description": "Key/value pairs that provide additional information about the request.", + "$ref": "#/$defs/propertyBag" + } + } + }, + "webResponse": { + "description": "Describes the response to an HTTP request.", + "type": "object", + "additionalProperties": false, + "properties": { + "index": { + "description": "The index within the run.webResponses array of the response object associated with this result.", + "type": "integer", + "default": -1, + "minimum": -1 + }, + "protocol": { + "description": "The response protocol. Example: 'http'.", + "type": "string" + }, + "version": { + "description": "The response version. Example: '1.1'.", + "type": "string" + }, + "statusCode": { + "description": "The response status code. Example: 451.", + "type": "integer" + }, + "reasonPhrase": { + "description": "The response reason. Example: 'Not found'.", + "type": "string" + }, + "headers": { + "description": "The response headers.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "body": { + "description": "The body of the response.", + "$ref": "#/$defs/artifactContent" + }, + "noResponseReceived": { + "description": "Specifies whether a response was received from the server.", + "type": "boolean", + "default": false + }, + "properties": { + "description": "Key/value pairs that provide additional information about the response.", + "$ref": "#/$defs/propertyBag" + } + } + } + } +} \ No newline at end of file diff --git a/sarif/spec/gen/sarif-schema/v2-1-0/schema.go b/sarif/spec/gen/sarif-schema/v2-1-0/schema.go new file mode 100644 index 0000000..79ec5aa --- /dev/null +++ b/sarif/spec/gen/sarif-schema/v2-1-0/schema.go @@ -0,0 +1,3506 @@ +// Code generated by github.com/atombender/go-jsonschema, DO NOT EDIT. + +package schema +import ( + "encoding/json" + "fmt" + "reflect" + "regexp" + "strings" + "time" + + "github.com/mitchellh/mapstructure" +) + +// A physical or virtual address, or a range of addresses, in an 'addressable +// region' (memory or a binary file). +type Address struct { + // The address expressed as a byte offset from the start of the addressable + // region. + AbsoluteAddress int `json:"absoluteAddress,omitempty" yaml:"absoluteAddress,omitempty" mapstructure:"absoluteAddress,omitempty"` + + // A human-readable fully qualified name that is associated with the address. + FullyQualifiedName *string `json:"fullyQualifiedName,omitempty" yaml:"fullyQualifiedName,omitempty" mapstructure:"fullyQualifiedName,omitempty"` + + // The index within run.addresses of the cached object for this address. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // An open-ended string that identifies the address kind. 'data', 'function', + // 'header','instruction', 'module', 'page', 'section', 'segment', 'stack', + // 'stackFrame', 'table' are well-known values. + Kind *string `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // The number of bytes in this range of addresses. + Length *int `json:"length,omitempty" yaml:"length,omitempty" mapstructure:"length,omitempty"` + + // A name that is associated with the address, e.g., '.text'. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // The byte offset of this address from the absolute or relative address of the + // parent object. + OffsetFromParent *int `json:"offsetFromParent,omitempty" yaml:"offsetFromParent,omitempty" mapstructure:"offsetFromParent,omitempty"` + + // The index within run.addresses of the parent object. + ParentIndex int `json:"parentIndex,omitempty" yaml:"parentIndex,omitempty" mapstructure:"parentIndex,omitempty"` + + // Key/value pairs that provide additional information about the address. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The address expressed as a byte offset from the absolute address of the + // top-most parent object. + RelativeAddress *int `json:"relativeAddress,omitempty" yaml:"relativeAddress,omitempty" mapstructure:"relativeAddress,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Address) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain Address + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["absoluteAddress"]; !ok || v == nil { + plain.AbsoluteAddress = -1.0 + } + if -1 > plain.AbsoluteAddress { + return fmt.Errorf("field %s: must be >= %v", "absoluteAddress", -1) + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["parentIndex"]; !ok || v == nil { + plain.ParentIndex = -1.0 + } + if -1 > plain.ParentIndex { + return fmt.Errorf("field %s: must be >= %v", "parentIndex", -1) + } + *j = Address(plain) + return nil +} + + +// A single artifact. In some cases, this artifact might be nested within another +// artifact. +type Artifact struct { + // The contents of the artifact. + Contents *ArtifactContent `json:"contents,omitempty" yaml:"contents,omitempty" mapstructure:"contents,omitempty"` + + // A short description of the artifact. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // Specifies the encoding for an artifact object that refers to a text file. + Encoding *string `json:"encoding,omitempty" yaml:"encoding,omitempty" mapstructure:"encoding,omitempty"` + + // A dictionary, each of whose keys is the name of a hash function and each of + // whose values is the hashed value of the artifact produced by the specified hash + // function. + Hashes ArtifactHashes `json:"hashes,omitempty" yaml:"hashes,omitempty" mapstructure:"hashes,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the artifact was + // most recently modified. See "Date/time properties" in the SARIF spec for the + // required format. + LastModifiedTimeUtc *time.Time `json:"lastModifiedTimeUtc,omitempty" yaml:"lastModifiedTimeUtc,omitempty" mapstructure:"lastModifiedTimeUtc,omitempty"` + + // The length of the artifact in bytes. + Length int `json:"length,omitempty" yaml:"length,omitempty" mapstructure:"length,omitempty"` + + // The location of the artifact. + Location *ArtifactLocation `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // The MIME type (RFC 2045) of the artifact. + MimeType *string `json:"mimeType,omitempty" yaml:"mimeType,omitempty" mapstructure:"mimeType,omitempty"` + + // The offset in bytes of the artifact within its containing artifact. + Offset *int `json:"offset,omitempty" yaml:"offset,omitempty" mapstructure:"offset,omitempty"` + + // Identifies the index of the immediate parent of the artifact, if this artifact + // is nested. + ParentIndex int `json:"parentIndex,omitempty" yaml:"parentIndex,omitempty" mapstructure:"parentIndex,omitempty"` + + // Key/value pairs that provide additional information about the artifact. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The role or roles played by the artifact in the analysis. + Roles []ArtifactRolesElem `json:"roles,omitempty" yaml:"roles,omitempty" mapstructure:"roles,omitempty"` + + // Specifies the source language for any artifact object that refers to a text + // file that contains source code. + SourceLanguage *string `json:"sourceLanguage,omitempty" yaml:"sourceLanguage,omitempty" mapstructure:"sourceLanguage,omitempty"` +} + +// A change to a single artifact. +type ArtifactChange struct { + // The location of the artifact to change. + ArtifactLocation ArtifactLocation `json:"artifactLocation" yaml:"artifactLocation" mapstructure:"artifactLocation"` + + // Key/value pairs that provide additional information about the change. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of replacement objects, each of which represents the replacement of a + // single region in a single artifact specified by 'artifactLocation'. + Replacements []Replacement `json:"replacements" yaml:"replacements" mapstructure:"replacements"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ArtifactChange) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["artifactLocation"]; raw != nil && !ok { + return fmt.Errorf("field artifactLocation in ArtifactChange: required") + } + if _, ok := raw["replacements"]; raw != nil && !ok { + return fmt.Errorf("field replacements in ArtifactChange: required") + } + type Plain ArtifactChange + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Replacements != nil && len(plain.Replacements) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "replacements", 1) + } + *j = ArtifactChange(plain) + return nil +} + + +// Represents the contents of an artifact. +type ArtifactContent struct { + // MIME Base64-encoded content from a binary artifact, or from a text artifact in + // its original encoding. + Binary *string `json:"binary,omitempty" yaml:"binary,omitempty" mapstructure:"binary,omitempty"` + + // Key/value pairs that provide additional information about the artifact content. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An alternate rendered representation of the artifact (e.g., a decompiled + // representation of a binary region). + Rendered *MultiformatMessageString `json:"rendered,omitempty" yaml:"rendered,omitempty" mapstructure:"rendered,omitempty"` + + // UTF-8-encoded content from a text artifact. + Text *string `json:"text,omitempty" yaml:"text,omitempty" mapstructure:"text,omitempty"` +} + +// A dictionary, each of whose keys is the name of a hash function and each of +// whose values is the hashed value of the artifact produced by the specified hash +// function. +type ArtifactHashes map[string]string + +// Specifies the location of an artifact. +type ArtifactLocation struct { + // A short description of the artifact location. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // The index within the run artifacts array of the artifact object associated with + // the artifact location. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // Key/value pairs that provide additional information about the artifact + // location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A string containing a valid relative or absolute URI. + Uri *string `json:"uri,omitempty" yaml:"uri,omitempty" mapstructure:"uri,omitempty"` + + // A string which indirectly specifies the absolute URI with respect to which a + // relative URI in the "uri" property is interpreted. + UriBaseId *string `json:"uriBaseId,omitempty" yaml:"uriBaseId,omitempty" mapstructure:"uriBaseId,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ArtifactLocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ArtifactLocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = ArtifactLocation(plain) + return nil +} + + +type ArtifactRolesElem string + +const ArtifactRolesElemAdded ArtifactRolesElem = "added" +const ArtifactRolesElemAnalysisTarget ArtifactRolesElem = "analysisTarget" +const ArtifactRolesElemAttachment ArtifactRolesElem = "attachment" +const ArtifactRolesElemDebugOutputFile ArtifactRolesElem = "debugOutputFile" +const ArtifactRolesElemDeleted ArtifactRolesElem = "deleted" +const ArtifactRolesElemDirectory ArtifactRolesElem = "directory" +const ArtifactRolesElemDriver ArtifactRolesElem = "driver" +const ArtifactRolesElemExtension ArtifactRolesElem = "extension" +const ArtifactRolesElemMemoryContents ArtifactRolesElem = "memoryContents" +const ArtifactRolesElemModified ArtifactRolesElem = "modified" +const ArtifactRolesElemPolicy ArtifactRolesElem = "policy" +const ArtifactRolesElemReferencedOnCommandLine ArtifactRolesElem = "referencedOnCommandLine" +const ArtifactRolesElemRenamed ArtifactRolesElem = "renamed" +const ArtifactRolesElemResponseFile ArtifactRolesElem = "responseFile" +const ArtifactRolesElemResultFile ArtifactRolesElem = "resultFile" +const ArtifactRolesElemStandardStream ArtifactRolesElem = "standardStream" +const ArtifactRolesElemTaxonomy ArtifactRolesElem = "taxonomy" +const ArtifactRolesElemToolSpecifiedConfiguration ArtifactRolesElem = "toolSpecifiedConfiguration" +const ArtifactRolesElemTracedFile ArtifactRolesElem = "tracedFile" +const ArtifactRolesElemTranslation ArtifactRolesElem = "translation" +const ArtifactRolesElemUncontrolled ArtifactRolesElem = "uncontrolled" +const ArtifactRolesElemUnmodified ArtifactRolesElem = "unmodified" +const ArtifactRolesElemUserSpecifiedConfiguration ArtifactRolesElem = "userSpecifiedConfiguration" +var enumValues_ArtifactRolesElem = []interface {}{ + "analysisTarget", + "attachment", + "responseFile", + "resultFile", + "standardStream", + "tracedFile", + "unmodified", + "modified", + "added", + "deleted", + "renamed", + "uncontrolled", + "driver", + "extension", + "translation", + "taxonomy", + "policy", + "referencedOnCommandLine", + "memoryContents", + "directory", + "userSpecifiedConfiguration", + "toolSpecifiedConfiguration", + "debugOutputFile", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ArtifactRolesElem) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ArtifactRolesElem { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ArtifactRolesElem, v) + } + *j = ArtifactRolesElem(v) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Artifact) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain Artifact + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["length"]; !ok || v == nil { + plain.Length = -1.0 + } + if -1 > plain.Length { + return fmt.Errorf("field %s: must be >= %v", "length", -1) + } + if plain.MimeType != nil { + if matched, _ := regexp.MatchString("[^/]+/.+", string(*plain.MimeType)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "[^/]+/.+", "MimeType") + } + } + if plain.Offset != nil && 0 >* plain.Offset { + return fmt.Errorf("field %s: must be >= %v", "offset", 0) + } + if v, ok := raw["parentIndex"]; !ok || v == nil { + plain.ParentIndex = -1.0 + } + if -1 > plain.ParentIndex { + return fmt.Errorf("field %s: must be >= %v", "parentIndex", -1) + } + if v, ok := raw["roles"]; !ok || v == nil { + plain.Roles = []ArtifactRolesElem{ +} + } + *j = Artifact(plain) + return nil +} + + +// An artifact relevant to a result. +type Attachment struct { + // The location of the attachment. + ArtifactLocation ArtifactLocation `json:"artifactLocation" yaml:"artifactLocation" mapstructure:"artifactLocation"` + + // A message describing the role played by the attachment. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // Key/value pairs that provide additional information about the attachment. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of rectangles specifying areas of interest within the image. + Rectangles []Rectangle `json:"rectangles,omitempty" yaml:"rectangles,omitempty" mapstructure:"rectangles,omitempty"` + + // An array of regions of interest within the attachment. + Regions []Region `json:"regions,omitempty" yaml:"regions,omitempty" mapstructure:"regions,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Attachment) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["artifactLocation"]; raw != nil && !ok { + return fmt.Errorf("field artifactLocation in Attachment: required") + } + type Plain Attachment + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["rectangles"]; !ok || v == nil { + plain.Rectangles = []Rectangle{ +} + } + if v, ok := raw["regions"]; !ok || v == nil { + plain.Regions = []Region{ +} + } + *j = Attachment(plain) + return nil +} + + +// A set of threadFlows which together describe a pattern of code execution +// relevant to detecting a result. +type CodeFlow struct { + // A message relevant to the code flow. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the code flow. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of one or more unique threadFlow objects, each of which describes the + // progress of a program through a thread of execution. + ThreadFlows []ThreadFlow `json:"threadFlows" yaml:"threadFlows" mapstructure:"threadFlows"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *CodeFlow) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["threadFlows"]; raw != nil && !ok { + return fmt.Errorf("field threadFlows in CodeFlow: required") + } + type Plain CodeFlow + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.ThreadFlows != nil && len(plain.ThreadFlows) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "threadFlows", 1) + } + *j = CodeFlow(plain) + return nil +} + + +// Information about how a specific rule or notification was reconfigured at +// runtime. +type ConfigurationOverride struct { + // Specifies how the rule or notification was configured during the scan. + Configuration ReportingConfiguration `json:"configuration" yaml:"configuration" mapstructure:"configuration"` + + // A reference used to locate the descriptor whose configuration was overridden. + Descriptor ReportingDescriptorReference `json:"descriptor" yaml:"descriptor" mapstructure:"descriptor"` + + // Key/value pairs that provide additional information about the configuration + // override. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ConfigurationOverride) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["configuration"]; raw != nil && !ok { + return fmt.Errorf("field configuration in ConfigurationOverride: required") + } + if _, ok := raw["descriptor"]; raw != nil && !ok { + return fmt.Errorf("field descriptor in ConfigurationOverride: required") + } + type Plain ConfigurationOverride + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = ConfigurationOverride(plain) + return nil +} + + +// Describes how a converter transformed the output of a static analysis tool from +// the analysis tool's native output format into the SARIF format. +type Conversion struct { + // The locations of the analysis tool's per-run log files. + AnalysisToolLogFiles []ArtifactLocation `json:"analysisToolLogFiles,omitempty" yaml:"analysisToolLogFiles,omitempty" mapstructure:"analysisToolLogFiles,omitempty"` + + // An invocation object that describes the invocation of the converter. + Invocation *Invocation `json:"invocation,omitempty" yaml:"invocation,omitempty" mapstructure:"invocation,omitempty"` + + // Key/value pairs that provide additional information about the conversion. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A tool object that describes the converter. + Tool Tool `json:"tool" yaml:"tool" mapstructure:"tool"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Conversion) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["tool"]; raw != nil && !ok { + return fmt.Errorf("field tool in Conversion: required") + } + type Plain Conversion + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["analysisToolLogFiles"]; !ok || v == nil { + plain.AnalysisToolLogFiles = []ArtifactLocation{ +} + } + *j = Conversion(plain) + return nil +} + + +// Represents a directed edge in a graph. +type Edge struct { + // A string that uniquely identifies the edge within its graph. + Id string `json:"id" yaml:"id" mapstructure:"id"` + + // A short description of the edge. + Label *Message `json:"label,omitempty" yaml:"label,omitempty" mapstructure:"label,omitempty"` + + // Key/value pairs that provide additional information about the edge. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Identifies the source node (the node at which the edge starts). + SourceNodeId string `json:"sourceNodeId" yaml:"sourceNodeId" mapstructure:"sourceNodeId"` + + // Identifies the target node (the node at which the edge ends). + TargetNodeId string `json:"targetNodeId" yaml:"targetNodeId" mapstructure:"targetNodeId"` +} + +// Represents the traversal of a single edge during a graph traversal. +type EdgeTraversal struct { + // Identifies the edge being traversed. + EdgeId string `json:"edgeId" yaml:"edgeId" mapstructure:"edgeId"` + + // The values of relevant expressions after the edge has been traversed. + FinalState EdgeTraversalFinalState `json:"finalState,omitempty" yaml:"finalState,omitempty" mapstructure:"finalState,omitempty"` + + // A message to display to the user as the edge is traversed. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the edge traversal. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The number of edge traversals necessary to return from a nested graph. + StepOverEdgeCount *int `json:"stepOverEdgeCount,omitempty" yaml:"stepOverEdgeCount,omitempty" mapstructure:"stepOverEdgeCount,omitempty"` +} + +// The values of relevant expressions after the edge has been traversed. +type EdgeTraversalFinalState map[string]MultiformatMessageString + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *EdgeTraversal) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["edgeId"]; raw != nil && !ok { + return fmt.Errorf("field edgeId in EdgeTraversal: required") + } + type Plain EdgeTraversal + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.StepOverEdgeCount != nil && 0 >* plain.StepOverEdgeCount { + return fmt.Errorf("field %s: must be >= %v", "stepOverEdgeCount", 0) + } + *j = EdgeTraversal(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Edge) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["id"]; raw != nil && !ok { + return fmt.Errorf("field id in Edge: required") + } + if _, ok := raw["sourceNodeId"]; raw != nil && !ok { + return fmt.Errorf("field sourceNodeId in Edge: required") + } + if _, ok := raw["targetNodeId"]; raw != nil && !ok { + return fmt.Errorf("field targetNodeId in Edge: required") + } + type Plain Edge + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = Edge(plain) + return nil +} + + +// Describes a runtime exception encountered during the execution of an analysis +// tool. +type Exception struct { + // An array of exception objects each of which is considered a cause of this + // exception. + InnerExceptions []*Exception `json:"innerExceptions,omitempty" yaml:"innerExceptions,omitempty" mapstructure:"innerExceptions,omitempty"` + + // A string that identifies the kind of exception, for example, the fully + // qualified type name of an object that was thrown, or the symbolic name of a + // signal. + Kind *string `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // A message that describes the exception. + Message *string `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the exception. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The sequence of function calls leading to the exception. + Stack *Stack `json:"stack,omitempty" yaml:"stack,omitempty" mapstructure:"stack,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Exception) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain Exception + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["innerExceptions"]; !ok || v == nil { + plain.InnerExceptions = []*Exception{ +} + } + *j = Exception(plain) + return nil +} + + +// The top-level element of an external property file. +type ExternalProperties struct { + // Addresses that will be merged with a separate run. + Addresses []Address `json:"addresses,omitempty" yaml:"addresses,omitempty" mapstructure:"addresses,omitempty"` + + // An array of artifact objects that will be merged with a separate run. + Artifacts []Artifact `json:"artifacts,omitempty" yaml:"artifacts,omitempty" mapstructure:"artifacts,omitempty"` + + // A conversion object that will be merged with a separate run. + Conversion *Conversion `json:"conversion,omitempty" yaml:"conversion,omitempty" mapstructure:"conversion,omitempty"` + + // The analysis tool object that will be merged with a separate run. + Driver *ToolComponent `json:"driver,omitempty" yaml:"driver,omitempty" mapstructure:"driver,omitempty"` + + // Tool extensions that will be merged with a separate run. + Extensions []ToolComponent `json:"extensions,omitempty" yaml:"extensions,omitempty" mapstructure:"extensions,omitempty"` + + // Key/value pairs that provide additional information that will be merged with a + // separate run. + ExternalizedProperties *PropertyBag `json:"externalizedProperties,omitempty" yaml:"externalizedProperties,omitempty" mapstructure:"externalizedProperties,omitempty"` + + // An array of graph objects that will be merged with a separate run. + Graphs []Graph `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // A stable, unique identifier for this external properties object, in the form of + // a GUID. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // Describes the invocation of the analysis tool that will be merged with a + // separate run. + Invocations []Invocation `json:"invocations,omitempty" yaml:"invocations,omitempty" mapstructure:"invocations,omitempty"` + + // An array of logical locations such as namespaces, types or functions that will + // be merged with a separate run. + LogicalLocations []LogicalLocation `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // Tool policies that will be merged with a separate run. + Policies []ToolComponent `json:"policies,omitempty" yaml:"policies,omitempty" mapstructure:"policies,omitempty"` + + // Key/value pairs that provide additional information about the external + // properties. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of result objects that will be merged with a separate run. + Results []Result `json:"results,omitempty" yaml:"results,omitempty" mapstructure:"results,omitempty"` + + // A stable, unique identifier for the run associated with this external + // properties object, in the form of a GUID. + RunGuid *string `json:"runGuid,omitempty" yaml:"runGuid,omitempty" mapstructure:"runGuid,omitempty"` + + // The URI of the JSON schema corresponding to the version of the external + // property file format. + Schema *string `json:"schema,omitempty" yaml:"schema,omitempty" mapstructure:"schema,omitempty"` + + // Tool taxonomies that will be merged with a separate run. + Taxonomies []ToolComponent `json:"taxonomies,omitempty" yaml:"taxonomies,omitempty" mapstructure:"taxonomies,omitempty"` + + // An array of threadFlowLocation objects that will be merged with a separate run. + ThreadFlowLocations []ThreadFlowLocation `json:"threadFlowLocations,omitempty" yaml:"threadFlowLocations,omitempty" mapstructure:"threadFlowLocations,omitempty"` + + // Tool translations that will be merged with a separate run. + Translations []ToolComponent `json:"translations,omitempty" yaml:"translations,omitempty" mapstructure:"translations,omitempty"` + + // The SARIF format version of this external properties object. + Version *ExternalPropertiesVersion `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` + + // Requests that will be merged with a separate run. + WebRequests []WebRequest `json:"webRequests,omitempty" yaml:"webRequests,omitempty" mapstructure:"webRequests,omitempty"` + + // Responses that will be merged with a separate run. + WebResponses []WebResponse `json:"webResponses,omitempty" yaml:"webResponses,omitempty" mapstructure:"webResponses,omitempty"` +} + +type ExternalPropertiesVersion string + +const ExternalPropertiesVersionA210 ExternalPropertiesVersion = "2.1.0" +var enumValues_ExternalPropertiesVersion = []interface {}{ + "2.1.0", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalPropertiesVersion) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ExternalPropertiesVersion { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ExternalPropertiesVersion, v) + } + *j = ExternalPropertiesVersion(v) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalProperties) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ExternalProperties + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["addresses"]; !ok || v == nil { + plain.Addresses = []Address{ +} + } + if v, ok := raw["extensions"]; !ok || v == nil { + plain.Extensions = []ToolComponent{ +} + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []Graph{ +} + } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + if v, ok := raw["invocations"]; !ok || v == nil { + plain.Invocations = []Invocation{ +} + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []LogicalLocation{ +} + } + if v, ok := raw["policies"]; !ok || v == nil { + plain.Policies = []ToolComponent{ +} + } + if v, ok := raw["results"]; !ok || v == nil { + plain.Results = []Result{ +} + } + if plain.RunGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.RunGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "RunGuid") + } + } + if v, ok := raw["taxonomies"]; !ok || v == nil { + plain.Taxonomies = []ToolComponent{ +} + } + if v, ok := raw["threadFlowLocations"]; !ok || v == nil { + plain.ThreadFlowLocations = []ThreadFlowLocation{ +} + } + if v, ok := raw["translations"]; !ok || v == nil { + plain.Translations = []ToolComponent{ +} + } + if v, ok := raw["webRequests"]; !ok || v == nil { + plain.WebRequests = []WebRequest{ +} + } + if v, ok := raw["webResponses"]; !ok || v == nil { + plain.WebResponses = []WebResponse{ +} + } + *j = ExternalProperties(plain) + return nil +} + + +// Contains information that enables a SARIF consumer to locate the external +// property file that contains the value of an externalized property associated +// with the run. +type ExternalPropertyFileReference struct { + // A stable, unique identifier for the external property file in the form of a + // GUID. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // A non-negative integer specifying the number of items contained in the external + // property file. + ItemCount int `json:"itemCount,omitempty" yaml:"itemCount,omitempty" mapstructure:"itemCount,omitempty"` + + // The location of the external property file. + Location *ArtifactLocation `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // Key/value pairs that provide additional information about the external property + // file. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalPropertyFileReference) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ExternalPropertyFileReference + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + if v, ok := raw["itemCount"]; !ok || v == nil { + plain.ItemCount = -1.0 + } + if -1 > plain.ItemCount { + return fmt.Errorf("field %s: must be >= %v", "itemCount", -1) + } + *j = ExternalPropertyFileReference(plain) + return nil +} + + +// References to external property files that should be inlined with the content of +// a root log file. +type ExternalPropertyFileReferences struct { + // An array of external property files containing run.addresses arrays to be + // merged with the root log file. + Addresses []ExternalPropertyFileReference `json:"addresses,omitempty" yaml:"addresses,omitempty" mapstructure:"addresses,omitempty"` + + // An array of external property files containing run.artifacts arrays to be + // merged with the root log file. + Artifacts []ExternalPropertyFileReference `json:"artifacts,omitempty" yaml:"artifacts,omitempty" mapstructure:"artifacts,omitempty"` + + // An external property file containing a run.conversion object to be merged with + // the root log file. + Conversion *ExternalPropertyFileReference `json:"conversion,omitempty" yaml:"conversion,omitempty" mapstructure:"conversion,omitempty"` + + // An external property file containing a run.driver object to be merged with the + // root log file. + Driver *ExternalPropertyFileReference `json:"driver,omitempty" yaml:"driver,omitempty" mapstructure:"driver,omitempty"` + + // An array of external property files containing run.extensions arrays to be + // merged with the root log file. + Extensions []ExternalPropertyFileReference `json:"extensions,omitempty" yaml:"extensions,omitempty" mapstructure:"extensions,omitempty"` + + // An external property file containing a run.properties object to be merged with + // the root log file. + ExternalizedProperties *ExternalPropertyFileReference `json:"externalizedProperties,omitempty" yaml:"externalizedProperties,omitempty" mapstructure:"externalizedProperties,omitempty"` + + // An array of external property files containing a run.graphs object to be merged + // with the root log file. + Graphs []ExternalPropertyFileReference `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // An array of external property files containing run.invocations arrays to be + // merged with the root log file. + Invocations []ExternalPropertyFileReference `json:"invocations,omitempty" yaml:"invocations,omitempty" mapstructure:"invocations,omitempty"` + + // An array of external property files containing run.logicalLocations arrays to + // be merged with the root log file. + LogicalLocations []ExternalPropertyFileReference `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // An array of external property files containing run.policies arrays to be merged + // with the root log file. + Policies []ExternalPropertyFileReference `json:"policies,omitempty" yaml:"policies,omitempty" mapstructure:"policies,omitempty"` + + // Key/value pairs that provide additional information about the external property + // files. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of external property files containing run.results arrays to be merged + // with the root log file. + Results []ExternalPropertyFileReference `json:"results,omitempty" yaml:"results,omitempty" mapstructure:"results,omitempty"` + + // An array of external property files containing run.taxonomies arrays to be + // merged with the root log file. + Taxonomies []ExternalPropertyFileReference `json:"taxonomies,omitempty" yaml:"taxonomies,omitempty" mapstructure:"taxonomies,omitempty"` + + // An array of external property files containing run.threadFlowLocations arrays + // to be merged with the root log file. + ThreadFlowLocations []ExternalPropertyFileReference `json:"threadFlowLocations,omitempty" yaml:"threadFlowLocations,omitempty" mapstructure:"threadFlowLocations,omitempty"` + + // An array of external property files containing run.translations arrays to be + // merged with the root log file. + Translations []ExternalPropertyFileReference `json:"translations,omitempty" yaml:"translations,omitempty" mapstructure:"translations,omitempty"` + + // An array of external property files containing run.requests arrays to be merged + // with the root log file. + WebRequests []ExternalPropertyFileReference `json:"webRequests,omitempty" yaml:"webRequests,omitempty" mapstructure:"webRequests,omitempty"` + + // An array of external property files containing run.responses arrays to be + // merged with the root log file. + WebResponses []ExternalPropertyFileReference `json:"webResponses,omitempty" yaml:"webResponses,omitempty" mapstructure:"webResponses,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalPropertyFileReferences) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ExternalPropertyFileReferences + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["addresses"]; !ok || v == nil { + plain.Addresses = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["artifacts"]; !ok || v == nil { + plain.Artifacts = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["extensions"]; !ok || v == nil { + plain.Extensions = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["invocations"]; !ok || v == nil { + plain.Invocations = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["policies"]; !ok || v == nil { + plain.Policies = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["results"]; !ok || v == nil { + plain.Results = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["taxonomies"]; !ok || v == nil { + plain.Taxonomies = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["threadFlowLocations"]; !ok || v == nil { + plain.ThreadFlowLocations = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["translations"]; !ok || v == nil { + plain.Translations = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["webRequests"]; !ok || v == nil { + plain.WebRequests = []ExternalPropertyFileReference{ +} + } + if v, ok := raw["webResponses"]; !ok || v == nil { + plain.WebResponses = []ExternalPropertyFileReference{ +} + } + *j = ExternalPropertyFileReferences(plain) + return nil +} + + +// A proposed fix for the problem represented by a result object. A fix specifies a +// set of artifacts to modify. For each artifact, it specifies a set of bytes to +// remove, and provides a set of new bytes to replace them. +type Fix struct { + // One or more artifact changes that comprise a fix for a result. + ArtifactChanges []ArtifactChange `json:"artifactChanges" yaml:"artifactChanges" mapstructure:"artifactChanges"` + + // A message that describes the proposed fix, enabling viewers to present the + // proposed change to an end user. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // Key/value pairs that provide additional information about the fix. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Fix) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["artifactChanges"]; raw != nil && !ok { + return fmt.Errorf("field artifactChanges in Fix: required") + } + type Plain Fix + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.ArtifactChanges != nil && len(plain.ArtifactChanges) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "artifactChanges", 1) + } + *j = Fix(plain) + return nil +} + + +// A network of nodes and directed edges that describes some aspect of the +// structure of the code (for example, a call graph). +type Graph struct { + // A description of the graph. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // An array of edge objects representing the edges of the graph. + Edges []Edge `json:"edges,omitempty" yaml:"edges,omitempty" mapstructure:"edges,omitempty"` + + // An array of node objects representing the nodes of the graph. + Nodes []Node `json:"nodes,omitempty" yaml:"nodes,omitempty" mapstructure:"nodes,omitempty"` + + // Key/value pairs that provide additional information about the graph. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// Represents a path through a graph. +type GraphTraversal struct { + // A description of this graph traversal. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // The sequences of edges traversed by this graph traversal. + EdgeTraversals []EdgeTraversal `json:"edgeTraversals,omitempty" yaml:"edgeTraversals,omitempty" mapstructure:"edgeTraversals,omitempty"` + + // Values of relevant expressions at the start of the graph traversal that remain + // constant for the graph traversal. + ImmutableState GraphTraversalImmutableState `json:"immutableState,omitempty" yaml:"immutableState,omitempty" mapstructure:"immutableState,omitempty"` + + // Values of relevant expressions at the start of the graph traversal that may + // change during graph traversal. + InitialState GraphTraversalInitialState `json:"initialState,omitempty" yaml:"initialState,omitempty" mapstructure:"initialState,omitempty"` + + // Key/value pairs that provide additional information about the graph traversal. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The index within the result.graphs to be associated with the result. + ResultGraphIndex int `json:"resultGraphIndex,omitempty" yaml:"resultGraphIndex,omitempty" mapstructure:"resultGraphIndex,omitempty"` + + // The index within the run.graphs to be associated with the result. + RunGraphIndex int `json:"runGraphIndex,omitempty" yaml:"runGraphIndex,omitempty" mapstructure:"runGraphIndex,omitempty"` +} + +// Values of relevant expressions at the start of the graph traversal that remain +// constant for the graph traversal. +type GraphTraversalImmutableState map[string]MultiformatMessageString + +// Values of relevant expressions at the start of the graph traversal that may +// change during graph traversal. +type GraphTraversalInitialState map[string]MultiformatMessageString + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *GraphTraversal) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain GraphTraversal + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["edgeTraversals"]; !ok || v == nil { + plain.EdgeTraversals = []EdgeTraversal{ +} + } + if v, ok := raw["resultGraphIndex"]; !ok || v == nil { + plain.ResultGraphIndex = -1.0 + } + if -1 > plain.ResultGraphIndex { + return fmt.Errorf("field %s: must be >= %v", "resultGraphIndex", -1) + } + if v, ok := raw["runGraphIndex"]; !ok || v == nil { + plain.RunGraphIndex = -1.0 + } + if -1 > plain.RunGraphIndex { + return fmt.Errorf("field %s: must be >= %v", "runGraphIndex", -1) + } + *j = GraphTraversal(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Graph) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain Graph + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["edges"]; !ok || v == nil { + plain.Edges = []Edge{ +} + } + if v, ok := raw["nodes"]; !ok || v == nil { + plain.Nodes = []Node{ +} + } + *j = Graph(plain) + return nil +} + + +// The runtime environment of the analysis tool run. +type Invocation struct { + // The account under which the invocation occurred. + Account *string `json:"account,omitempty" yaml:"account,omitempty" mapstructure:"account,omitempty"` + + // An array of strings, containing in order the command line arguments passed to + // the tool from the operating system. + Arguments []string `json:"arguments,omitempty" yaml:"arguments,omitempty" mapstructure:"arguments,omitempty"` + + // The command line used to invoke the tool. + CommandLine *string `json:"commandLine,omitempty" yaml:"commandLine,omitempty" mapstructure:"commandLine,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the invocation + // ended. See "Date/time properties" in the SARIF spec for the required format. + EndTimeUtc *time.Time `json:"endTimeUtc,omitempty" yaml:"endTimeUtc,omitempty" mapstructure:"endTimeUtc,omitempty"` + + // The environment variables associated with the analysis tool process, expressed + // as key/value pairs. + EnvironmentVariables InvocationEnvironmentVariables `json:"environmentVariables,omitempty" yaml:"environmentVariables,omitempty" mapstructure:"environmentVariables,omitempty"` + + // An absolute URI specifying the location of the executable that was invoked. + ExecutableLocation *ArtifactLocation `json:"executableLocation,omitempty" yaml:"executableLocation,omitempty" mapstructure:"executableLocation,omitempty"` + + // Specifies whether the tool's execution completed successfully. + ExecutionSuccessful bool `json:"executionSuccessful" yaml:"executionSuccessful" mapstructure:"executionSuccessful"` + + // The process exit code. + ExitCode *int `json:"exitCode,omitempty" yaml:"exitCode,omitempty" mapstructure:"exitCode,omitempty"` + + // The reason for the process exit. + ExitCodeDescription *string `json:"exitCodeDescription,omitempty" yaml:"exitCodeDescription,omitempty" mapstructure:"exitCodeDescription,omitempty"` + + // The name of the signal that caused the process to exit. + ExitSignalName *string `json:"exitSignalName,omitempty" yaml:"exitSignalName,omitempty" mapstructure:"exitSignalName,omitempty"` + + // The numeric value of the signal that caused the process to exit. + ExitSignalNumber *int `json:"exitSignalNumber,omitempty" yaml:"exitSignalNumber,omitempty" mapstructure:"exitSignalNumber,omitempty"` + + // The machine on which the invocation occurred. + Machine *string `json:"machine,omitempty" yaml:"machine,omitempty" mapstructure:"machine,omitempty"` + + // An array of configurationOverride objects that describe notifications related + // runtime overrides. + NotificationConfigurationOverrides []ConfigurationOverride `json:"notificationConfigurationOverrides,omitempty" yaml:"notificationConfigurationOverrides,omitempty" mapstructure:"notificationConfigurationOverrides,omitempty"` + + // The id of the process in which the invocation occurred. + ProcessId *int `json:"processId,omitempty" yaml:"processId,omitempty" mapstructure:"processId,omitempty"` + + // The reason given by the operating system that the process failed to start. + ProcessStartFailureMessage *string `json:"processStartFailureMessage,omitempty" yaml:"processStartFailureMessage,omitempty" mapstructure:"processStartFailureMessage,omitempty"` + + // Key/value pairs that provide additional information about the invocation. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The locations of any response files specified on the tool's command line. + ResponseFiles []ArtifactLocation `json:"responseFiles,omitempty" yaml:"responseFiles,omitempty" mapstructure:"responseFiles,omitempty"` + + // An array of configurationOverride objects that describe rules related runtime + // overrides. + RuleConfigurationOverrides []ConfigurationOverride `json:"ruleConfigurationOverrides,omitempty" yaml:"ruleConfigurationOverrides,omitempty" mapstructure:"ruleConfigurationOverrides,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the invocation + // started. See "Date/time properties" in the SARIF spec for the required format. + StartTimeUtc *time.Time `json:"startTimeUtc,omitempty" yaml:"startTimeUtc,omitempty" mapstructure:"startTimeUtc,omitempty"` + + // A file containing the standard error stream from the process that was invoked. + Stderr *ArtifactLocation `json:"stderr,omitempty" yaml:"stderr,omitempty" mapstructure:"stderr,omitempty"` + + // A file containing the standard input stream to the process that was invoked. + Stdin *ArtifactLocation `json:"stdin,omitempty" yaml:"stdin,omitempty" mapstructure:"stdin,omitempty"` + + // A file containing the standard output stream from the process that was invoked. + Stdout *ArtifactLocation `json:"stdout,omitempty" yaml:"stdout,omitempty" mapstructure:"stdout,omitempty"` + + // A file containing the interleaved standard output and standard error stream + // from the process that was invoked. + StdoutStderr *ArtifactLocation `json:"stdoutStderr,omitempty" yaml:"stdoutStderr,omitempty" mapstructure:"stdoutStderr,omitempty"` + + // A list of conditions detected by the tool that are relevant to the tool's + // configuration. + ToolConfigurationNotifications []Notification `json:"toolConfigurationNotifications,omitempty" yaml:"toolConfigurationNotifications,omitempty" mapstructure:"toolConfigurationNotifications,omitempty"` + + // A list of runtime conditions detected by the tool during the analysis. + ToolExecutionNotifications []Notification `json:"toolExecutionNotifications,omitempty" yaml:"toolExecutionNotifications,omitempty" mapstructure:"toolExecutionNotifications,omitempty"` + + // The working directory for the invocation. + WorkingDirectory *ArtifactLocation `json:"workingDirectory,omitempty" yaml:"workingDirectory,omitempty" mapstructure:"workingDirectory,omitempty"` +} + +// The environment variables associated with the analysis tool process, expressed +// as key/value pairs. +type InvocationEnvironmentVariables map[string]string + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Invocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["executionSuccessful"]; raw != nil && !ok { + return fmt.Errorf("field executionSuccessful in Invocation: required") + } + type Plain Invocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["notificationConfigurationOverrides"]; !ok || v == nil { + plain.NotificationConfigurationOverrides = []ConfigurationOverride{ +} + } + if v, ok := raw["ruleConfigurationOverrides"]; !ok || v == nil { + plain.RuleConfigurationOverrides = []ConfigurationOverride{ +} + } + if v, ok := raw["toolConfigurationNotifications"]; !ok || v == nil { + plain.ToolConfigurationNotifications = []Notification{ +} + } + if v, ok := raw["toolExecutionNotifications"]; !ok || v == nil { + plain.ToolExecutionNotifications = []Notification{ +} + } + *j = Invocation(plain) + return nil +} + + +// A location within a programming artifact. +type Location struct { + // A set of regions relevant to the location. + Annotations []Region `json:"annotations,omitempty" yaml:"annotations,omitempty" mapstructure:"annotations,omitempty"` + + // Value that distinguishes this location from all other locations within a single + // result object. + Id int `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // The logical locations associated with the result. + LogicalLocations []LogicalLocation `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // A message relevant to the location. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Identifies the artifact and region. + PhysicalLocation *PhysicalLocation `json:"physicalLocation,omitempty" yaml:"physicalLocation,omitempty" mapstructure:"physicalLocation,omitempty"` + + // Key/value pairs that provide additional information about the location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of objects that describe relationships between this location and + // others. + Relationships []LocationRelationship `json:"relationships,omitempty" yaml:"relationships,omitempty" mapstructure:"relationships,omitempty"` +} + +// Information about the relation of one location to another. +type LocationRelationship struct { + // A description of the location relationship. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // A set of distinct strings that categorize the relationship. Well-known kinds + // include 'includes', 'isIncludedBy' and 'relevant'. + Kinds []string `json:"kinds,omitempty" yaml:"kinds,omitempty" mapstructure:"kinds,omitempty"` + + // Key/value pairs that provide additional information about the location + // relationship. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A reference to the related location. + Target int `json:"target" yaml:"target" mapstructure:"target"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *LocationRelationship) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["target"]; raw != nil && !ok { + return fmt.Errorf("field target in LocationRelationship: required") + } + type Plain LocationRelationship + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["kinds"]; !ok || v == nil { + plain.Kinds = []string{ +"relevant", +} + } + if 0 > plain.Target { + return fmt.Errorf("field %s: must be >= %v", "target", 0) + } + *j = LocationRelationship(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Location) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain Location + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["annotations"]; !ok || v == nil { + plain.Annotations = []Region{ +} + } + if v, ok := raw["id"]; !ok || v == nil { + plain.Id = -1.0 + } + if -1 > plain.Id { + return fmt.Errorf("field %s: must be >= %v", "id", -1) + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []LogicalLocation{ +} + } + if v, ok := raw["relationships"]; !ok || v == nil { + plain.Relationships = []LocationRelationship{ +} + } + *j = Location(plain) + return nil +} + + +// A logical location of a construct that produced a result. +type LogicalLocation struct { + // The machine-readable name for the logical location, such as a mangled function + // name provided by a C++ compiler that encodes calling convention, return type + // and other details along with the function name. + DecoratedName *string `json:"decoratedName,omitempty" yaml:"decoratedName,omitempty" mapstructure:"decoratedName,omitempty"` + + // The human-readable fully qualified name of the logical location. + FullyQualifiedName *string `json:"fullyQualifiedName,omitempty" yaml:"fullyQualifiedName,omitempty" mapstructure:"fullyQualifiedName,omitempty"` + + // The index within the logical locations array. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // The type of construct this logical location component refers to. Should be one + // of 'function', 'member', 'module', 'namespace', 'parameter', 'resource', + // 'returnType', 'type', 'variable', 'object', 'array', 'property', 'value', + // 'element', 'text', 'attribute', 'comment', 'declaration', 'dtd' or + // 'processingInstruction', if any of those accurately describe the construct. + Kind *string `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // Identifies the construct in which the result occurred. For example, this + // property might contain the name of a class or a method. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // Identifies the index of the immediate parent of the construct in which the + // result was detected. For example, this property might point to a logical + // location that represents the namespace that holds a type. + ParentIndex int `json:"parentIndex,omitempty" yaml:"parentIndex,omitempty" mapstructure:"parentIndex,omitempty"` + + // Key/value pairs that provide additional information about the logical location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *LogicalLocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain LogicalLocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["parentIndex"]; !ok || v == nil { + plain.ParentIndex = -1.0 + } + if -1 > plain.ParentIndex { + return fmt.Errorf("field %s: must be >= %v", "parentIndex", -1) + } + *j = LogicalLocation(plain) + return nil +} + + +// Encapsulates a message intended to be read by the end user. +type Message struct { + // An array of strings to substitute into the message string. + Arguments []string `json:"arguments,omitempty" yaml:"arguments,omitempty" mapstructure:"arguments,omitempty"` + + // The identifier for this message. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // A Markdown message string. + Markdown *string `json:"markdown,omitempty" yaml:"markdown,omitempty" mapstructure:"markdown,omitempty"` + + // Key/value pairs that provide additional information about the message. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A plain text message string. + Text *string `json:"text,omitempty" yaml:"text,omitempty" mapstructure:"text,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Message) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain Message + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["arguments"]; !ok || v == nil { + plain.Arguments = []string{ +} + } + *j = Message(plain) + return nil +} + + +// A message string or message format string rendered in multiple formats. +type MultiformatMessageString struct { + // A Markdown message string or format string. + Markdown *string `json:"markdown,omitempty" yaml:"markdown,omitempty" mapstructure:"markdown,omitempty"` + + // Key/value pairs that provide additional information about the message. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A plain text message string or format string. + Text string `json:"text" yaml:"text" mapstructure:"text"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *MultiformatMessageString) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["text"]; raw != nil && !ok { + return fmt.Errorf("field text in MultiformatMessageString: required") + } + type Plain MultiformatMessageString + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = MultiformatMessageString(plain) + return nil +} + + +// Represents a node in a graph. +type Node struct { + // Array of child nodes. + Children []*Node `json:"children,omitempty" yaml:"children,omitempty" mapstructure:"children,omitempty"` + + // A string that uniquely identifies the node within its graph. + Id string `json:"id" yaml:"id" mapstructure:"id"` + + // A short description of the node. + Label *Message `json:"label,omitempty" yaml:"label,omitempty" mapstructure:"label,omitempty"` + + // A code location associated with the node. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // Key/value pairs that provide additional information about the node. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Node) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["id"]; raw != nil && !ok { + return fmt.Errorf("field id in Node: required") + } + type Plain Node + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["children"]; !ok || v == nil { + plain.Children = []*Node{ +} + } + *j = Node(plain) + return nil +} + + +// Describes a condition relevant to the tool itself, as opposed to being relevant +// to a target being analyzed by the tool. +type Notification struct { + // A reference used to locate the rule descriptor associated with this + // notification. + AssociatedRule *ReportingDescriptorReference `json:"associatedRule,omitempty" yaml:"associatedRule,omitempty" mapstructure:"associatedRule,omitempty"` + + // A reference used to locate the descriptor relevant to this notification. + Descriptor *ReportingDescriptorReference `json:"descriptor,omitempty" yaml:"descriptor,omitempty" mapstructure:"descriptor,omitempty"` + + // The runtime exception, if any, relevant to this notification. + Exception *Exception `json:"exception,omitempty" yaml:"exception,omitempty" mapstructure:"exception,omitempty"` + + // A value specifying the severity level of the notification. + Level NotificationLevel `json:"level,omitempty" yaml:"level,omitempty" mapstructure:"level,omitempty"` + + // The locations relevant to this notification. + Locations []Location `json:"locations,omitempty" yaml:"locations,omitempty" mapstructure:"locations,omitempty"` + + // A message that describes the condition that was encountered. + Message Message `json:"message" yaml:"message" mapstructure:"message"` + + // Key/value pairs that provide additional information about the notification. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The thread identifier of the code that generated the notification. + ThreadId *int `json:"threadId,omitempty" yaml:"threadId,omitempty" mapstructure:"threadId,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the analysis tool + // generated the notification. + TimeUtc *time.Time `json:"timeUtc,omitempty" yaml:"timeUtc,omitempty" mapstructure:"timeUtc,omitempty"` +} + +type NotificationLevel string + +const NotificationLevelError NotificationLevel = "error" +const NotificationLevelNone NotificationLevel = "none" +const NotificationLevelNote NotificationLevel = "note" +const NotificationLevelWarning NotificationLevel = "warning" +var enumValues_NotificationLevel = []interface {}{ + "none", + "note", + "warning", + "error", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *NotificationLevel) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_NotificationLevel { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_NotificationLevel, v) + } + *j = NotificationLevel(v) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Notification) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["message"]; raw != nil && !ok { + return fmt.Errorf("field message in Notification: required") + } + type Plain Notification + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["level"]; !ok || v == nil { + plain.Level = "warning" + } + if v, ok := raw["locations"]; !ok || v == nil { + plain.Locations = []Location{ +} + } + *j = Notification(plain) + return nil +} + + +// A physical location relevant to a result. Specifies a reference to a programming +// artifact together with a range of bytes or characters within that artifact. +type PhysicalLocation struct { + // The address of the location. + Address *Address `json:"address,omitempty" yaml:"address,omitempty" mapstructure:"address,omitempty"` + + // The location of the artifact. + ArtifactLocation *ArtifactLocation `json:"artifactLocation,omitempty" yaml:"artifactLocation,omitempty" mapstructure:"artifactLocation,omitempty"` + + // Specifies a portion of the artifact that encloses the region. Allows a viewer + // to display additional context around the region. + ContextRegion *Region `json:"contextRegion,omitempty" yaml:"contextRegion,omitempty" mapstructure:"contextRegion,omitempty"` + + // Key/value pairs that provide additional information about the physical + // location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Specifies a portion of the artifact. + Region *Region `json:"region,omitempty" yaml:"region,omitempty" mapstructure:"region,omitempty"` +} + +// Key/value pairs that provide additional information about the object. +type PropertyBag struct { + // A set of distinct strings that provide additional information. + Tags []string `json:"tags,omitempty" yaml:"tags,omitempty" mapstructure:"tags,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *PropertyBag) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain PropertyBag + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["tags"]; !ok || v == nil { + plain.Tags = []string{ +} + } + st := reflect.TypeOf(Plain{}) + for i := range st.NumField() { + delete(raw, st.Field(i).Name) + delete(raw, strings.Split(st.Field(i).Tag.Get("json"), ",")[0]) + } + if err := mapstructure.Decode(raw, &plain.AdditionalProperties); err != nil { + return err + } + *j = PropertyBag(plain) + return nil +} + + +// An area within an image. +type Rectangle struct { + // The Y coordinate of the bottom edge of the rectangle, measured in the image's + // natural units. + Bottom *float64 `json:"bottom,omitempty" yaml:"bottom,omitempty" mapstructure:"bottom,omitempty"` + + // The X coordinate of the left edge of the rectangle, measured in the image's + // natural units. + Left *float64 `json:"left,omitempty" yaml:"left,omitempty" mapstructure:"left,omitempty"` + + // A message relevant to the rectangle. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the rectangle. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The X coordinate of the right edge of the rectangle, measured in the image's + // natural units. + Right *float64 `json:"right,omitempty" yaml:"right,omitempty" mapstructure:"right,omitempty"` + + // The Y coordinate of the top edge of the rectangle, measured in the image's + // natural units. + Top *float64 `json:"top,omitempty" yaml:"top,omitempty" mapstructure:"top,omitempty"` +} + +// A region within an artifact where a result was detected. +type Region struct { + // The length of the region in bytes. + ByteLength *int `json:"byteLength,omitempty" yaml:"byteLength,omitempty" mapstructure:"byteLength,omitempty"` + + // The zero-based offset from the beginning of the artifact of the first byte in + // the region. + ByteOffset int `json:"byteOffset,omitempty" yaml:"byteOffset,omitempty" mapstructure:"byteOffset,omitempty"` + + // The length of the region in characters. + CharLength *int `json:"charLength,omitempty" yaml:"charLength,omitempty" mapstructure:"charLength,omitempty"` + + // The zero-based offset from the beginning of the artifact of the first character + // in the region. + CharOffset int `json:"charOffset,omitempty" yaml:"charOffset,omitempty" mapstructure:"charOffset,omitempty"` + + // The column number of the character following the end of the region. + EndColumn *int `json:"endColumn,omitempty" yaml:"endColumn,omitempty" mapstructure:"endColumn,omitempty"` + + // The line number of the last character in the region. + EndLine *int `json:"endLine,omitempty" yaml:"endLine,omitempty" mapstructure:"endLine,omitempty"` + + // A message relevant to the region. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the region. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The portion of the artifact contents within the specified region. + Snippet *ArtifactContent `json:"snippet,omitempty" yaml:"snippet,omitempty" mapstructure:"snippet,omitempty"` + + // Specifies the source language, if any, of the portion of the artifact specified + // by the region object. + SourceLanguage *string `json:"sourceLanguage,omitempty" yaml:"sourceLanguage,omitempty" mapstructure:"sourceLanguage,omitempty"` + + // The column number of the first character in the region. + StartColumn *int `json:"startColumn,omitempty" yaml:"startColumn,omitempty" mapstructure:"startColumn,omitempty"` + + // The line number of the first character in the region. + StartLine *int `json:"startLine,omitempty" yaml:"startLine,omitempty" mapstructure:"startLine,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Region) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain Region + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.ByteLength != nil && 0 >* plain.ByteLength { + return fmt.Errorf("field %s: must be >= %v", "byteLength", 0) + } + if v, ok := raw["byteOffset"]; !ok || v == nil { + plain.ByteOffset = -1.0 + } + if -1 > plain.ByteOffset { + return fmt.Errorf("field %s: must be >= %v", "byteOffset", -1) + } + if plain.CharLength != nil && 0 >* plain.CharLength { + return fmt.Errorf("field %s: must be >= %v", "charLength", 0) + } + if v, ok := raw["charOffset"]; !ok || v == nil { + plain.CharOffset = -1.0 + } + if -1 > plain.CharOffset { + return fmt.Errorf("field %s: must be >= %v", "charOffset", -1) + } + if plain.EndColumn != nil && 1 >* plain.EndColumn { + return fmt.Errorf("field %s: must be >= %v", "endColumn", 1) + } + if plain.EndLine != nil && 1 >* plain.EndLine { + return fmt.Errorf("field %s: must be >= %v", "endLine", 1) + } + if plain.StartColumn != nil && 1 >* plain.StartColumn { + return fmt.Errorf("field %s: must be >= %v", "startColumn", 1) + } + if plain.StartLine != nil && 1 >* plain.StartLine { + return fmt.Errorf("field %s: must be >= %v", "startLine", 1) + } + *j = Region(plain) + return nil +} + + +// The replacement of a single region of an artifact. +type Replacement struct { + // The region of the artifact to delete. + DeletedRegion Region `json:"deletedRegion" yaml:"deletedRegion" mapstructure:"deletedRegion"` + + // The content to insert at the location specified by the 'deletedRegion' + // property. + InsertedContent *ArtifactContent `json:"insertedContent,omitempty" yaml:"insertedContent,omitempty" mapstructure:"insertedContent,omitempty"` + + // Key/value pairs that provide additional information about the replacement. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Replacement) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["deletedRegion"]; raw != nil && !ok { + return fmt.Errorf("field deletedRegion in Replacement: required") + } + type Plain Replacement + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = Replacement(plain) + return nil +} + + +// Information about a rule or notification that can be configured at runtime. +type ReportingConfiguration struct { + // Specifies whether the report may be produced during the scan. + Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty" mapstructure:"enabled,omitempty"` + + // Specifies the failure level for the report. + Level ReportingConfigurationLevel `json:"level,omitempty" yaml:"level,omitempty" mapstructure:"level,omitempty"` + + // Contains configuration information specific to a report. + Parameters *PropertyBag `json:"parameters,omitempty" yaml:"parameters,omitempty" mapstructure:"parameters,omitempty"` + + // Key/value pairs that provide additional information about the reporting + // configuration. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Specifies the relative priority of the report. Used for analysis output only. + Rank float64 `json:"rank,omitempty" yaml:"rank,omitempty" mapstructure:"rank,omitempty"` +} + +type ReportingConfigurationLevel string + +const ReportingConfigurationLevelError ReportingConfigurationLevel = "error" +const ReportingConfigurationLevelNone ReportingConfigurationLevel = "none" +const ReportingConfigurationLevelNote ReportingConfigurationLevel = "note" +const ReportingConfigurationLevelWarning ReportingConfigurationLevel = "warning" +var enumValues_ReportingConfigurationLevel = []interface {}{ + "none", + "note", + "warning", + "error", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingConfigurationLevel) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ReportingConfigurationLevel { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ReportingConfigurationLevel, v) + } + *j = ReportingConfigurationLevel(v) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingConfiguration) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ReportingConfiguration + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["enabled"]; !ok || v == nil { + plain.Enabled = true + } + if v, ok := raw["level"]; !ok || v == nil { + plain.Level = "warning" + } + if v, ok := raw["rank"]; !ok || v == nil { + plain.Rank = -1.0 + } + if 100 < plain.Rank { + return fmt.Errorf("field %s: must be <= %v", "rank", 100) + } + if -1 > plain.Rank { + return fmt.Errorf("field %s: must be >= %v", "rank", -1) + } + *j = ReportingConfiguration(plain) + return nil +} + + +// Metadata that describes a specific report produced by the tool, as part of the +// analysis it provides or its runtime reporting. +type ReportingDescriptor struct { + // Default reporting configuration information. + DefaultConfiguration *ReportingConfiguration `json:"defaultConfiguration,omitempty" yaml:"defaultConfiguration,omitempty" mapstructure:"defaultConfiguration,omitempty"` + + // An array of unique identifies in the form of a GUID by which this report was + // known in some previous version of the analysis tool. + DeprecatedGuids []string `json:"deprecatedGuids,omitempty" yaml:"deprecatedGuids,omitempty" mapstructure:"deprecatedGuids,omitempty"` + + // An array of stable, opaque identifiers by which this report was known in some + // previous version of the analysis tool. + DeprecatedIds []string `json:"deprecatedIds,omitempty" yaml:"deprecatedIds,omitempty" mapstructure:"deprecatedIds,omitempty"` + + // An array of readable identifiers by which this report was known in some + // previous version of the analysis tool. + DeprecatedNames []string `json:"deprecatedNames,omitempty" yaml:"deprecatedNames,omitempty" mapstructure:"deprecatedNames,omitempty"` + + // A description of the report. Should, as far as possible, provide details + // sufficient to enable resolution of any problem indicated by the result. + FullDescription *MultiformatMessageString `json:"fullDescription,omitempty" yaml:"fullDescription,omitempty" mapstructure:"fullDescription,omitempty"` + + // A unique identifier for the reporting descriptor in the form of a GUID. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // Provides the primary documentation for the report, useful when there is no + // online documentation. + Help *MultiformatMessageString `json:"help,omitempty" yaml:"help,omitempty" mapstructure:"help,omitempty"` + + // A URI where the primary documentation for the report can be found. + HelpUri *string `json:"helpUri,omitempty" yaml:"helpUri,omitempty" mapstructure:"helpUri,omitempty"` + + // A stable, opaque identifier for the report. + Id string `json:"id" yaml:"id" mapstructure:"id"` + + // A set of name/value pairs with arbitrary names. Each value is a + // multiformatMessageString object, which holds message strings in plain text and + // (optionally) Markdown format. The strings can include placeholders, which can + // be used to construct a message in combination with an arbitrary number of + // additional string arguments. + MessageStrings ReportingDescriptorMessageStrings `json:"messageStrings,omitempty" yaml:"messageStrings,omitempty" mapstructure:"messageStrings,omitempty"` + + // A report identifier that is understandable to an end user. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // Key/value pairs that provide additional information about the report. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of objects that describe relationships between this reporting + // descriptor and others. + Relationships []ReportingDescriptorRelationship `json:"relationships,omitempty" yaml:"relationships,omitempty" mapstructure:"relationships,omitempty"` + + // A concise description of the report. Should be a single sentence that is + // understandable when visible space is limited to a single line of text. + ShortDescription *MultiformatMessageString `json:"shortDescription,omitempty" yaml:"shortDescription,omitempty" mapstructure:"shortDescription,omitempty"` +} + +// A set of name/value pairs with arbitrary names. Each value is a +// multiformatMessageString object, which holds message strings in plain text and +// (optionally) Markdown format. The strings can include placeholders, which can be +// used to construct a message in combination with an arbitrary number of +// additional string arguments. +type ReportingDescriptorMessageStrings map[string]MultiformatMessageString + +// Information about how to locate a relevant reporting descriptor. +type ReportingDescriptorReference struct { + // A guid that uniquely identifies the descriptor. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // The id of the descriptor. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // The index into an array of descriptors in toolComponent.ruleDescriptors, + // toolComponent.notificationDescriptors, or toolComponent.taxonomyDescriptors, + // depending on context. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // Key/value pairs that provide additional information about the reporting + // descriptor reference. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A reference used to locate the toolComponent associated with the descriptor. + ToolComponent *ToolComponentReference `json:"toolComponent,omitempty" yaml:"toolComponent,omitempty" mapstructure:"toolComponent,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingDescriptorReference) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ReportingDescriptorReference + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = ReportingDescriptorReference(plain) + return nil +} + + +// Information about the relation of one reporting descriptor to another. +type ReportingDescriptorRelationship struct { + // A description of the reporting descriptor relationship. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // A set of distinct strings that categorize the relationship. Well-known kinds + // include 'canPrecede', 'canFollow', 'willPrecede', 'willFollow', 'superset', + // 'subset', 'equal', 'disjoint', 'relevant', and 'incomparable'. + Kinds []string `json:"kinds,omitempty" yaml:"kinds,omitempty" mapstructure:"kinds,omitempty"` + + // Key/value pairs that provide additional information about the reporting + // descriptor reference. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A reference to the related reporting descriptor. + Target ReportingDescriptorReference `json:"target" yaml:"target" mapstructure:"target"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingDescriptorRelationship) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["target"]; raw != nil && !ok { + return fmt.Errorf("field target in ReportingDescriptorRelationship: required") + } + type Plain ReportingDescriptorRelationship + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["kinds"]; !ok || v == nil { + plain.Kinds = []string{ +"relevant", +} + } + *j = ReportingDescriptorRelationship(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingDescriptor) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["id"]; raw != nil && !ok { + return fmt.Errorf("field id in ReportingDescriptor: required") + } + type Plain ReportingDescriptor + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + if v, ok := raw["relationships"]; !ok || v == nil { + plain.Relationships = []ReportingDescriptorRelationship{ +} + } + *j = ReportingDescriptor(plain) + return nil +} + + +// A result produced by an analysis tool. +type Result struct { + // Identifies the artifact that the analysis tool was instructed to scan. This + // need not be the same as the artifact where the result actually occurred. + AnalysisTarget *ArtifactLocation `json:"analysisTarget,omitempty" yaml:"analysisTarget,omitempty" mapstructure:"analysisTarget,omitempty"` + + // A set of artifacts relevant to the result. + Attachments []Attachment `json:"attachments,omitempty" yaml:"attachments,omitempty" mapstructure:"attachments,omitempty"` + + // The state of a result relative to a baseline of a previous run. + BaselineState *ResultBaselineState `json:"baselineState,omitempty" yaml:"baselineState,omitempty" mapstructure:"baselineState,omitempty"` + + // An array of 'codeFlow' objects relevant to the result. + CodeFlows []CodeFlow `json:"codeFlows,omitempty" yaml:"codeFlows,omitempty" mapstructure:"codeFlows,omitempty"` + + // A stable, unique identifier for the equivalence class of logically identical + // results to which this result belongs, in the form of a GUID. + CorrelationGuid *string `json:"correlationGuid,omitempty" yaml:"correlationGuid,omitempty" mapstructure:"correlationGuid,omitempty"` + + // A set of strings each of which individually defines a stable, unique identity + // for the result. + Fingerprints ResultFingerprints `json:"fingerprints,omitempty" yaml:"fingerprints,omitempty" mapstructure:"fingerprints,omitempty"` + + // An array of 'fix' objects, each of which represents a proposed fix to the + // problem indicated by the result. + Fixes []Fix `json:"fixes,omitempty" yaml:"fixes,omitempty" mapstructure:"fixes,omitempty"` + + // An array of one or more unique 'graphTraversal' objects. + GraphTraversals []GraphTraversal `json:"graphTraversals,omitempty" yaml:"graphTraversals,omitempty" mapstructure:"graphTraversals,omitempty"` + + // An array of zero or more unique graph objects associated with the result. + Graphs []Graph `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // A stable, unique identifier for the result in the form of a GUID. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // An absolute URI at which the result can be viewed. + HostedViewerUri *string `json:"hostedViewerUri,omitempty" yaml:"hostedViewerUri,omitempty" mapstructure:"hostedViewerUri,omitempty"` + + // A value that categorizes results by evaluation state. + Kind ResultKind `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // A value specifying the severity level of the result. + Level ResultLevel `json:"level,omitempty" yaml:"level,omitempty" mapstructure:"level,omitempty"` + + // The set of locations where the result was detected. Specify only one location + // unless the problem indicated by the result can only be corrected by making a + // change at every specified location. + Locations []Location `json:"locations,omitempty" yaml:"locations,omitempty" mapstructure:"locations,omitempty"` + + // A message that describes the result. The first sentence of the message only + // will be displayed when visible space is limited. + Message Message `json:"message" yaml:"message" mapstructure:"message"` + + // A positive integer specifying the number of times this logically unique result + // was observed in this run. + OccurrenceCount *int `json:"occurrenceCount,omitempty" yaml:"occurrenceCount,omitempty" mapstructure:"occurrenceCount,omitempty"` + + // A set of strings that contribute to the stable, unique identity of the result. + PartialFingerprints ResultPartialFingerprints `json:"partialFingerprints,omitempty" yaml:"partialFingerprints,omitempty" mapstructure:"partialFingerprints,omitempty"` + + // Key/value pairs that provide additional information about the result. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Information about how and when the result was detected. + Provenance *ResultProvenance `json:"provenance,omitempty" yaml:"provenance,omitempty" mapstructure:"provenance,omitempty"` + + // A number representing the priority or importance of the result. + Rank float64 `json:"rank,omitempty" yaml:"rank,omitempty" mapstructure:"rank,omitempty"` + + // A set of locations relevant to this result. + RelatedLocations []Location `json:"relatedLocations,omitempty" yaml:"relatedLocations,omitempty" mapstructure:"relatedLocations,omitempty"` + + // A reference used to locate the rule descriptor relevant to this result. + Rule *ReportingDescriptorReference `json:"rule,omitempty" yaml:"rule,omitempty" mapstructure:"rule,omitempty"` + + // The stable, unique identifier of the rule, if any, to which this result is + // relevant. + RuleId *string `json:"ruleId,omitempty" yaml:"ruleId,omitempty" mapstructure:"ruleId,omitempty"` + + // The index within the tool component rules array of the rule object associated + // with this result. + RuleIndex int `json:"ruleIndex,omitempty" yaml:"ruleIndex,omitempty" mapstructure:"ruleIndex,omitempty"` + + // An array of 'stack' objects relevant to the result. + Stacks []Stack `json:"stacks,omitempty" yaml:"stacks,omitempty" mapstructure:"stacks,omitempty"` + + // A set of suppressions relevant to this result. + Suppressions []Suppression `json:"suppressions,omitempty" yaml:"suppressions,omitempty" mapstructure:"suppressions,omitempty"` + + // An array of references to taxonomy reporting descriptors that are applicable to + // the result. + Taxa []ReportingDescriptorReference `json:"taxa,omitempty" yaml:"taxa,omitempty" mapstructure:"taxa,omitempty"` + + // A web request associated with this result. + WebRequest *WebRequest `json:"webRequest,omitempty" yaml:"webRequest,omitempty" mapstructure:"webRequest,omitempty"` + + // A web response associated with this result. + WebResponse *WebResponse `json:"webResponse,omitempty" yaml:"webResponse,omitempty" mapstructure:"webResponse,omitempty"` + + // The URIs of the work items associated with this result. + WorkItemUris []string `json:"workItemUris,omitempty" yaml:"workItemUris,omitempty" mapstructure:"workItemUris,omitempty"` +} + +type ResultBaselineState string + +const ResultBaselineStateAbsent ResultBaselineState = "absent" +const ResultBaselineStateNew ResultBaselineState = "new" +const ResultBaselineStateUnchanged ResultBaselineState = "unchanged" +const ResultBaselineStateUpdated ResultBaselineState = "updated" +var enumValues_ResultBaselineState = []interface {}{ + "new", + "unchanged", + "updated", + "absent", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultBaselineState) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ResultBaselineState { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ResultBaselineState, v) + } + *j = ResultBaselineState(v) + return nil +} + + +// A set of strings each of which individually defines a stable, unique identity +// for the result. +type ResultFingerprints map[string]string + +type ResultKind string + +const ResultKindFail ResultKind = "fail" +const ResultKindInformational ResultKind = "informational" +const ResultKindNotApplicable ResultKind = "notApplicable" +const ResultKindOpen ResultKind = "open" +const ResultKindPass ResultKind = "pass" +const ResultKindReview ResultKind = "review" +var enumValues_ResultKind = []interface {}{ + "notApplicable", + "pass", + "fail", + "review", + "open", + "informational", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultKind) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ResultKind { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ResultKind, v) + } + *j = ResultKind(v) + return nil +} + + +type ResultLevel string + +const ResultLevelError ResultLevel = "error" +const ResultLevelNone ResultLevel = "none" +const ResultLevelNote ResultLevel = "note" +const ResultLevelWarning ResultLevel = "warning" +var enumValues_ResultLevel = []interface {}{ + "none", + "note", + "warning", + "error", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultLevel) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ResultLevel { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ResultLevel, v) + } + *j = ResultLevel(v) + return nil +} + + +// A set of strings that contribute to the stable, unique identity of the result. +type ResultPartialFingerprints map[string]string + +// Contains information about how and when a result was detected. +type ResultProvenance struct { + // An array of physicalLocation objects which specify the portions of an analysis + // tool's output that a converter transformed into the result. + ConversionSources []PhysicalLocation `json:"conversionSources,omitempty" yaml:"conversionSources,omitempty" mapstructure:"conversionSources,omitempty"` + + // A GUID-valued string equal to the automationDetails.guid property of the run in + // which the result was first detected. + FirstDetectionRunGuid *string `json:"firstDetectionRunGuid,omitempty" yaml:"firstDetectionRunGuid,omitempty" mapstructure:"firstDetectionRunGuid,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the result was + // first detected. See "Date/time properties" in the SARIF spec for the required + // format. + FirstDetectionTimeUtc *time.Time `json:"firstDetectionTimeUtc,omitempty" yaml:"firstDetectionTimeUtc,omitempty" mapstructure:"firstDetectionTimeUtc,omitempty"` + + // The index within the run.invocations array of the invocation object which + // describes the tool invocation that detected the result. + InvocationIndex int `json:"invocationIndex,omitempty" yaml:"invocationIndex,omitempty" mapstructure:"invocationIndex,omitempty"` + + // A GUID-valued string equal to the automationDetails.guid property of the run in + // which the result was most recently detected. + LastDetectionRunGuid *string `json:"lastDetectionRunGuid,omitempty" yaml:"lastDetectionRunGuid,omitempty" mapstructure:"lastDetectionRunGuid,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the result was most + // recently detected. See "Date/time properties" in the SARIF spec for the + // required format. + LastDetectionTimeUtc *time.Time `json:"lastDetectionTimeUtc,omitempty" yaml:"lastDetectionTimeUtc,omitempty" mapstructure:"lastDetectionTimeUtc,omitempty"` + + // Key/value pairs that provide additional information about the result. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultProvenance) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ResultProvenance + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["conversionSources"]; !ok || v == nil { + plain.ConversionSources = []PhysicalLocation{ +} + } + if plain.FirstDetectionRunGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.FirstDetectionRunGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "FirstDetectionRunGuid") + } + } + if v, ok := raw["invocationIndex"]; !ok || v == nil { + plain.InvocationIndex = -1.0 + } + if -1 > plain.InvocationIndex { + return fmt.Errorf("field %s: must be >= %v", "invocationIndex", -1) + } + if plain.LastDetectionRunGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.LastDetectionRunGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "LastDetectionRunGuid") + } + } + *j = ResultProvenance(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Result) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["message"]; raw != nil && !ok { + return fmt.Errorf("field message in Result: required") + } + type Plain Result + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["attachments"]; !ok || v == nil { + plain.Attachments = []Attachment{ +} + } + if v, ok := raw["codeFlows"]; !ok || v == nil { + plain.CodeFlows = []CodeFlow{ +} + } + if plain.CorrelationGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.CorrelationGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "CorrelationGuid") + } + } + if v, ok := raw["fixes"]; !ok || v == nil { + plain.Fixes = []Fix{ +} + } + if v, ok := raw["graphTraversals"]; !ok || v == nil { + plain.GraphTraversals = []GraphTraversal{ +} + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []Graph{ +} + } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + if v, ok := raw["kind"]; !ok || v == nil { + plain.Kind = "fail" + } + if v, ok := raw["level"]; !ok || v == nil { + plain.Level = "warning" + } + if v, ok := raw["locations"]; !ok || v == nil { + plain.Locations = []Location{ +} + } + if plain.OccurrenceCount != nil && 1 >* plain.OccurrenceCount { + return fmt.Errorf("field %s: must be >= %v", "occurrenceCount", 1) + } + if v, ok := raw["rank"]; !ok || v == nil { + plain.Rank = -1.0 + } + if 100 < plain.Rank { + return fmt.Errorf("field %s: must be <= %v", "rank", 100) + } + if -1 > plain.Rank { + return fmt.Errorf("field %s: must be >= %v", "rank", -1) + } + if v, ok := raw["relatedLocations"]; !ok || v == nil { + plain.RelatedLocations = []Location{ +} + } + if v, ok := raw["ruleIndex"]; !ok || v == nil { + plain.RuleIndex = -1.0 + } + if -1 > plain.RuleIndex { + return fmt.Errorf("field %s: must be >= %v", "ruleIndex", -1) + } + if v, ok := raw["stacks"]; !ok || v == nil { + plain.Stacks = []Stack{ +} + } + if v, ok := raw["taxa"]; !ok || v == nil { + plain.Taxa = []ReportingDescriptorReference{ +} + } + *j = Result(plain) + return nil +} + + +// Describes a single run of an analysis tool, and contains the reported output of +// that run. +type Run struct { + // Addresses associated with this run instance, if any. + Addresses []Address `json:"addresses,omitempty" yaml:"addresses,omitempty" mapstructure:"addresses,omitempty"` + + // An array of artifact objects relevant to the run. + Artifacts []Artifact `json:"artifacts,omitempty" yaml:"artifacts,omitempty" mapstructure:"artifacts,omitempty"` + + // Automation details that describe this run. + AutomationDetails *RunAutomationDetails `json:"automationDetails,omitempty" yaml:"automationDetails,omitempty" mapstructure:"automationDetails,omitempty"` + + // The 'guid' property of a previous SARIF 'run' that comprises the baseline that + // was used to compute result 'baselineState' properties for the run. + BaselineGuid *string `json:"baselineGuid,omitempty" yaml:"baselineGuid,omitempty" mapstructure:"baselineGuid,omitempty"` + + // Specifies the unit in which the tool measures columns. + ColumnKind *RunColumnKind `json:"columnKind,omitempty" yaml:"columnKind,omitempty" mapstructure:"columnKind,omitempty"` + + // A conversion object that describes how a converter transformed an analysis + // tool's native reporting format into the SARIF format. + Conversion *Conversion `json:"conversion,omitempty" yaml:"conversion,omitempty" mapstructure:"conversion,omitempty"` + + // Specifies the default encoding for any artifact object that refers to a text + // file. + DefaultEncoding *string `json:"defaultEncoding,omitempty" yaml:"defaultEncoding,omitempty" mapstructure:"defaultEncoding,omitempty"` + + // Specifies the default source language for any artifact object that refers to a + // text file that contains source code. + DefaultSourceLanguage *string `json:"defaultSourceLanguage,omitempty" yaml:"defaultSourceLanguage,omitempty" mapstructure:"defaultSourceLanguage,omitempty"` + + // References to external property files that should be inlined with the content + // of a root log file. + ExternalPropertyFileReferences *ExternalPropertyFileReferences `json:"externalPropertyFileReferences,omitempty" yaml:"externalPropertyFileReferences,omitempty" mapstructure:"externalPropertyFileReferences,omitempty"` + + // An array of zero or more unique graph objects associated with the run. + Graphs []Graph `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // Describes the invocation of the analysis tool. + Invocations []Invocation `json:"invocations,omitempty" yaml:"invocations,omitempty" mapstructure:"invocations,omitempty"` + + // The language of the messages emitted into the log file during this run + // (expressed as an ISO 639-1 two-letter lowercase culture code) and an optional + // region (expressed as an ISO 3166-1 two-letter uppercase subculture code + // associated with a country or region). The casing is recommended but not + // required (in order for this data to conform to RFC5646). + Language string `json:"language,omitempty" yaml:"language,omitempty" mapstructure:"language,omitempty"` + + // An array of logical locations such as namespaces, types or functions. + LogicalLocations []LogicalLocation `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // An ordered list of character sequences that were treated as line breaks when + // computing region information for the run. + NewlineSequences []string `json:"newlineSequences,omitempty" yaml:"newlineSequences,omitempty" mapstructure:"newlineSequences,omitempty"` + + // The artifact location specified by each uriBaseId symbol on the machine where + // the tool originally ran. + OriginalUriBaseIds RunOriginalUriBaseIds `json:"originalUriBaseIds,omitempty" yaml:"originalUriBaseIds,omitempty" mapstructure:"originalUriBaseIds,omitempty"` + + // Contains configurations that may potentially override both + // reportingDescriptor.defaultConfiguration (the tool's default severities) and + // invocation.configurationOverrides (severities established at run-time from the + // command line). + Policies []ToolComponent `json:"policies,omitempty" yaml:"policies,omitempty" mapstructure:"policies,omitempty"` + + // Key/value pairs that provide additional information about the run. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of strings used to replace sensitive information in a redaction-aware + // property. + RedactionTokens []string `json:"redactionTokens,omitempty" yaml:"redactionTokens,omitempty" mapstructure:"redactionTokens,omitempty"` + + // The set of results contained in an SARIF log. The results array can be omitted + // when a run is solely exporting rules metadata. It must be present (but may be + // empty) if a log file represents an actual scan. + Results []Result `json:"results,omitempty" yaml:"results,omitempty" mapstructure:"results,omitempty"` + + // Automation details that describe the aggregate of runs to which this run + // belongs. + RunAggregates []RunAutomationDetails `json:"runAggregates,omitempty" yaml:"runAggregates,omitempty" mapstructure:"runAggregates,omitempty"` + + // A specialLocations object that defines locations of special significance to + // SARIF consumers. + SpecialLocations *SpecialLocations `json:"specialLocations,omitempty" yaml:"specialLocations,omitempty" mapstructure:"specialLocations,omitempty"` + + // An array of toolComponent objects relevant to a taxonomy in which results are + // categorized. + Taxonomies []ToolComponent `json:"taxonomies,omitempty" yaml:"taxonomies,omitempty" mapstructure:"taxonomies,omitempty"` + + // An array of threadFlowLocation objects cached at run level. + ThreadFlowLocations []ThreadFlowLocation `json:"threadFlowLocations,omitempty" yaml:"threadFlowLocations,omitempty" mapstructure:"threadFlowLocations,omitempty"` + + // Information about the tool or tool pipeline that generated the results in this + // run. A run can only contain results produced by a single tool or tool pipeline. + // A run can aggregate results from multiple log files, as long as context around + // the tool run (tool command-line arguments and the like) is identical for all + // aggregated files. + Tool Tool `json:"tool" yaml:"tool" mapstructure:"tool"` + + // The set of available translations of the localized data provided by the tool. + Translations []ToolComponent `json:"translations,omitempty" yaml:"translations,omitempty" mapstructure:"translations,omitempty"` + + // Specifies the revision in version control of the artifacts that were scanned. + VersionControlProvenance []VersionControlDetails `json:"versionControlProvenance,omitempty" yaml:"versionControlProvenance,omitempty" mapstructure:"versionControlProvenance,omitempty"` + + // An array of request objects cached at run level. + WebRequests []WebRequest `json:"webRequests,omitempty" yaml:"webRequests,omitempty" mapstructure:"webRequests,omitempty"` + + // An array of response objects cached at run level. + WebResponses []WebResponse `json:"webResponses,omitempty" yaml:"webResponses,omitempty" mapstructure:"webResponses,omitempty"` +} + +// Information that describes a run's identity and role within an engineering +// system process. +type RunAutomationDetails struct { + // A stable, unique identifier for the equivalence class of runs to which this + // object's containing run object belongs in the form of a GUID. + CorrelationGuid *string `json:"correlationGuid,omitempty" yaml:"correlationGuid,omitempty" mapstructure:"correlationGuid,omitempty"` + + // A description of the identity and role played within the engineering system by + // this object's containing run object. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // A stable, unique identifier for this object's containing run object in the form + // of a GUID. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // A hierarchical string that uniquely identifies this object's containing run + // object. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // Key/value pairs that provide additional information about the run automation + // details. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *RunAutomationDetails) UnmarshalJSON(b []byte) error { + type Plain RunAutomationDetails + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.CorrelationGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.CorrelationGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "CorrelationGuid") + } + } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + *j = RunAutomationDetails(plain) + return nil +} + + +type RunColumnKind string + +const RunColumnKindUnicodeCodePoints RunColumnKind = "unicodeCodePoints" +const RunColumnKindUtf16CodeUnits RunColumnKind = "utf16CodeUnits" +var enumValues_RunColumnKind = []interface {}{ + "utf16CodeUnits", + "unicodeCodePoints", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *RunColumnKind) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_RunColumnKind { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_RunColumnKind, v) + } + *j = RunColumnKind(v) + return nil +} + + +// The artifact location specified by each uriBaseId symbol on the machine where +// the tool originally ran. +type RunOriginalUriBaseIds map[string]ArtifactLocation + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Run) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["tool"]; raw != nil && !ok { + return fmt.Errorf("field tool in Run: required") + } + type Plain Run + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["addresses"]; !ok || v == nil { + plain.Addresses = []Address{ +} + } + if plain.BaselineGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.BaselineGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "BaselineGuid") + } + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []Graph{ +} + } + if v, ok := raw["invocations"]; !ok || v == nil { + plain.Invocations = []Invocation{ +} + } + if v, ok := raw["language"]; !ok || v == nil { + plain.Language = "en-US" + } + if matched, _ := regexp.MatchString("^[a-zA-Z]{2}(-[a-zA-Z]{2})?$", string(plain.Language)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$", "Language") + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []LogicalLocation{ +} + } + if v, ok := raw["newlineSequences"]; !ok || v == nil { + plain.NewlineSequences = []string{ +"\r\n", +"\n", +} + } + if plain.NewlineSequences != nil && len(plain.NewlineSequences) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "newlineSequences", 1) + } + if v, ok := raw["policies"]; !ok || v == nil { + plain.Policies = []ToolComponent{ +} + } + if v, ok := raw["redactionTokens"]; !ok || v == nil { + plain.RedactionTokens = []string{ +} + } + if v, ok := raw["runAggregates"]; !ok || v == nil { + plain.RunAggregates = []RunAutomationDetails{ +} + } + if v, ok := raw["taxonomies"]; !ok || v == nil { + plain.Taxonomies = []ToolComponent{ +} + } + if v, ok := raw["threadFlowLocations"]; !ok || v == nil { + plain.ThreadFlowLocations = []ThreadFlowLocation{ +} + } + if v, ok := raw["translations"]; !ok || v == nil { + plain.Translations = []ToolComponent{ +} + } + if v, ok := raw["versionControlProvenance"]; !ok || v == nil { + plain.VersionControlProvenance = []VersionControlDetails{ +} + } + if v, ok := raw["webRequests"]; !ok || v == nil { + plain.WebRequests = []WebRequest{ +} + } + if v, ok := raw["webResponses"]; !ok || v == nil { + plain.WebResponses = []WebResponse{ +} + } + *j = Run(plain) + return nil +} + + +// Static Analysis Results Format (SARIF) Version 2.1.0 JSON Schema: a standard +// format for the output of static analysis tools. +type SchemaJson struct { + // The URI of the JSON schema corresponding to the version. + Schema *string `json:"$schema,omitempty" yaml:"$schema,omitempty" mapstructure:"$schema,omitempty"` + + // References to external property files that share data between runs. + InlineExternalProperties []ExternalProperties `json:"inlineExternalProperties,omitempty" yaml:"inlineExternalProperties,omitempty" mapstructure:"inlineExternalProperties,omitempty"` + + // Key/value pairs that provide additional information about the log file. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The set of runs contained in this log file. + Runs []Run `json:"runs" yaml:"runs" mapstructure:"runs"` + + // The SARIF format version of this log file. + Version SchemaJsonVersion `json:"version" yaml:"version" mapstructure:"version"` +} + +type SchemaJsonVersion string + +const SchemaJsonVersionA210 SchemaJsonVersion = "2.1.0" +var enumValues_SchemaJsonVersion = []interface {}{ + "2.1.0", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SchemaJsonVersion) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_SchemaJsonVersion { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_SchemaJsonVersion, v) + } + *j = SchemaJsonVersion(v) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SchemaJson) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["runs"]; raw != nil && !ok { + return fmt.Errorf("field runs in SchemaJson: required") + } + if _, ok := raw["version"]; raw != nil && !ok { + return fmt.Errorf("field version in SchemaJson: required") + } + type Plain SchemaJson + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = SchemaJson(plain) + return nil +} + + +// Defines locations of special significance to SARIF consumers. +type SpecialLocations struct { + // Provides a suggestion to SARIF consumers to display file paths relative to the + // specified location. + DisplayBase *ArtifactLocation `json:"displayBase,omitempty" yaml:"displayBase,omitempty" mapstructure:"displayBase,omitempty"` + + // Key/value pairs that provide additional information about the special + // locations. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// A call stack that is relevant to a result. +type Stack struct { + // An array of stack frames that represents a sequence of calls, rendered in + // reverse chronological order, that comprise the call stack. + Frames []StackFrame `json:"frames" yaml:"frames" mapstructure:"frames"` + + // A message relevant to this call stack. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the stack. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// A function call within a stack trace. +type StackFrame struct { + // The location to which this stack frame refers. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // The name of the module that contains the code of this stack frame. + Module *string `json:"module,omitempty" yaml:"module,omitempty" mapstructure:"module,omitempty"` + + // The parameters of the call that is executing. + Parameters []string `json:"parameters,omitempty" yaml:"parameters,omitempty" mapstructure:"parameters,omitempty"` + + // Key/value pairs that provide additional information about the stack frame. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The thread identifier of the stack frame. + ThreadId *int `json:"threadId,omitempty" yaml:"threadId,omitempty" mapstructure:"threadId,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *StackFrame) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain StackFrame + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["parameters"]; !ok || v == nil { + plain.Parameters = []string{ +} + } + *j = StackFrame(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Stack) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["frames"]; raw != nil && !ok { + return fmt.Errorf("field frames in Stack: required") + } + type Plain Stack + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = Stack(plain) + return nil +} + + +// A suppression that is relevant to a result. +type Suppression struct { + // A stable, unique identifier for the suprression in the form of a GUID. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // A string representing the justification for the suppression. + Justification *string `json:"justification,omitempty" yaml:"justification,omitempty" mapstructure:"justification,omitempty"` + + // A string that indicates where the suppression is persisted. + Kind SuppressionKind `json:"kind" yaml:"kind" mapstructure:"kind"` + + // Identifies the location associated with the suppression. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // Key/value pairs that provide additional information about the suppression. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A string that indicates the review status of the suppression. + Status *SuppressionStatus `json:"status,omitempty" yaml:"status,omitempty" mapstructure:"status,omitempty"` +} + +type SuppressionKind string + +const SuppressionKindExternal SuppressionKind = "external" +const SuppressionKindInSource SuppressionKind = "inSource" +var enumValues_SuppressionKind = []interface {}{ + "inSource", + "external", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SuppressionKind) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_SuppressionKind { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_SuppressionKind, v) + } + *j = SuppressionKind(v) + return nil +} + + +type SuppressionStatus string + +const SuppressionStatusAccepted SuppressionStatus = "accepted" +const SuppressionStatusRejected SuppressionStatus = "rejected" +const SuppressionStatusUnderReview SuppressionStatus = "underReview" +var enumValues_SuppressionStatus = []interface {}{ + "accepted", + "underReview", + "rejected", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SuppressionStatus) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_SuppressionStatus { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_SuppressionStatus, v) + } + *j = SuppressionStatus(v) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Suppression) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["kind"]; raw != nil && !ok { + return fmt.Errorf("field kind in Suppression: required") + } + type Plain Suppression + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + *j = Suppression(plain) + return nil +} + + +// Describes a sequence of code locations that specify a path through a single +// thread of execution such as an operating system or fiber. +type ThreadFlow struct { + // An string that uniquely identifies the threadFlow within the codeFlow in which + // it occurs. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // Values of relevant expressions at the start of the thread flow that remain + // constant. + ImmutableState ThreadFlowImmutableState `json:"immutableState,omitempty" yaml:"immutableState,omitempty" mapstructure:"immutableState,omitempty"` + + // Values of relevant expressions at the start of the thread flow that may change + // during thread flow execution. + InitialState ThreadFlowInitialState `json:"initialState,omitempty" yaml:"initialState,omitempty" mapstructure:"initialState,omitempty"` + + // A temporally ordered array of 'threadFlowLocation' objects, each of which + // describes a location visited by the tool while producing the result. + Locations []ThreadFlowLocation `json:"locations" yaml:"locations" mapstructure:"locations"` + + // A message relevant to the thread flow. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the thread flow. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// Values of relevant expressions at the start of the thread flow that remain +// constant. +type ThreadFlowImmutableState map[string]MultiformatMessageString + +// Values of relevant expressions at the start of the thread flow that may change +// during thread flow execution. +type ThreadFlowInitialState map[string]MultiformatMessageString + +// A location visited by an analysis tool while simulating or monitoring the +// execution of a program. +type ThreadFlowLocation struct { + // An integer representing the temporal order in which execution reached this + // location. + ExecutionOrder int `json:"executionOrder,omitempty" yaml:"executionOrder,omitempty" mapstructure:"executionOrder,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which this location was + // executed. + ExecutionTimeUtc *time.Time `json:"executionTimeUtc,omitempty" yaml:"executionTimeUtc,omitempty" mapstructure:"executionTimeUtc,omitempty"` + + // Specifies the importance of this location in understanding the code flow in + // which it occurs. The order from most to least important is "essential", + // "important", "unimportant". Default: "important". + Importance ThreadFlowLocationImportance `json:"importance,omitempty" yaml:"importance,omitempty" mapstructure:"importance,omitempty"` + + // The index within the run threadFlowLocations array. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // A set of distinct strings that categorize the thread flow location. Well-known + // kinds include 'acquire', 'release', 'enter', 'exit', 'call', 'return', + // 'branch', 'implicit', 'false', 'true', 'caution', 'danger', 'unknown', + // 'unreachable', 'taint', 'function', 'handler', 'lock', 'memory', 'resource', + // 'scope' and 'value'. + Kinds []string `json:"kinds,omitempty" yaml:"kinds,omitempty" mapstructure:"kinds,omitempty"` + + // The code location. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // The name of the module that contains the code that is executing. + Module *string `json:"module,omitempty" yaml:"module,omitempty" mapstructure:"module,omitempty"` + + // An integer representing a containment hierarchy within the thread flow. + NestingLevel *int `json:"nestingLevel,omitempty" yaml:"nestingLevel,omitempty" mapstructure:"nestingLevel,omitempty"` + + // Key/value pairs that provide additional information about the threadflow + // location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The call stack leading to this location. + Stack *Stack `json:"stack,omitempty" yaml:"stack,omitempty" mapstructure:"stack,omitempty"` + + // A dictionary, each of whose keys specifies a variable or expression, the + // associated value of which represents the variable or expression value. For an + // annotation of kind 'continuation', for example, this dictionary might hold the + // current assumed values of a set of global variables. + State ThreadFlowLocationState `json:"state,omitempty" yaml:"state,omitempty" mapstructure:"state,omitempty"` + + // An array of references to rule or taxonomy reporting descriptors that are + // applicable to the thread flow location. + Taxa []ReportingDescriptorReference `json:"taxa,omitempty" yaml:"taxa,omitempty" mapstructure:"taxa,omitempty"` + + // A web request associated with this thread flow location. + WebRequest *WebRequest `json:"webRequest,omitempty" yaml:"webRequest,omitempty" mapstructure:"webRequest,omitempty"` + + // A web response associated with this thread flow location. + WebResponse *WebResponse `json:"webResponse,omitempty" yaml:"webResponse,omitempty" mapstructure:"webResponse,omitempty"` +} + +type ThreadFlowLocationImportance string + +const ThreadFlowLocationImportanceEssential ThreadFlowLocationImportance = "essential" +const ThreadFlowLocationImportanceImportant ThreadFlowLocationImportance = "important" +const ThreadFlowLocationImportanceUnimportant ThreadFlowLocationImportance = "unimportant" +var enumValues_ThreadFlowLocationImportance = []interface {}{ + "important", + "essential", + "unimportant", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ThreadFlowLocationImportance) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ThreadFlowLocationImportance { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ThreadFlowLocationImportance, v) + } + *j = ThreadFlowLocationImportance(v) + return nil +} + + +// A dictionary, each of whose keys specifies a variable or expression, the +// associated value of which represents the variable or expression value. For an +// annotation of kind 'continuation', for example, this dictionary might hold the +// current assumed values of a set of global variables. +type ThreadFlowLocationState map[string]MultiformatMessageString + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ThreadFlowLocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ThreadFlowLocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["executionOrder"]; !ok || v == nil { + plain.ExecutionOrder = -1.0 + } + if -1 > plain.ExecutionOrder { + return fmt.Errorf("field %s: must be >= %v", "executionOrder", -1) + } + if v, ok := raw["importance"]; !ok || v == nil { + plain.Importance = "important" + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["kinds"]; !ok || v == nil { + plain.Kinds = []string{ +} + } + if plain.NestingLevel != nil && 0 >* plain.NestingLevel { + return fmt.Errorf("field %s: must be >= %v", "nestingLevel", 0) + } + if v, ok := raw["taxa"]; !ok || v == nil { + plain.Taxa = []ReportingDescriptorReference{ +} + } + *j = ThreadFlowLocation(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ThreadFlow) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["locations"]; raw != nil && !ok { + return fmt.Errorf("field locations in ThreadFlow: required") + } + type Plain ThreadFlow + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Locations != nil && len(plain.Locations) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "locations", 1) + } + *j = ThreadFlow(plain) + return nil +} + + +// The analysis tool that was run. +type Tool struct { + // The analysis tool that was run. + Driver ToolComponent `json:"driver" yaml:"driver" mapstructure:"driver"` + + // Tool extensions that contributed to or reconfigured the analysis tool that was + // run. + Extensions []ToolComponent `json:"extensions,omitempty" yaml:"extensions,omitempty" mapstructure:"extensions,omitempty"` + + // Key/value pairs that provide additional information about the tool. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// A component, such as a plug-in or the driver, of the analysis tool that was run. +type ToolComponent struct { + // The component which is strongly associated with this component. For a + // translation, this refers to the component which has been translated. For an + // extension, this is the driver that provides the extension's plugin model. + AssociatedComponent *ToolComponentReference `json:"associatedComponent,omitempty" yaml:"associatedComponent,omitempty" mapstructure:"associatedComponent,omitempty"` + + // The kinds of data contained in this object. + Contents []ToolComponentContentsElem `json:"contents,omitempty" yaml:"contents,omitempty" mapstructure:"contents,omitempty"` + + // The binary version of the tool component's primary executable file expressed as + // four non-negative integers separated by a period (for operating systems that + // express file versions in this way). + DottedQuadFileVersion *string `json:"dottedQuadFileVersion,omitempty" yaml:"dottedQuadFileVersion,omitempty" mapstructure:"dottedQuadFileVersion,omitempty"` + + // The absolute URI from which the tool component can be downloaded. + DownloadUri *string `json:"downloadUri,omitempty" yaml:"downloadUri,omitempty" mapstructure:"downloadUri,omitempty"` + + // A comprehensive description of the tool component. + FullDescription *MultiformatMessageString `json:"fullDescription,omitempty" yaml:"fullDescription,omitempty" mapstructure:"fullDescription,omitempty"` + + // The name of the tool component along with its version and any other useful + // identifying information, such as its locale. + FullName *string `json:"fullName,omitempty" yaml:"fullName,omitempty" mapstructure:"fullName,omitempty"` + + // A dictionary, each of whose keys is a resource identifier and each of whose + // values is a multiformatMessageString object, which holds message strings in + // plain text and (optionally) Markdown format. The strings can include + // placeholders, which can be used to construct a message in combination with an + // arbitrary number of additional string arguments. + GlobalMessageStrings ToolComponentGlobalMessageStrings `json:"globalMessageStrings,omitempty" yaml:"globalMessageStrings,omitempty" mapstructure:"globalMessageStrings,omitempty"` + + // A unique identifier for the tool component in the form of a GUID. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // The absolute URI at which information about this version of the tool component + // can be found. + InformationUri *string `json:"informationUri,omitempty" yaml:"informationUri,omitempty" mapstructure:"informationUri,omitempty"` + + // Specifies whether this object contains a complete definition of the localizable + // and/or non-localizable data for this component, as opposed to including only + // data that is relevant to the results persisted to this log file. + IsComprehensive bool `json:"isComprehensive,omitempty" yaml:"isComprehensive,omitempty" mapstructure:"isComprehensive,omitempty"` + + // The language of the messages emitted into the log file during this run + // (expressed as an ISO 639-1 two-letter lowercase language code) and an optional + // region (expressed as an ISO 3166-1 two-letter uppercase subculture code + // associated with a country or region). The casing is recommended but not + // required (in order for this data to conform to RFC5646). + Language string `json:"language,omitempty" yaml:"language,omitempty" mapstructure:"language,omitempty"` + + // The semantic version of the localized strings defined in this component; + // maintained by components that provide translations. + LocalizedDataSemanticVersion *string `json:"localizedDataSemanticVersion,omitempty" yaml:"localizedDataSemanticVersion,omitempty" mapstructure:"localizedDataSemanticVersion,omitempty"` + + // An array of the artifactLocation objects associated with the tool component. + Locations []ArtifactLocation `json:"locations,omitempty" yaml:"locations,omitempty" mapstructure:"locations,omitempty"` + + // The minimum value of localizedDataSemanticVersion required in translations + // consumed by this component; used by components that consume translations. + MinimumRequiredLocalizedDataSemanticVersion *string `json:"minimumRequiredLocalizedDataSemanticVersion,omitempty" yaml:"minimumRequiredLocalizedDataSemanticVersion,omitempty" mapstructure:"minimumRequiredLocalizedDataSemanticVersion,omitempty"` + + // The name of the tool component. + Name string `json:"name" yaml:"name" mapstructure:"name"` + + // An array of reportingDescriptor objects relevant to the notifications related + // to the configuration and runtime execution of the tool component. + Notifications []ReportingDescriptor `json:"notifications,omitempty" yaml:"notifications,omitempty" mapstructure:"notifications,omitempty"` + + // The organization or company that produced the tool component. + Organization *string `json:"organization,omitempty" yaml:"organization,omitempty" mapstructure:"organization,omitempty"` + + // A product suite to which the tool component belongs. + Product *string `json:"product,omitempty" yaml:"product,omitempty" mapstructure:"product,omitempty"` + + // A localizable string containing the name of the suite of products to which the + // tool component belongs. + ProductSuite *string `json:"productSuite,omitempty" yaml:"productSuite,omitempty" mapstructure:"productSuite,omitempty"` + + // Key/value pairs that provide additional information about the tool component. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A string specifying the UTC date (and optionally, the time) of the component's + // release. + ReleaseDateUtc *string `json:"releaseDateUtc,omitempty" yaml:"releaseDateUtc,omitempty" mapstructure:"releaseDateUtc,omitempty"` + + // An array of reportingDescriptor objects relevant to the analysis performed by + // the tool component. + Rules []ReportingDescriptor `json:"rules,omitempty" yaml:"rules,omitempty" mapstructure:"rules,omitempty"` + + // The tool component version in the format specified by Semantic Versioning 2.0. + SemanticVersion *string `json:"semanticVersion,omitempty" yaml:"semanticVersion,omitempty" mapstructure:"semanticVersion,omitempty"` + + // A brief description of the tool component. + ShortDescription *MultiformatMessageString `json:"shortDescription,omitempty" yaml:"shortDescription,omitempty" mapstructure:"shortDescription,omitempty"` + + // An array of toolComponentReference objects to declare the taxonomies supported + // by the tool component. + SupportedTaxonomies []ToolComponentReference `json:"supportedTaxonomies,omitempty" yaml:"supportedTaxonomies,omitempty" mapstructure:"supportedTaxonomies,omitempty"` + + // An array of reportingDescriptor objects relevant to the definitions of both + // standalone and tool-defined taxonomies. + Taxa []ReportingDescriptor `json:"taxa,omitempty" yaml:"taxa,omitempty" mapstructure:"taxa,omitempty"` + + // Translation metadata, required for a translation, not populated by other + // component types. + TranslationMetadata *TranslationMetadata `json:"translationMetadata,omitempty" yaml:"translationMetadata,omitempty" mapstructure:"translationMetadata,omitempty"` + + // The tool component version, in whatever format the component natively provides. + Version *string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` +} + +type ToolComponentContentsElem string + +const ToolComponentContentsElemLocalizedData ToolComponentContentsElem = "localizedData" +const ToolComponentContentsElemNonLocalizedData ToolComponentContentsElem = "nonLocalizedData" +var enumValues_ToolComponentContentsElem = []interface {}{ + "localizedData", + "nonLocalizedData", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ToolComponentContentsElem) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { return err } + var ok bool + for _, expected := range enumValues_ToolComponentContentsElem { + if reflect.DeepEqual(v, expected) { ok = true; break } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ToolComponentContentsElem, v) + } + *j = ToolComponentContentsElem(v) + return nil +} + + +// A dictionary, each of whose keys is a resource identifier and each of whose +// values is a multiformatMessageString object, which holds message strings in +// plain text and (optionally) Markdown format. The strings can include +// placeholders, which can be used to construct a message in combination with an +// arbitrary number of additional string arguments. +type ToolComponentGlobalMessageStrings map[string]MultiformatMessageString + +// Identifies a particular toolComponent object, either the driver or an extension. +type ToolComponentReference struct { + // The 'guid' property of the referenced toolComponent. + Guid *string `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // An index into the referenced toolComponent in tool.extensions. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // The 'name' property of the referenced toolComponent. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // Key/value pairs that provide additional information about the + // toolComponentReference. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ToolComponentReference) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain ToolComponentReference + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = ToolComponentReference(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ToolComponent) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["name"]; raw != nil && !ok { + return fmt.Errorf("field name in ToolComponent: required") + } + type Plain ToolComponent + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["contents"]; !ok || v == nil { + plain.Contents = []ToolComponentContentsElem{ +"localizedData", +"nonLocalizedData", +} + } + if plain.DottedQuadFileVersion != nil { + if matched, _ := regexp.MatchString(`[0-9]+(\.[0-9]+){3}`, string(*plain.DottedQuadFileVersion)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", `[0-9]+(\.[0-9]+){3}`, "DottedQuadFileVersion") + } + } + if plain.Guid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.Guid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "Guid") + } + } + if v, ok := raw["isComprehensive"]; !ok || v == nil { + plain.IsComprehensive = false + } + if v, ok := raw["language"]; !ok || v == nil { + plain.Language = "en-US" + } + if matched, _ := regexp.MatchString("^[a-zA-Z]{2}(-[a-zA-Z]{2})?$", string(plain.Language)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$", "Language") + } + if v, ok := raw["locations"]; !ok || v == nil { + plain.Locations = []ArtifactLocation{ +} + } + if v, ok := raw["notifications"]; !ok || v == nil { + plain.Notifications = []ReportingDescriptor{ +} + } + if v, ok := raw["rules"]; !ok || v == nil { + plain.Rules = []ReportingDescriptor{ +} + } + if v, ok := raw["supportedTaxonomies"]; !ok || v == nil { + plain.SupportedTaxonomies = []ToolComponentReference{ +} + } + if v, ok := raw["taxa"]; !ok || v == nil { + plain.Taxa = []ReportingDescriptor{ +} + } + *j = ToolComponent(plain) + return nil +} + + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Tool) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["driver"]; raw != nil && !ok { + return fmt.Errorf("field driver in Tool: required") + } + type Plain Tool + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["extensions"]; !ok || v == nil { + plain.Extensions = []ToolComponent{ +} + } + *j = Tool(plain) + return nil +} + + +// Provides additional metadata related to translation. +type TranslationMetadata struct { + // The absolute URI from which the translation metadata can be downloaded. + DownloadUri *string `json:"downloadUri,omitempty" yaml:"downloadUri,omitempty" mapstructure:"downloadUri,omitempty"` + + // A comprehensive description of the translation metadata. + FullDescription *MultiformatMessageString `json:"fullDescription,omitempty" yaml:"fullDescription,omitempty" mapstructure:"fullDescription,omitempty"` + + // The full name associated with the translation metadata. + FullName *string `json:"fullName,omitempty" yaml:"fullName,omitempty" mapstructure:"fullName,omitempty"` + + // The absolute URI from which information related to the translation metadata can + // be downloaded. + InformationUri *string `json:"informationUri,omitempty" yaml:"informationUri,omitempty" mapstructure:"informationUri,omitempty"` + + // The name associated with the translation metadata. + Name string `json:"name" yaml:"name" mapstructure:"name"` + + // Key/value pairs that provide additional information about the translation + // metadata. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A brief description of the translation metadata. + ShortDescription *MultiformatMessageString `json:"shortDescription,omitempty" yaml:"shortDescription,omitempty" mapstructure:"shortDescription,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *TranslationMetadata) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["name"]; raw != nil && !ok { + return fmt.Errorf("field name in TranslationMetadata: required") + } + type Plain TranslationMetadata + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = TranslationMetadata(plain) + return nil +} + + +// Specifies the information necessary to retrieve a desired revision from a +// version control system. +type VersionControlDetails struct { + // A Coordinated Universal Time (UTC) date and time that can be used to + // synchronize an enlistment to the state of the repository at that time. + AsOfTimeUtc *time.Time `json:"asOfTimeUtc,omitempty" yaml:"asOfTimeUtc,omitempty" mapstructure:"asOfTimeUtc,omitempty"` + + // The name of a branch containing the revision. + Branch *string `json:"branch,omitempty" yaml:"branch,omitempty" mapstructure:"branch,omitempty"` + + // The location in the local file system to which the root of the repository was + // mapped at the time of the analysis. + MappedTo *ArtifactLocation `json:"mappedTo,omitempty" yaml:"mappedTo,omitempty" mapstructure:"mappedTo,omitempty"` + + // Key/value pairs that provide additional information about the version control + // details. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The absolute URI of the repository. + RepositoryUri string `json:"repositoryUri" yaml:"repositoryUri" mapstructure:"repositoryUri"` + + // A string that uniquely and permanently identifies the revision within the + // repository. + RevisionId *string `json:"revisionId,omitempty" yaml:"revisionId,omitempty" mapstructure:"revisionId,omitempty"` + + // A tag that has been applied to the revision. + RevisionTag *string `json:"revisionTag,omitempty" yaml:"revisionTag,omitempty" mapstructure:"revisionTag,omitempty"` +} + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *VersionControlDetails) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + if _, ok := raw["repositoryUri"]; raw != nil && !ok { + return fmt.Errorf("field repositoryUri in VersionControlDetails: required") + } + type Plain VersionControlDetails + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + *j = VersionControlDetails(plain) + return nil +} + + +// Describes an HTTP request. +type WebRequest struct { + // The body of the request. + Body *ArtifactContent `json:"body,omitempty" yaml:"body,omitempty" mapstructure:"body,omitempty"` + + // The request headers. + Headers WebRequestHeaders `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // The index within the run.webRequests array of the request object associated + // with this result. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // The HTTP method. Well-known values are 'GET', 'PUT', 'POST', 'DELETE', 'PATCH', + // 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT'. + Method *string `json:"method,omitempty" yaml:"method,omitempty" mapstructure:"method,omitempty"` + + // The request parameters. + Parameters WebRequestParameters `json:"parameters,omitempty" yaml:"parameters,omitempty" mapstructure:"parameters,omitempty"` + + // Key/value pairs that provide additional information about the request. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The request protocol. Example: 'http'. + Protocol *string `json:"protocol,omitempty" yaml:"protocol,omitempty" mapstructure:"protocol,omitempty"` + + // The target of the request. + Target *string `json:"target,omitempty" yaml:"target,omitempty" mapstructure:"target,omitempty"` + + // The request version. Example: '1.1'. + Version *string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` +} + +// The request headers. +type WebRequestHeaders map[string]string + +// The request parameters. +type WebRequestParameters map[string]string + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *WebRequest) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain WebRequest + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = WebRequest(plain) + return nil +} + + +// Describes the response to an HTTP request. +type WebResponse struct { + // The body of the response. + Body *ArtifactContent `json:"body,omitempty" yaml:"body,omitempty" mapstructure:"body,omitempty"` + + // The response headers. + Headers WebResponseHeaders `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // The index within the run.webResponses array of the response object associated + // with this result. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // Specifies whether a response was received from the server. + NoResponseReceived bool `json:"noResponseReceived,omitempty" yaml:"noResponseReceived,omitempty" mapstructure:"noResponseReceived,omitempty"` + + // Key/value pairs that provide additional information about the response. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The response protocol. Example: 'http'. + Protocol *string `json:"protocol,omitempty" yaml:"protocol,omitempty" mapstructure:"protocol,omitempty"` + + // The response reason. Example: 'Not found'. + ReasonPhrase *string `json:"reasonPhrase,omitempty" yaml:"reasonPhrase,omitempty" mapstructure:"reasonPhrase,omitempty"` + + // The response status code. Example: 451. + StatusCode *int `json:"statusCode,omitempty" yaml:"statusCode,omitempty" mapstructure:"statusCode,omitempty"` + + // The response version. Example: '1.1'. + Version *string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` +} + +// The response headers. +type WebResponseHeaders map[string]string + + +// UnmarshalJSON implements json.Unmarshaler. +func (j *WebResponse) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { return err } + type Plain WebResponse + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { return err } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["noResponseReceived"]; !ok || v == nil { + plain.NoResponseReceived = false + } + *j = WebResponse(plain) + return nil +} + diff --git a/sarif/spec/gen/sarif-schema/v2-2-0/schema.go b/sarif/spec/gen/sarif-schema/v2-2-0/schema.go new file mode 100644 index 0000000..e31946a --- /dev/null +++ b/sarif/spec/gen/sarif-schema/v2-2-0/schema.go @@ -0,0 +1,3584 @@ +// Code generated by github.com/atombender/go-jsonschema, DO NOT EDIT. + +package schema + +import ( + "encoding/json" + "fmt" + "reflect" + "regexp" + "strings" + "time" + + "github.com/mitchellh/mapstructure" +) + +// A physical or virtual address, or a range of addresses, in an 'addressable +// region' (memory or a binary file). +type Address struct { + // The address expressed as a byte offset from the start of the addressable + // region. + AbsoluteAddress int `json:"absoluteAddress,omitempty" yaml:"absoluteAddress,omitempty" mapstructure:"absoluteAddress,omitempty"` + + // A human-readable fully qualified name that is associated with the address. + FullyQualifiedName *string `json:"fullyQualifiedName,omitempty" yaml:"fullyQualifiedName,omitempty" mapstructure:"fullyQualifiedName,omitempty"` + + // The index within run.addresses of the cached object for this address. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // An open-ended string that identifies the address kind. 'data', 'function', + // 'header','instruction', 'module', 'page', 'section', 'segment', 'stack', + // 'stackFrame', 'table' are well-known values. + Kind *string `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // The number of bytes in this range of addresses. + Length *int `json:"length,omitempty" yaml:"length,omitempty" mapstructure:"length,omitempty"` + + // A name that is associated with the address, e.g., '.text'. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // The byte offset of this address from the absolute or relative address of the + // parent object. + OffsetFromParent *int `json:"offsetFromParent,omitempty" yaml:"offsetFromParent,omitempty" mapstructure:"offsetFromParent,omitempty"` + + // The index within run.addresses of the parent object. + ParentIndex int `json:"parentIndex,omitempty" yaml:"parentIndex,omitempty" mapstructure:"parentIndex,omitempty"` + + // Key/value pairs that provide additional information about the address. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The address expressed as a byte offset from the absolute address of the + // top-most parent object. + RelativeAddress *int `json:"relativeAddress,omitempty" yaml:"relativeAddress,omitempty" mapstructure:"relativeAddress,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Address) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Address + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["absoluteAddress"]; !ok || v == nil { + plain.AbsoluteAddress = -1.0 + } + if -1 > plain.AbsoluteAddress { + return fmt.Errorf("field %s: must be >= %v", "absoluteAddress", -1) + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["parentIndex"]; !ok || v == nil { + plain.ParentIndex = -1.0 + } + if -1 > plain.ParentIndex { + return fmt.Errorf("field %s: must be >= %v", "parentIndex", -1) + } + *j = Address(plain) + return nil +} + +// A single artifact. In some cases, this artifact might be nested within another +// artifact. +type Artifact struct { + // The contents of the artifact. + Contents *ArtifactContent `json:"contents,omitempty" yaml:"contents,omitempty" mapstructure:"contents,omitempty"` + + // A short description of the artifact. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // Specifies the encoding for an artifact object that refers to a text file. + Encoding *string `json:"encoding,omitempty" yaml:"encoding,omitempty" mapstructure:"encoding,omitempty"` + + // A dictionary, each of whose keys is the name of a hash function and each of + // whose values is the hashed value of the artifact produced by the specified hash + // function. + Hashes ArtifactHashes `json:"hashes,omitempty" yaml:"hashes,omitempty" mapstructure:"hashes,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the artifact was + // most recently modified. See "Date/time properties" in the SARIF spec for the + // required format. + LastModifiedTimeUtc *time.Time `json:"lastModifiedTimeUtc,omitempty" yaml:"lastModifiedTimeUtc,omitempty" mapstructure:"lastModifiedTimeUtc,omitempty"` + + // The length of the artifact in bytes. + Length int `json:"length,omitempty" yaml:"length,omitempty" mapstructure:"length,omitempty"` + + // The location of the artifact. + Location *ArtifactLocation `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // The MIME type (RFC 2045) of the artifact. + MimeType *string `json:"mimeType,omitempty" yaml:"mimeType,omitempty" mapstructure:"mimeType,omitempty"` + + // The offset in bytes of the artifact within its containing artifact. + Offset *int `json:"offset,omitempty" yaml:"offset,omitempty" mapstructure:"offset,omitempty"` + + // Identifies the index of the immediate parent of the artifact, if this artifact + // is nested. + ParentIndex int `json:"parentIndex,omitempty" yaml:"parentIndex,omitempty" mapstructure:"parentIndex,omitempty"` + + // Key/value pairs that provide additional information about the artifact. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The role or roles played by the artifact in the analysis. + Roles []ArtifactRolesElem `json:"roles,omitempty" yaml:"roles,omitempty" mapstructure:"roles,omitempty"` + + // Specifies the source language for any artifact object that refers to a text + // file that contains source code. + SourceLanguage *string `json:"sourceLanguage,omitempty" yaml:"sourceLanguage,omitempty" mapstructure:"sourceLanguage,omitempty"` +} + +// A change to a single artifact. +type ArtifactChange struct { + // The location of the artifact to change. + ArtifactLocation ArtifactLocation `json:"artifactLocation" yaml:"artifactLocation" mapstructure:"artifactLocation"` + + // Key/value pairs that provide additional information about the change. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of replacement objects, each of which represents the replacement of a + // single region in a single artifact specified by 'artifactLocation'. + Replacements []Replacement `json:"replacements" yaml:"replacements" mapstructure:"replacements"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ArtifactChange) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["artifactLocation"]; raw != nil && !ok { + return fmt.Errorf("field artifactLocation in ArtifactChange: required") + } + if _, ok := raw["replacements"]; raw != nil && !ok { + return fmt.Errorf("field replacements in ArtifactChange: required") + } + type Plain ArtifactChange + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.Replacements != nil && len(plain.Replacements) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "replacements", 1) + } + *j = ArtifactChange(plain) + return nil +} + +// Represents the contents of an artifact. +type ArtifactContent struct { + // MIME Base64-encoded content from a binary artifact, or from a text artifact in + // its original encoding. + Binary *string `json:"binary,omitempty" yaml:"binary,omitempty" mapstructure:"binary,omitempty"` + + // Key/value pairs that provide additional information about the artifact content. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An alternate rendered representation of the artifact (e.g., a decompiled + // representation of a binary region). + Rendered *MultiformatMessageString `json:"rendered,omitempty" yaml:"rendered,omitempty" mapstructure:"rendered,omitempty"` + + // UTF-8-encoded content from a text artifact. + Text *string `json:"text,omitempty" yaml:"text,omitempty" mapstructure:"text,omitempty"` +} + +// A dictionary, each of whose keys is the name of a hash function and each of +// whose values is the hashed value of the artifact produced by the specified hash +// function. +type ArtifactHashes map[string]string + +// Specifies the location of an artifact. +type ArtifactLocation struct { + // A short description of the artifact location. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // The index within the run artifacts array of the artifact object associated with + // the artifact location. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // Key/value pairs that provide additional information about the artifact + // location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A string containing a valid relative or absolute URI. + Uri *string `json:"uri,omitempty" yaml:"uri,omitempty" mapstructure:"uri,omitempty"` + + // A string which indirectly specifies the absolute URI with respect to which a + // relative URI in the "uri" property is interpreted. + UriBaseId *string `json:"uriBaseId,omitempty" yaml:"uriBaseId,omitempty" mapstructure:"uriBaseId,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ArtifactLocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ArtifactLocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = ArtifactLocation(plain) + return nil +} + +type ArtifactRolesElem string + +const ArtifactRolesElemAdded ArtifactRolesElem = "added" +const ArtifactRolesElemAnalysisTarget ArtifactRolesElem = "analysisTarget" +const ArtifactRolesElemAttachment ArtifactRolesElem = "attachment" +const ArtifactRolesElemDebugOutputFile ArtifactRolesElem = "debugOutputFile" +const ArtifactRolesElemDeleted ArtifactRolesElem = "deleted" +const ArtifactRolesElemDirectory ArtifactRolesElem = "directory" +const ArtifactRolesElemDriver ArtifactRolesElem = "driver" +const ArtifactRolesElemExtension ArtifactRolesElem = "extension" +const ArtifactRolesElemMemoryContents ArtifactRolesElem = "memoryContents" +const ArtifactRolesElemModified ArtifactRolesElem = "modified" +const ArtifactRolesElemPolicy ArtifactRolesElem = "policy" +const ArtifactRolesElemReferencedOnCommandLine ArtifactRolesElem = "referencedOnCommandLine" +const ArtifactRolesElemRenamed ArtifactRolesElem = "renamed" +const ArtifactRolesElemResponseFile ArtifactRolesElem = "responseFile" +const ArtifactRolesElemResultFile ArtifactRolesElem = "resultFile" +const ArtifactRolesElemScannedFile ArtifactRolesElem = "scannedFile" +const ArtifactRolesElemStandardStream ArtifactRolesElem = "standardStream" +const ArtifactRolesElemTaxonomy ArtifactRolesElem = "taxonomy" +const ArtifactRolesElemToolSpecifiedConfiguration ArtifactRolesElem = "toolSpecifiedConfiguration" +const ArtifactRolesElemTracedFile ArtifactRolesElem = "tracedFile" +const ArtifactRolesElemTranslation ArtifactRolesElem = "translation" +const ArtifactRolesElemUncontrolled ArtifactRolesElem = "uncontrolled" +const ArtifactRolesElemUnmodified ArtifactRolesElem = "unmodified" +const ArtifactRolesElemUserSpecifiedConfiguration ArtifactRolesElem = "userSpecifiedConfiguration" + +var enumValues_ArtifactRolesElem = []interface{}{ + "analysisTarget", + "attachment", + "responseFile", + "resultFile", + "scannedFile", + "standardStream", + "tracedFile", + "unmodified", + "modified", + "added", + "deleted", + "renamed", + "uncontrolled", + "driver", + "extension", + "translation", + "taxonomy", + "policy", + "referencedOnCommandLine", + "memoryContents", + "directory", + "userSpecifiedConfiguration", + "toolSpecifiedConfiguration", + "debugOutputFile", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ArtifactRolesElem) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ArtifactRolesElem { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ArtifactRolesElem, v) + } + *j = ArtifactRolesElem(v) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Artifact) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Artifact + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["length"]; !ok || v == nil { + plain.Length = -1.0 + } + if -1 > plain.Length { + return fmt.Errorf("field %s: must be >= %v", "length", -1) + } + if plain.MimeType != nil { + if matched, _ := regexp.MatchString("[^/]+/.+", string(*plain.MimeType)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "[^/]+/.+", "MimeType") + } + } + if plain.Offset != nil && 0 > *plain.Offset { + return fmt.Errorf("field %s: must be >= %v", "offset", 0) + } + if v, ok := raw["parentIndex"]; !ok || v == nil { + plain.ParentIndex = -1.0 + } + if -1 > plain.ParentIndex { + return fmt.Errorf("field %s: must be >= %v", "parentIndex", -1) + } + if v, ok := raw["roles"]; !ok || v == nil { + plain.Roles = []ArtifactRolesElem{} + } + *j = Artifact(plain) + return nil +} + +// An artifact relevant to a result. +type Attachment struct { + // The location of the attachment. + ArtifactLocation ArtifactLocation `json:"artifactLocation" yaml:"artifactLocation" mapstructure:"artifactLocation"` + + // A message describing the role played by the attachment. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // Key/value pairs that provide additional information about the attachment. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of rectangles specifying areas of interest within the image. + Rectangles []Rectangle `json:"rectangles,omitempty" yaml:"rectangles,omitempty" mapstructure:"rectangles,omitempty"` + + // An array of regions of interest within the attachment. + Regions []Region `json:"regions,omitempty" yaml:"regions,omitempty" mapstructure:"regions,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Attachment) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["artifactLocation"]; raw != nil && !ok { + return fmt.Errorf("field artifactLocation in Attachment: required") + } + type Plain Attachment + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["rectangles"]; !ok || v == nil { + plain.Rectangles = []Rectangle{} + } + if v, ok := raw["regions"]; !ok || v == nil { + plain.Regions = []Region{} + } + *j = Attachment(plain) + return nil +} + +// A set of threadFlows which together describe a pattern of code execution +// relevant to detecting a result. +type CodeFlow struct { + // A message relevant to the code flow. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the code flow. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of one or more unique threadFlow objects, each of which describes the + // progress of a program through a thread of execution. + ThreadFlows []ThreadFlow `json:"threadFlows" yaml:"threadFlows" mapstructure:"threadFlows"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *CodeFlow) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["threadFlows"]; raw != nil && !ok { + return fmt.Errorf("field threadFlows in CodeFlow: required") + } + type Plain CodeFlow + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.ThreadFlows != nil && len(plain.ThreadFlows) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "threadFlows", 1) + } + *j = CodeFlow(plain) + return nil +} + +// Information about how a specific rule or notification was reconfigured at +// runtime. +type ConfigurationOverride struct { + // Specifies how the rule or notification was configured during the scan. + Configuration ReportingConfiguration `json:"configuration" yaml:"configuration" mapstructure:"configuration"` + + // A reference used to locate the descriptor whose configuration was overridden. + Descriptor ReportingDescriptorReference `json:"descriptor" yaml:"descriptor" mapstructure:"descriptor"` + + // Key/value pairs that provide additional information about the configuration + // override. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ConfigurationOverride) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["configuration"]; raw != nil && !ok { + return fmt.Errorf("field configuration in ConfigurationOverride: required") + } + if _, ok := raw["descriptor"]; raw != nil && !ok { + return fmt.Errorf("field descriptor in ConfigurationOverride: required") + } + type Plain ConfigurationOverride + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = ConfigurationOverride(plain) + return nil +} + +// Describes how a converter transformed the output of a static analysis tool from +// the analysis tool's native output format into the SARIF format. +type Conversion struct { + // The locations of the analysis tool's per-run log files. + AnalysisToolLogFiles []ArtifactLocation `json:"analysisToolLogFiles,omitempty" yaml:"analysisToolLogFiles,omitempty" mapstructure:"analysisToolLogFiles,omitempty"` + + // An invocation object that describes the invocation of the converter. + Invocation *Invocation `json:"invocation,omitempty" yaml:"invocation,omitempty" mapstructure:"invocation,omitempty"` + + // Key/value pairs that provide additional information about the conversion. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A tool object that describes the converter. + Tool Tool `json:"tool" yaml:"tool" mapstructure:"tool"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Conversion) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["tool"]; raw != nil && !ok { + return fmt.Errorf("field tool in Conversion: required") + } + type Plain Conversion + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["analysisToolLogFiles"]; !ok || v == nil { + plain.AnalysisToolLogFiles = []ArtifactLocation{} + } + *j = Conversion(plain) + return nil +} + +// Represents a directed edge in a graph. +type Edge struct { + // A string that uniquely identifies the edge within its graph. + Id string `json:"id" yaml:"id" mapstructure:"id"` + + // A short description of the edge. + Label *Message `json:"label,omitempty" yaml:"label,omitempty" mapstructure:"label,omitempty"` + + // Key/value pairs that provide additional information about the edge. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Identifies the source node (the node at which the edge starts). + SourceNodeId string `json:"sourceNodeId" yaml:"sourceNodeId" mapstructure:"sourceNodeId"` + + // Identifies the target node (the node at which the edge ends). + TargetNodeId string `json:"targetNodeId" yaml:"targetNodeId" mapstructure:"targetNodeId"` +} + +// Represents the traversal of a single edge during a graph traversal. +type EdgeTraversal struct { + // Identifies the edge being traversed. + EdgeId string `json:"edgeId" yaml:"edgeId" mapstructure:"edgeId"` + + // The values of relevant expressions after the edge has been traversed. + FinalState EdgeTraversalFinalState `json:"finalState,omitempty" yaml:"finalState,omitempty" mapstructure:"finalState,omitempty"` + + // A message to display to the user as the edge is traversed. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the edge traversal. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The number of edge traversals necessary to return from a nested graph. + StepOverEdgeCount *int `json:"stepOverEdgeCount,omitempty" yaml:"stepOverEdgeCount,omitempty" mapstructure:"stepOverEdgeCount,omitempty"` +} + +// The values of relevant expressions after the edge has been traversed. +type EdgeTraversalFinalState map[string]MultiformatMessageString + +// UnmarshalJSON implements json.Unmarshaler. +func (j *EdgeTraversal) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["edgeId"]; raw != nil && !ok { + return fmt.Errorf("field edgeId in EdgeTraversal: required") + } + type Plain EdgeTraversal + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.StepOverEdgeCount != nil && 0 > *plain.StepOverEdgeCount { + return fmt.Errorf("field %s: must be >= %v", "stepOverEdgeCount", 0) + } + *j = EdgeTraversal(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Edge) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["id"]; raw != nil && !ok { + return fmt.Errorf("field id in Edge: required") + } + if _, ok := raw["sourceNodeId"]; raw != nil && !ok { + return fmt.Errorf("field sourceNodeId in Edge: required") + } + if _, ok := raw["targetNodeId"]; raw != nil && !ok { + return fmt.Errorf("field targetNodeId in Edge: required") + } + type Plain Edge + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Edge(plain) + return nil +} + +// Describes a runtime exception encountered during the execution of an analysis +// tool. +type Exception struct { + // An array of exception objects each of which is considered a cause of this + // exception. + InnerExceptions []*Exception `json:"innerExceptions,omitempty" yaml:"innerExceptions,omitempty" mapstructure:"innerExceptions,omitempty"` + + // A string that identifies the kind of exception, for example, the fully + // qualified type name of an object that was thrown, or the symbolic name of a + // signal. + Kind *string `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // A message that describes the exception. + Message *string `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the exception. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The sequence of function calls leading to the exception. + Stack *Stack `json:"stack,omitempty" yaml:"stack,omitempty" mapstructure:"stack,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Exception) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Exception + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["innerExceptions"]; !ok || v == nil { + plain.InnerExceptions = []*Exception{} + } + *j = Exception(plain) + return nil +} + +// The top-level element of an external property file. +type ExternalProperties struct { + // Addresses that will be merged with a separate run. + Addresses []Address `json:"addresses,omitempty" yaml:"addresses,omitempty" mapstructure:"addresses,omitempty"` + + // An array of artifact objects that will be merged with a separate run. + Artifacts []Artifact `json:"artifacts,omitempty" yaml:"artifacts,omitempty" mapstructure:"artifacts,omitempty"` + + // A conversion object that will be merged with a separate run. + Conversion *Conversion `json:"conversion,omitempty" yaml:"conversion,omitempty" mapstructure:"conversion,omitempty"` + + // The analysis tool object that will be merged with a separate run. + Driver *ToolComponent `json:"driver,omitempty" yaml:"driver,omitempty" mapstructure:"driver,omitempty"` + + // Tool extensions that will be merged with a separate run. + Extensions []ToolComponent `json:"extensions,omitempty" yaml:"extensions,omitempty" mapstructure:"extensions,omitempty"` + + // Key/value pairs that provide additional information that will be merged with a + // separate run. + ExternalizedProperties *PropertyBag `json:"externalizedProperties,omitempty" yaml:"externalizedProperties,omitempty" mapstructure:"externalizedProperties,omitempty"` + + // An array of graph objects that will be merged with a separate run. + Graphs []Graph `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // A stable, unique identifier for this external properties object, in the form of + // a GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // Describes the invocation of the analysis tool that will be merged with a + // separate run. + Invocations []Invocation `json:"invocations,omitempty" yaml:"invocations,omitempty" mapstructure:"invocations,omitempty"` + + // An array of logical locations such as namespaces, types or functions that will + // be merged with a separate run. + LogicalLocations []LogicalLocation `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // Tool policies that will be merged with a separate run. + Policies []ToolComponent `json:"policies,omitempty" yaml:"policies,omitempty" mapstructure:"policies,omitempty"` + + // Key/value pairs that provide additional information about the external + // properties. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of result objects that will be merged with a separate run. + Results []Result `json:"results,omitempty" yaml:"results,omitempty" mapstructure:"results,omitempty"` + + // A stable, unique identifier for the run associated with this external + // properties object, in the form of a GUID. + RunGuid *string `json:"runGuid,omitempty" yaml:"runGuid,omitempty" mapstructure:"runGuid,omitempty"` + + // The URI of the JSON schema corresponding to the version of the external + // property file format. + Schema *string `json:"schema,omitempty" yaml:"schema,omitempty" mapstructure:"schema,omitempty"` + + // Tool taxonomies that will be merged with a separate run. + Taxonomies []ToolComponent `json:"taxonomies,omitempty" yaml:"taxonomies,omitempty" mapstructure:"taxonomies,omitempty"` + + // An array of threadFlowLocation objects that will be merged with a separate run. + ThreadFlowLocations []ThreadFlowLocation `json:"threadFlowLocations,omitempty" yaml:"threadFlowLocations,omitempty" mapstructure:"threadFlowLocations,omitempty"` + + // Tool translations that will be merged with a separate run. + Translations []ToolComponent `json:"translations,omitempty" yaml:"translations,omitempty" mapstructure:"translations,omitempty"` + + // The SARIF format version of this external properties object. + Version *ExternalPropertiesVersion `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` + + // Requests that will be merged with a separate run. + WebRequests []WebRequest `json:"webRequests,omitempty" yaml:"webRequests,omitempty" mapstructure:"webRequests,omitempty"` + + // Responses that will be merged with a separate run. + WebResponses []WebResponse `json:"webResponses,omitempty" yaml:"webResponses,omitempty" mapstructure:"webResponses,omitempty"` +} + +type ExternalPropertiesVersion string + +const ExternalPropertiesVersionA210 ExternalPropertiesVersion = "2.1.0" + +var enumValues_ExternalPropertiesVersion = []interface{}{ + "2.1.0", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalPropertiesVersion) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ExternalPropertiesVersion { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ExternalPropertiesVersion, v) + } + *j = ExternalPropertiesVersion(v) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalProperties) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ExternalProperties + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["addresses"]; !ok || v == nil { + plain.Addresses = []Address{} + } + if v, ok := raw["extensions"]; !ok || v == nil { + plain.Extensions = []ToolComponent{} + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []Graph{} + } + if v, ok := raw["invocations"]; !ok || v == nil { + plain.Invocations = []Invocation{} + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []LogicalLocation{} + } + if v, ok := raw["policies"]; !ok || v == nil { + plain.Policies = []ToolComponent{} + } + if v, ok := raw["results"]; !ok || v == nil { + plain.Results = []Result{} + } + if plain.RunGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.RunGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "RunGuid") + } + } + if v, ok := raw["taxonomies"]; !ok || v == nil { + plain.Taxonomies = []ToolComponent{} + } + if v, ok := raw["threadFlowLocations"]; !ok || v == nil { + plain.ThreadFlowLocations = []ThreadFlowLocation{} + } + if v, ok := raw["translations"]; !ok || v == nil { + plain.Translations = []ToolComponent{} + } + if v, ok := raw["webRequests"]; !ok || v == nil { + plain.WebRequests = []WebRequest{} + } + if v, ok := raw["webResponses"]; !ok || v == nil { + plain.WebResponses = []WebResponse{} + } + *j = ExternalProperties(plain) + return nil +} + +// Contains information that enables a SARIF consumer to locate the external +// property file that contains the value of an externalized property associated +// with the run. +type ExternalPropertyFileReference struct { + // A stable, unique identifier for the external property file in the form of a + // GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // A non-negative integer specifying the number of items contained in the external + // property file. + ItemCount int `json:"itemCount,omitempty" yaml:"itemCount,omitempty" mapstructure:"itemCount,omitempty"` + + // The location of the external property file. + Location *ArtifactLocation `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // Key/value pairs that provide additional information about the external property + // file. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalPropertyFileReference) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ExternalPropertyFileReference + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["itemCount"]; !ok || v == nil { + plain.ItemCount = -1.0 + } + if -1 > plain.ItemCount { + return fmt.Errorf("field %s: must be >= %v", "itemCount", -1) + } + *j = ExternalPropertyFileReference(plain) + return nil +} + +// References to external property files that should be inlined with the content of +// a root log file. +type ExternalPropertyFileReferences struct { + // An array of external property files containing run.addresses arrays to be + // merged with the root log file. + Addresses []ExternalPropertyFileReference `json:"addresses,omitempty" yaml:"addresses,omitempty" mapstructure:"addresses,omitempty"` + + // An array of external property files containing run.artifacts arrays to be + // merged with the root log file. + Artifacts []ExternalPropertyFileReference `json:"artifacts,omitempty" yaml:"artifacts,omitempty" mapstructure:"artifacts,omitempty"` + + // An external property file containing a run.conversion object to be merged with + // the root log file. + Conversion *ExternalPropertyFileReference `json:"conversion,omitempty" yaml:"conversion,omitempty" mapstructure:"conversion,omitempty"` + + // An external property file containing a run.driver object to be merged with the + // root log file. + Driver *ExternalPropertyFileReference `json:"driver,omitempty" yaml:"driver,omitempty" mapstructure:"driver,omitempty"` + + // An array of external property files containing run.extensions arrays to be + // merged with the root log file. + Extensions []ExternalPropertyFileReference `json:"extensions,omitempty" yaml:"extensions,omitempty" mapstructure:"extensions,omitempty"` + + // An external property file containing a run.properties object to be merged with + // the root log file. + ExternalizedProperties *ExternalPropertyFileReference `json:"externalizedProperties,omitempty" yaml:"externalizedProperties,omitempty" mapstructure:"externalizedProperties,omitempty"` + + // An array of external property files containing a run.graphs object to be merged + // with the root log file. + Graphs []ExternalPropertyFileReference `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // An array of external property files containing run.invocations arrays to be + // merged with the root log file. + Invocations []ExternalPropertyFileReference `json:"invocations,omitempty" yaml:"invocations,omitempty" mapstructure:"invocations,omitempty"` + + // An array of external property files containing run.logicalLocations arrays to + // be merged with the root log file. + LogicalLocations []ExternalPropertyFileReference `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // An array of external property files containing run.policies arrays to be merged + // with the root log file. + Policies []ExternalPropertyFileReference `json:"policies,omitempty" yaml:"policies,omitempty" mapstructure:"policies,omitempty"` + + // Key/value pairs that provide additional information about the external property + // files. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of external property files containing run.results arrays to be merged + // with the root log file. + Results []ExternalPropertyFileReference `json:"results,omitempty" yaml:"results,omitempty" mapstructure:"results,omitempty"` + + // An array of external property files containing run.taxonomies arrays to be + // merged with the root log file. + Taxonomies []ExternalPropertyFileReference `json:"taxonomies,omitempty" yaml:"taxonomies,omitempty" mapstructure:"taxonomies,omitempty"` + + // An array of external property files containing run.threadFlowLocations arrays + // to be merged with the root log file. + ThreadFlowLocations []ExternalPropertyFileReference `json:"threadFlowLocations,omitempty" yaml:"threadFlowLocations,omitempty" mapstructure:"threadFlowLocations,omitempty"` + + // An array of external property files containing run.translations arrays to be + // merged with the root log file. + Translations []ExternalPropertyFileReference `json:"translations,omitempty" yaml:"translations,omitempty" mapstructure:"translations,omitempty"` + + // An array of external property files containing run.requests arrays to be merged + // with the root log file. + WebRequests []ExternalPropertyFileReference `json:"webRequests,omitempty" yaml:"webRequests,omitempty" mapstructure:"webRequests,omitempty"` + + // An array of external property files containing run.responses arrays to be + // merged with the root log file. + WebResponses []ExternalPropertyFileReference `json:"webResponses,omitempty" yaml:"webResponses,omitempty" mapstructure:"webResponses,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ExternalPropertyFileReferences) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ExternalPropertyFileReferences + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["addresses"]; !ok || v == nil { + plain.Addresses = []ExternalPropertyFileReference{} + } + if v, ok := raw["artifacts"]; !ok || v == nil { + plain.Artifacts = []ExternalPropertyFileReference{} + } + if v, ok := raw["extensions"]; !ok || v == nil { + plain.Extensions = []ExternalPropertyFileReference{} + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []ExternalPropertyFileReference{} + } + if v, ok := raw["invocations"]; !ok || v == nil { + plain.Invocations = []ExternalPropertyFileReference{} + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []ExternalPropertyFileReference{} + } + if v, ok := raw["policies"]; !ok || v == nil { + plain.Policies = []ExternalPropertyFileReference{} + } + if v, ok := raw["results"]; !ok || v == nil { + plain.Results = []ExternalPropertyFileReference{} + } + if v, ok := raw["taxonomies"]; !ok || v == nil { + plain.Taxonomies = []ExternalPropertyFileReference{} + } + if v, ok := raw["threadFlowLocations"]; !ok || v == nil { + plain.ThreadFlowLocations = []ExternalPropertyFileReference{} + } + if v, ok := raw["translations"]; !ok || v == nil { + plain.Translations = []ExternalPropertyFileReference{} + } + if v, ok := raw["webRequests"]; !ok || v == nil { + plain.WebRequests = []ExternalPropertyFileReference{} + } + if v, ok := raw["webResponses"]; !ok || v == nil { + plain.WebResponses = []ExternalPropertyFileReference{} + } + *j = ExternalPropertyFileReferences(plain) + return nil +} + +// A proposed fix for the problem represented by a result object. A fix specifies a +// set of artifacts to modify. For each artifact, it specifies a set of bytes to +// remove, and provides a set of new bytes to replace them. +type Fix struct { + // One or more artifact changes that comprise a fix for a result. + ArtifactChanges []ArtifactChange `json:"artifactChanges" yaml:"artifactChanges" mapstructure:"artifactChanges"` + + // A message that describes the proposed fix, enabling viewers to present the + // proposed change to an end user. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // Key/value pairs that provide additional information about the fix. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Fix) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["artifactChanges"]; raw != nil && !ok { + return fmt.Errorf("field artifactChanges in Fix: required") + } + type Plain Fix + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.ArtifactChanges != nil && len(plain.ArtifactChanges) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "artifactChanges", 1) + } + *j = Fix(plain) + return nil +} + +// A network of nodes and directed edges that describes some aspect of the +// structure of the code (for example, a call graph). +type Graph struct { + // A description of the graph. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // An array of edge objects representing the edges of the graph. + Edges []Edge `json:"edges,omitempty" yaml:"edges,omitempty" mapstructure:"edges,omitempty"` + + // An array of node objects representing the nodes of the graph. + Nodes []Node `json:"nodes,omitempty" yaml:"nodes,omitempty" mapstructure:"nodes,omitempty"` + + // Key/value pairs that provide additional information about the graph. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// Represents a path through a graph. +type GraphTraversal struct { + // A description of this graph traversal. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // The sequences of edges traversed by this graph traversal. + EdgeTraversals []EdgeTraversal `json:"edgeTraversals,omitempty" yaml:"edgeTraversals,omitempty" mapstructure:"edgeTraversals,omitempty"` + + // Values of relevant expressions at the start of the graph traversal that remain + // constant for the graph traversal. + ImmutableState GraphTraversalImmutableState `json:"immutableState,omitempty" yaml:"immutableState,omitempty" mapstructure:"immutableState,omitempty"` + + // Values of relevant expressions at the start of the graph traversal that may + // change during graph traversal. + InitialState GraphTraversalInitialState `json:"initialState,omitempty" yaml:"initialState,omitempty" mapstructure:"initialState,omitempty"` + + // Key/value pairs that provide additional information about the graph traversal. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The index within the result.graphs to be associated with the result. + ResultGraphIndex int `json:"resultGraphIndex,omitempty" yaml:"resultGraphIndex,omitempty" mapstructure:"resultGraphIndex,omitempty"` + + // The index within the run.graphs to be associated with the result. + RunGraphIndex int `json:"runGraphIndex,omitempty" yaml:"runGraphIndex,omitempty" mapstructure:"runGraphIndex,omitempty"` +} + +// Values of relevant expressions at the start of the graph traversal that remain +// constant for the graph traversal. +type GraphTraversalImmutableState map[string]MultiformatMessageString + +// Values of relevant expressions at the start of the graph traversal that may +// change during graph traversal. +type GraphTraversalInitialState map[string]MultiformatMessageString + +// UnmarshalJSON implements json.Unmarshaler. +func (j *GraphTraversal) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain GraphTraversal + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["edgeTraversals"]; !ok || v == nil { + plain.EdgeTraversals = []EdgeTraversal{} + } + if v, ok := raw["resultGraphIndex"]; !ok || v == nil { + plain.ResultGraphIndex = -1.0 + } + if -1 > plain.ResultGraphIndex { + return fmt.Errorf("field %s: must be >= %v", "resultGraphIndex", -1) + } + if v, ok := raw["runGraphIndex"]; !ok || v == nil { + plain.RunGraphIndex = -1.0 + } + if -1 > plain.RunGraphIndex { + return fmt.Errorf("field %s: must be >= %v", "runGraphIndex", -1) + } + *j = GraphTraversal(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Graph) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Graph + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["edges"]; !ok || v == nil { + plain.Edges = []Edge{} + } + if v, ok := raw["nodes"]; !ok || v == nil { + plain.Nodes = []Node{} + } + *j = Graph(plain) + return nil +} + +// A stable, unique identifier for many entities in the form of a GUID. +type Guid string + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Guid) UnmarshalJSON(b []byte) error { + type Plain Guid + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(plain)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "") + } + *j = Guid(plain) + return nil +} + +// The runtime environment of the analysis tool run. +type Invocation struct { + // The account under which the invocation occurred. + Account *string `json:"account,omitempty" yaml:"account,omitempty" mapstructure:"account,omitempty"` + + // An array of strings, containing in order the command line arguments passed to + // the tool from the operating system. + Arguments []string `json:"arguments,omitempty" yaml:"arguments,omitempty" mapstructure:"arguments,omitempty"` + + // The command line used to invoke the tool. + CommandLine *string `json:"commandLine,omitempty" yaml:"commandLine,omitempty" mapstructure:"commandLine,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the invocation + // ended. See "Date/time properties" in the SARIF spec for the required format. + EndTimeUtc *time.Time `json:"endTimeUtc,omitempty" yaml:"endTimeUtc,omitempty" mapstructure:"endTimeUtc,omitempty"` + + // The environment variables associated with the analysis tool process, expressed + // as key/value pairs. + EnvironmentVariables InvocationEnvironmentVariables `json:"environmentVariables,omitempty" yaml:"environmentVariables,omitempty" mapstructure:"environmentVariables,omitempty"` + + // An absolute URI specifying the location of the executable that was invoked. + ExecutableLocation *ArtifactLocation `json:"executableLocation,omitempty" yaml:"executableLocation,omitempty" mapstructure:"executableLocation,omitempty"` + + // Specifies whether the tool's execution completed successfully. + ExecutionSuccessful bool `json:"executionSuccessful" yaml:"executionSuccessful" mapstructure:"executionSuccessful"` + + // The process exit code. + ExitCode *int `json:"exitCode,omitempty" yaml:"exitCode,omitempty" mapstructure:"exitCode,omitempty"` + + // The reason for the process exit. + ExitCodeDescription *string `json:"exitCodeDescription,omitempty" yaml:"exitCodeDescription,omitempty" mapstructure:"exitCodeDescription,omitempty"` + + // The name of the signal that caused the process to exit. + ExitSignalName *string `json:"exitSignalName,omitempty" yaml:"exitSignalName,omitempty" mapstructure:"exitSignalName,omitempty"` + + // The numeric value of the signal that caused the process to exit. + ExitSignalNumber *int `json:"exitSignalNumber,omitempty" yaml:"exitSignalNumber,omitempty" mapstructure:"exitSignalNumber,omitempty"` + + // The machine on which the invocation occurred. + Machine *string `json:"machine,omitempty" yaml:"machine,omitempty" mapstructure:"machine,omitempty"` + + // An array of configurationOverride objects that describe notifications related + // runtime overrides. + NotificationConfigurationOverrides []ConfigurationOverride `json:"notificationConfigurationOverrides,omitempty" yaml:"notificationConfigurationOverrides,omitempty" mapstructure:"notificationConfigurationOverrides,omitempty"` + + // The id of the process in which the invocation occurred. + ProcessId *int `json:"processId,omitempty" yaml:"processId,omitempty" mapstructure:"processId,omitempty"` + + // The reason given by the operating system that the process failed to start. + ProcessStartFailureMessage *string `json:"processStartFailureMessage,omitempty" yaml:"processStartFailureMessage,omitempty" mapstructure:"processStartFailureMessage,omitempty"` + + // Key/value pairs that provide additional information about the invocation. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The locations of any response files specified on the tool's command line. + ResponseFiles []ArtifactLocation `json:"responseFiles,omitempty" yaml:"responseFiles,omitempty" mapstructure:"responseFiles,omitempty"` + + // An array of configurationOverride objects that describe rules related runtime + // overrides. + RuleConfigurationOverrides []ConfigurationOverride `json:"ruleConfigurationOverrides,omitempty" yaml:"ruleConfigurationOverrides,omitempty" mapstructure:"ruleConfigurationOverrides,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the invocation + // started. See "Date/time properties" in the SARIF spec for the required format. + StartTimeUtc *time.Time `json:"startTimeUtc,omitempty" yaml:"startTimeUtc,omitempty" mapstructure:"startTimeUtc,omitempty"` + + // A file containing the standard error stream from the process that was invoked. + Stderr *ArtifactLocation `json:"stderr,omitempty" yaml:"stderr,omitempty" mapstructure:"stderr,omitempty"` + + // A file containing the standard input stream to the process that was invoked. + Stdin *ArtifactLocation `json:"stdin,omitempty" yaml:"stdin,omitempty" mapstructure:"stdin,omitempty"` + + // A file containing the standard output stream from the process that was invoked. + Stdout *ArtifactLocation `json:"stdout,omitempty" yaml:"stdout,omitempty" mapstructure:"stdout,omitempty"` + + // A file containing the interleaved standard output and standard error stream + // from the process that was invoked. + StdoutStderr *ArtifactLocation `json:"stdoutStderr,omitempty" yaml:"stdoutStderr,omitempty" mapstructure:"stdoutStderr,omitempty"` + + // A list of conditions detected by the tool that are relevant to the tool's + // configuration. + ToolConfigurationNotifications []Notification `json:"toolConfigurationNotifications,omitempty" yaml:"toolConfigurationNotifications,omitempty" mapstructure:"toolConfigurationNotifications,omitempty"` + + // A list of runtime conditions detected by the tool during the analysis. + ToolExecutionNotifications []Notification `json:"toolExecutionNotifications,omitempty" yaml:"toolExecutionNotifications,omitempty" mapstructure:"toolExecutionNotifications,omitempty"` + + // The working directory for the invocation. + WorkingDirectory *ArtifactLocation `json:"workingDirectory,omitempty" yaml:"workingDirectory,omitempty" mapstructure:"workingDirectory,omitempty"` +} + +// The environment variables associated with the analysis tool process, expressed +// as key/value pairs. +type InvocationEnvironmentVariables map[string]string + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Invocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["executionSuccessful"]; raw != nil && !ok { + return fmt.Errorf("field executionSuccessful in Invocation: required") + } + type Plain Invocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["notificationConfigurationOverrides"]; !ok || v == nil { + plain.NotificationConfigurationOverrides = []ConfigurationOverride{} + } + if v, ok := raw["ruleConfigurationOverrides"]; !ok || v == nil { + plain.RuleConfigurationOverrides = []ConfigurationOverride{} + } + if v, ok := raw["toolConfigurationNotifications"]; !ok || v == nil { + plain.ToolConfigurationNotifications = []Notification{} + } + if v, ok := raw["toolExecutionNotifications"]; !ok || v == nil { + plain.ToolExecutionNotifications = []Notification{} + } + *j = Invocation(plain) + return nil +} + +// The language of the messages emitted into the log file during this run +// (expressed as an ISO 639-1 two-letter lowercase culture code) and an optional +// region (expressed as an ISO 3166-1 two-letter uppercase subculture code +// associated with a country or region). The casing is recommended but not required +// (in order for this data to conform to RFC5646). +type Language string + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Language) UnmarshalJSON(b []byte) error { + type Plain Language + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if matched, _ := regexp.MatchString("^[a-zA-Z]{2}(-[a-zA-Z]{2})?$", string(plain)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$", "") + } + *j = Language(plain) + return nil +} + +// A location within a programming artifact. +type Location struct { + // A set of regions relevant to the location. + Annotations []Region `json:"annotations,omitempty" yaml:"annotations,omitempty" mapstructure:"annotations,omitempty"` + + // Value that distinguishes this location from all other locations within a single + // result object. + Id int `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // The logical locations associated with the result. + LogicalLocations []LogicalLocation `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // A message relevant to the location. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Identifies the artifact and region. + PhysicalLocation *PhysicalLocation `json:"physicalLocation,omitempty" yaml:"physicalLocation,omitempty" mapstructure:"physicalLocation,omitempty"` + + // Key/value pairs that provide additional information about the location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of objects that describe relationships between this location and + // others. + Relationships []LocationRelationship `json:"relationships,omitempty" yaml:"relationships,omitempty" mapstructure:"relationships,omitempty"` +} + +// Information about the relation of one location to another. +type LocationRelationship struct { + // A description of the location relationship. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // A set of distinct strings that categorize the relationship. Well-known kinds + // include 'includes', 'isIncludedBy' and 'relevant'. + Kinds []string `json:"kinds,omitempty" yaml:"kinds,omitempty" mapstructure:"kinds,omitempty"` + + // Key/value pairs that provide additional information about the location + // relationship. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A reference to the related location. + Target int `json:"target" yaml:"target" mapstructure:"target"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *LocationRelationship) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["target"]; raw != nil && !ok { + return fmt.Errorf("field target in LocationRelationship: required") + } + type Plain LocationRelationship + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["kinds"]; !ok || v == nil { + plain.Kinds = []string{ + "relevant", + } + } + if 0 > plain.Target { + return fmt.Errorf("field %s: must be >= %v", "target", 0) + } + *j = LocationRelationship(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Location) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Location + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["annotations"]; !ok || v == nil { + plain.Annotations = []Region{} + } + if v, ok := raw["id"]; !ok || v == nil { + plain.Id = -1.0 + } + if -1 > plain.Id { + return fmt.Errorf("field %s: must be >= %v", "id", -1) + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []LogicalLocation{} + } + if v, ok := raw["relationships"]; !ok || v == nil { + plain.Relationships = []LocationRelationship{} + } + *j = Location(plain) + return nil +} + +// A logical location of a construct that produced a result. +type LogicalLocation struct { + // The machine-readable name for the logical location, such as a mangled function + // name provided by a C++ compiler that encodes calling convention, return type + // and other details along with the function name. + DecoratedName *string `json:"decoratedName,omitempty" yaml:"decoratedName,omitempty" mapstructure:"decoratedName,omitempty"` + + // The human-readable fully qualified name of the logical location. + FullyQualifiedName *string `json:"fullyQualifiedName,omitempty" yaml:"fullyQualifiedName,omitempty" mapstructure:"fullyQualifiedName,omitempty"` + + // The index within the logical locations array. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // The type of construct this logical location component refers to. Should be one + // of 'function', 'member', 'module', 'namespace', 'parameter', 'resource', + // 'returnType', 'type', 'variable', 'object', 'array', 'property', 'value', + // 'element', 'text', 'attribute', 'comment', 'declaration', 'dtd' or + // 'processingInstruction', if any of those accurately describe the construct. + Kind *string `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // Identifies the construct in which the result occurred. For example, this + // property might contain the name of a class or a method. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // Identifies the index of the immediate parent of the construct in which the + // result was detected. For example, this property might point to a logical + // location that represents the namespace that holds a type. + ParentIndex int `json:"parentIndex,omitempty" yaml:"parentIndex,omitempty" mapstructure:"parentIndex,omitempty"` + + // Key/value pairs that provide additional information about the logical location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *LogicalLocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain LogicalLocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["parentIndex"]; !ok || v == nil { + plain.ParentIndex = -1.0 + } + if -1 > plain.ParentIndex { + return fmt.Errorf("field %s: must be >= %v", "parentIndex", -1) + } + *j = LogicalLocation(plain) + return nil +} + +// Encapsulates a message intended to be read by the end user. +type Message struct { + // An array of strings to substitute into the message string. + Arguments []string `json:"arguments,omitempty" yaml:"arguments,omitempty" mapstructure:"arguments,omitempty"` + + // The identifier for this message. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // A Markdown message string. + Markdown *string `json:"markdown,omitempty" yaml:"markdown,omitempty" mapstructure:"markdown,omitempty"` + + // Key/value pairs that provide additional information about the message. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A plain text message string. + Text *string `json:"text,omitempty" yaml:"text,omitempty" mapstructure:"text,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Message) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Message + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["arguments"]; !ok || v == nil { + plain.Arguments = []string{} + } + *j = Message(plain) + return nil +} + +// A message string or message format string rendered in multiple formats. +type MultiformatMessageString struct { + // A Markdown message string or format string. + Markdown *string `json:"markdown,omitempty" yaml:"markdown,omitempty" mapstructure:"markdown,omitempty"` + + // Key/value pairs that provide additional information about the message. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A plain text message string or format string. + Text string `json:"text" yaml:"text" mapstructure:"text"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *MultiformatMessageString) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["text"]; raw != nil && !ok { + return fmt.Errorf("field text in MultiformatMessageString: required") + } + type Plain MultiformatMessageString + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = MultiformatMessageString(plain) + return nil +} + +// Represents a node in a graph. +type Node struct { + // Array of child nodes. + Children []*Node `json:"children,omitempty" yaml:"children,omitempty" mapstructure:"children,omitempty"` + + // A string that uniquely identifies the node within its graph. + Id string `json:"id" yaml:"id" mapstructure:"id"` + + // A short description of the node. + Label *Message `json:"label,omitempty" yaml:"label,omitempty" mapstructure:"label,omitempty"` + + // A code location associated with the node. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // Key/value pairs that provide additional information about the node. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Node) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["id"]; raw != nil && !ok { + return fmt.Errorf("field id in Node: required") + } + type Plain Node + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["children"]; !ok || v == nil { + plain.Children = []*Node{} + } + *j = Node(plain) + return nil +} + +// Describes a condition relevant to the tool itself, as opposed to being relevant +// to a target being analyzed by the tool. +type Notification struct { + // A reference used to locate the rule descriptor associated with this + // notification. + AssociatedRule *ReportingDescriptorReference `json:"associatedRule,omitempty" yaml:"associatedRule,omitempty" mapstructure:"associatedRule,omitempty"` + + // A reference used to locate the descriptor relevant to this notification. + Descriptor *ReportingDescriptorReference `json:"descriptor,omitempty" yaml:"descriptor,omitempty" mapstructure:"descriptor,omitempty"` + + // The runtime exception, if any, relevant to this notification. + Exception *Exception `json:"exception,omitempty" yaml:"exception,omitempty" mapstructure:"exception,omitempty"` + + // A value specifying the severity level of the notification. + Level NotificationLevel `json:"level,omitempty" yaml:"level,omitempty" mapstructure:"level,omitempty"` + + // The locations relevant to this notification. + Locations []Location `json:"locations,omitempty" yaml:"locations,omitempty" mapstructure:"locations,omitempty"` + + // A message that describes the condition that was encountered. + Message Message `json:"message" yaml:"message" mapstructure:"message"` + + // Key/value pairs that provide additional information about the notification. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A set of locations relevant to this notification. + RelatedLocations []Location `json:"relatedLocations,omitempty" yaml:"relatedLocations,omitempty" mapstructure:"relatedLocations,omitempty"` + + // The thread identifier of the code that generated the notification. + ThreadId *int `json:"threadId,omitempty" yaml:"threadId,omitempty" mapstructure:"threadId,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the analysis tool + // generated the notification. + TimeUtc *time.Time `json:"timeUtc,omitempty" yaml:"timeUtc,omitempty" mapstructure:"timeUtc,omitempty"` +} + +type NotificationLevel string + +const NotificationLevelError NotificationLevel = "error" +const NotificationLevelNone NotificationLevel = "none" +const NotificationLevelNote NotificationLevel = "note" +const NotificationLevelWarning NotificationLevel = "warning" + +var enumValues_NotificationLevel = []interface{}{ + "none", + "note", + "warning", + "error", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *NotificationLevel) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_NotificationLevel { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_NotificationLevel, v) + } + *j = NotificationLevel(v) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Notification) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["message"]; raw != nil && !ok { + return fmt.Errorf("field message in Notification: required") + } + type Plain Notification + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["level"]; !ok || v == nil { + plain.Level = "warning" + } + if v, ok := raw["locations"]; !ok || v == nil { + plain.Locations = []Location{} + } + if v, ok := raw["relatedLocations"]; !ok || v == nil { + plain.RelatedLocations = []Location{} + } + *j = Notification(plain) + return nil +} + +// A physical location relevant to a result. Specifies a reference to a programming +// artifact together with a range of bytes or characters within that artifact. +type PhysicalLocation struct { + // The address of the location. + Address *Address `json:"address,omitempty" yaml:"address,omitempty" mapstructure:"address,omitempty"` + + // The location of the artifact. + ArtifactLocation *ArtifactLocation `json:"artifactLocation,omitempty" yaml:"artifactLocation,omitempty" mapstructure:"artifactLocation,omitempty"` + + // Specifies a portion of the artifact that encloses the region. Allows a viewer + // to display additional context around the region. + ContextRegion *Region `json:"contextRegion,omitempty" yaml:"contextRegion,omitempty" mapstructure:"contextRegion,omitempty"` + + // Key/value pairs that provide additional information about the physical + // location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Specifies a portion of the artifact. + Region *Region `json:"region,omitempty" yaml:"region,omitempty" mapstructure:"region,omitempty"` +} + +// Key/value pairs that provide additional information about the object. +type PropertyBag struct { + // A set of distinct strings that provide additional information. + Tags []string `json:"tags,omitempty" yaml:"tags,omitempty" mapstructure:"tags,omitempty"` + + AdditionalProperties interface{} `mapstructure:",remain"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *PropertyBag) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain PropertyBag + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["tags"]; !ok || v == nil { + plain.Tags = []string{} + } + st := reflect.TypeOf(Plain{}) + for i := range st.NumField() { + delete(raw, st.Field(i).Name) + delete(raw, strings.Split(st.Field(i).Tag.Get("json"), ",")[0]) + } + if err := mapstructure.Decode(raw, &plain.AdditionalProperties); err != nil { + return err + } + *j = PropertyBag(plain) + return nil +} + +// An area within an image. +type Rectangle struct { + // The Y coordinate of the bottom edge of the rectangle, measured in the image's + // natural units. + Bottom *float64 `json:"bottom,omitempty" yaml:"bottom,omitempty" mapstructure:"bottom,omitempty"` + + // The X coordinate of the left edge of the rectangle, measured in the image's + // natural units. + Left *float64 `json:"left,omitempty" yaml:"left,omitempty" mapstructure:"left,omitempty"` + + // A message relevant to the rectangle. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the rectangle. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The X coordinate of the right edge of the rectangle, measured in the image's + // natural units. + Right *float64 `json:"right,omitempty" yaml:"right,omitempty" mapstructure:"right,omitempty"` + + // The Y coordinate of the top edge of the rectangle, measured in the image's + // natural units. + Top *float64 `json:"top,omitempty" yaml:"top,omitempty" mapstructure:"top,omitempty"` +} + +// A region within an artifact where a result was detected. +type Region struct { + // The length of the region in bytes. + ByteLength *int `json:"byteLength,omitempty" yaml:"byteLength,omitempty" mapstructure:"byteLength,omitempty"` + + // The zero-based offset from the beginning of the artifact of the first byte in + // the region. + ByteOffset int `json:"byteOffset,omitempty" yaml:"byteOffset,omitempty" mapstructure:"byteOffset,omitempty"` + + // The length of the region in characters. + CharLength *int `json:"charLength,omitempty" yaml:"charLength,omitempty" mapstructure:"charLength,omitempty"` + + // The zero-based offset from the beginning of the artifact of the first character + // in the region. + CharOffset int `json:"charOffset,omitempty" yaml:"charOffset,omitempty" mapstructure:"charOffset,omitempty"` + + // The column number of the character following the end of the region. + EndColumn *int `json:"endColumn,omitempty" yaml:"endColumn,omitempty" mapstructure:"endColumn,omitempty"` + + // The line number of the last character in the region. + EndLine *int `json:"endLine,omitempty" yaml:"endLine,omitempty" mapstructure:"endLine,omitempty"` + + // A message relevant to the region. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the region. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The portion of the artifact contents within the specified region. + Snippet *ArtifactContent `json:"snippet,omitempty" yaml:"snippet,omitempty" mapstructure:"snippet,omitempty"` + + // Specifies the source language, if any, of the portion of the artifact specified + // by the region object. + SourceLanguage *string `json:"sourceLanguage,omitempty" yaml:"sourceLanguage,omitempty" mapstructure:"sourceLanguage,omitempty"` + + // The column number of the first character in the region. + StartColumn *int `json:"startColumn,omitempty" yaml:"startColumn,omitempty" mapstructure:"startColumn,omitempty"` + + // The line number of the first character in the region. + StartLine *int `json:"startLine,omitempty" yaml:"startLine,omitempty" mapstructure:"startLine,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Region) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain Region + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.ByteLength != nil && 0 > *plain.ByteLength { + return fmt.Errorf("field %s: must be >= %v", "byteLength", 0) + } + if v, ok := raw["byteOffset"]; !ok || v == nil { + plain.ByteOffset = -1.0 + } + if -1 > plain.ByteOffset { + return fmt.Errorf("field %s: must be >= %v", "byteOffset", -1) + } + if plain.CharLength != nil && 0 > *plain.CharLength { + return fmt.Errorf("field %s: must be >= %v", "charLength", 0) + } + if v, ok := raw["charOffset"]; !ok || v == nil { + plain.CharOffset = -1.0 + } + if -1 > plain.CharOffset { + return fmt.Errorf("field %s: must be >= %v", "charOffset", -1) + } + if plain.EndColumn != nil && 1 > *plain.EndColumn { + return fmt.Errorf("field %s: must be >= %v", "endColumn", 1) + } + if plain.EndLine != nil && 1 > *plain.EndLine { + return fmt.Errorf("field %s: must be >= %v", "endLine", 1) + } + if plain.StartColumn != nil && 1 > *plain.StartColumn { + return fmt.Errorf("field %s: must be >= %v", "startColumn", 1) + } + if plain.StartLine != nil && 1 > *plain.StartLine { + return fmt.Errorf("field %s: must be >= %v", "startLine", 1) + } + *j = Region(plain) + return nil +} + +// The replacement of a single region of an artifact. +type Replacement struct { + // The region of the artifact to delete. + DeletedRegion Region `json:"deletedRegion" yaml:"deletedRegion" mapstructure:"deletedRegion"` + + // The content to insert at the location specified by the 'deletedRegion' + // property. + InsertedContent *ArtifactContent `json:"insertedContent,omitempty" yaml:"insertedContent,omitempty" mapstructure:"insertedContent,omitempty"` + + // Key/value pairs that provide additional information about the replacement. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Replacement) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["deletedRegion"]; raw != nil && !ok { + return fmt.Errorf("field deletedRegion in Replacement: required") + } + type Plain Replacement + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Replacement(plain) + return nil +} + +// Information about a rule or notification that can be configured at runtime. +type ReportingConfiguration struct { + // Specifies whether the report may be produced during the scan. + Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty" mapstructure:"enabled,omitempty"` + + // Specifies the failure level for the report. + Level ReportingConfigurationLevel `json:"level,omitempty" yaml:"level,omitempty" mapstructure:"level,omitempty"` + + // Contains configuration information specific to a report. + Parameters *PropertyBag `json:"parameters,omitempty" yaml:"parameters,omitempty" mapstructure:"parameters,omitempty"` + + // Key/value pairs that provide additional information about the reporting + // configuration. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Specifies the relative priority of the report. Used for analysis output only. + Rank float64 `json:"rank,omitempty" yaml:"rank,omitempty" mapstructure:"rank,omitempty"` +} + +type ReportingConfigurationLevel string + +const ReportingConfigurationLevelError ReportingConfigurationLevel = "error" +const ReportingConfigurationLevelNone ReportingConfigurationLevel = "none" +const ReportingConfigurationLevelNote ReportingConfigurationLevel = "note" +const ReportingConfigurationLevelWarning ReportingConfigurationLevel = "warning" + +var enumValues_ReportingConfigurationLevel = []interface{}{ + "none", + "note", + "warning", + "error", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingConfigurationLevel) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ReportingConfigurationLevel { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ReportingConfigurationLevel, v) + } + *j = ReportingConfigurationLevel(v) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingConfiguration) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ReportingConfiguration + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["enabled"]; !ok || v == nil { + plain.Enabled = true + } + if v, ok := raw["level"]; !ok || v == nil { + plain.Level = "warning" + } + if v, ok := raw["rank"]; !ok || v == nil { + plain.Rank = -1.0 + } + if 100 < plain.Rank { + return fmt.Errorf("field %s: must be <= %v", "rank", 100) + } + if -1 > plain.Rank { + return fmt.Errorf("field %s: must be >= %v", "rank", -1) + } + *j = ReportingConfiguration(plain) + return nil +} + +// Metadata that describes a specific report produced by the tool, as part of the +// analysis it provides or its runtime reporting. +type ReportingDescriptor struct { + // Default reporting configuration information. + DefaultConfiguration *ReportingConfiguration `json:"defaultConfiguration,omitempty" yaml:"defaultConfiguration,omitempty" mapstructure:"defaultConfiguration,omitempty"` + + // An array of unique identifies in the form of a GUID by which this report was + // known in some previous version of the analysis tool. + DeprecatedGuids []string `json:"deprecatedGuids,omitempty" yaml:"deprecatedGuids,omitempty" mapstructure:"deprecatedGuids,omitempty"` + + // An array of stable, opaque identifiers by which this report was known in some + // previous version of the analysis tool. + DeprecatedIds []string `json:"deprecatedIds,omitempty" yaml:"deprecatedIds,omitempty" mapstructure:"deprecatedIds,omitempty"` + + // An array of readable identifiers by which this report was known in some + // previous version of the analysis tool. + DeprecatedNames []string `json:"deprecatedNames,omitempty" yaml:"deprecatedNames,omitempty" mapstructure:"deprecatedNames,omitempty"` + + // A description of the report. Should, as far as possible, provide details + // sufficient to enable resolution of any problem indicated by the result. + FullDescription *MultiformatMessageString `json:"fullDescription,omitempty" yaml:"fullDescription,omitempty" mapstructure:"fullDescription,omitempty"` + + // A unique identifier for the reporting descriptor in the form of a GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // Provides the primary documentation for the report, useful when there is no + // online documentation. + Help *MultiformatMessageString `json:"help,omitempty" yaml:"help,omitempty" mapstructure:"help,omitempty"` + + // A URI where the primary documentation for the report can be found. + HelpUri *string `json:"helpUri,omitempty" yaml:"helpUri,omitempty" mapstructure:"helpUri,omitempty"` + + // A stable, opaque identifier for the report. + Id string `json:"id" yaml:"id" mapstructure:"id"` + + // A set of name/value pairs with arbitrary names. Each value is a + // multiformatMessageString object, which holds message strings in plain text and + // (optionally) Markdown format. The strings can include placeholders, which can + // be used to construct a message in combination with an arbitrary number of + // additional string arguments. + MessageStrings ReportingDescriptorMessageStrings `json:"messageStrings,omitempty" yaml:"messageStrings,omitempty" mapstructure:"messageStrings,omitempty"` + + // A report identifier that is understandable to an end user. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // Key/value pairs that provide additional information about the report. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of objects that describe relationships between this reporting + // descriptor and others. + Relationships []ReportingDescriptorRelationship `json:"relationships,omitempty" yaml:"relationships,omitempty" mapstructure:"relationships,omitempty"` + + // A concise description of the report. Should be a single sentence that is + // understandable when visible space is limited to a single line of text. + ShortDescription *MultiformatMessageString `json:"shortDescription,omitempty" yaml:"shortDescription,omitempty" mapstructure:"shortDescription,omitempty"` +} + +// A set of name/value pairs with arbitrary names. Each value is a +// multiformatMessageString object, which holds message strings in plain text and +// (optionally) Markdown format. The strings can include placeholders, which can be +// used to construct a message in combination with an arbitrary number of +// additional string arguments. +type ReportingDescriptorMessageStrings map[string]MultiformatMessageString + +// Information about how to locate a relevant reporting descriptor. +type ReportingDescriptorReference struct { + // A guid that uniquely identifies the descriptor. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // The id of the descriptor. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // The index into an array of descriptors in toolComponent.ruleDescriptors, + // toolComponent.notificationDescriptors, or toolComponent.taxonomyDescriptors, + // depending on context. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // Key/value pairs that provide additional information about the reporting + // descriptor reference. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A reference used to locate the toolComponent associated with the descriptor. + ToolComponent *ToolComponentReference `json:"toolComponent,omitempty" yaml:"toolComponent,omitempty" mapstructure:"toolComponent,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingDescriptorReference) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ReportingDescriptorReference + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = ReportingDescriptorReference(plain) + return nil +} + +// Information about the relation of one reporting descriptor to another. +type ReportingDescriptorRelationship struct { + // A description of the reporting descriptor relationship. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // A set of distinct strings that categorize the relationship. Well-known kinds + // include 'canPrecede', 'canFollow', 'willPrecede', 'willFollow', 'superset', + // 'subset', 'equal', 'disjoint', 'relevant', and 'incomparable'. + Kinds []string `json:"kinds,omitempty" yaml:"kinds,omitempty" mapstructure:"kinds,omitempty"` + + // Key/value pairs that provide additional information about the reporting + // descriptor reference. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A reference to the related reporting descriptor. + Target ReportingDescriptorReference `json:"target" yaml:"target" mapstructure:"target"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingDescriptorRelationship) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["target"]; raw != nil && !ok { + return fmt.Errorf("field target in ReportingDescriptorRelationship: required") + } + type Plain ReportingDescriptorRelationship + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["kinds"]; !ok || v == nil { + plain.Kinds = []string{ + "relevant", + } + } + *j = ReportingDescriptorRelationship(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ReportingDescriptor) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["id"]; raw != nil && !ok { + return fmt.Errorf("field id in ReportingDescriptor: required") + } + type Plain ReportingDescriptor + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["relationships"]; !ok || v == nil { + plain.Relationships = []ReportingDescriptorRelationship{} + } + *j = ReportingDescriptor(plain) + return nil +} + +// A result produced by an analysis tool. +type Result struct { + // Identifies the artifact that the analysis tool was instructed to scan. This + // need not be the same as the artifact where the result actually occurred. + AnalysisTarget *ArtifactLocation `json:"analysisTarget,omitempty" yaml:"analysisTarget,omitempty" mapstructure:"analysisTarget,omitempty"` + + // A set of artifacts relevant to the result. + Attachments []Attachment `json:"attachments,omitempty" yaml:"attachments,omitempty" mapstructure:"attachments,omitempty"` + + // The state of a result relative to a baseline of a previous run. + BaselineState *ResultBaselineState `json:"baselineState,omitempty" yaml:"baselineState,omitempty" mapstructure:"baselineState,omitempty"` + + // An array of 'codeFlow' objects relevant to the result. + CodeFlows []CodeFlow `json:"codeFlows,omitempty" yaml:"codeFlows,omitempty" mapstructure:"codeFlows,omitempty"` + + // A stable, unique identifier for the equivalence class of logically identical + // results to which this result belongs, in the form of a GUID. + CorrelationGuid *string `json:"correlationGuid,omitempty" yaml:"correlationGuid,omitempty" mapstructure:"correlationGuid,omitempty"` + + // A set of strings each of which individually defines a stable, unique identity + // for the result. + Fingerprints ResultFingerprints `json:"fingerprints,omitempty" yaml:"fingerprints,omitempty" mapstructure:"fingerprints,omitempty"` + + // An array of 'fix' objects, each of which represents a proposed fix to the + // problem indicated by the result. + Fixes []Fix `json:"fixes,omitempty" yaml:"fixes,omitempty" mapstructure:"fixes,omitempty"` + + // An array of one or more unique 'graphTraversal' objects. + GraphTraversals []GraphTraversal `json:"graphTraversals,omitempty" yaml:"graphTraversals,omitempty" mapstructure:"graphTraversals,omitempty"` + + // An array of zero or more unique graph objects associated with the result. + Graphs []Graph `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // A stable, unique identifier for the result in the form of a GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // An absolute URI at which the result can be viewed. + HostedViewerUri *string `json:"hostedViewerUri,omitempty" yaml:"hostedViewerUri,omitempty" mapstructure:"hostedViewerUri,omitempty"` + + // A value that categorizes results by evaluation state. + Kind ResultKind `json:"kind,omitempty" yaml:"kind,omitempty" mapstructure:"kind,omitempty"` + + // A value specifying the severity level of the result. + Level ResultLevel `json:"level,omitempty" yaml:"level,omitempty" mapstructure:"level,omitempty"` + + // The set of locations where the result was detected. Specify only one location + // unless the problem indicated by the result can only be corrected by making a + // change at every specified location. + Locations []Location `json:"locations,omitempty" yaml:"locations,omitempty" mapstructure:"locations,omitempty"` + + // A message that describes the result. The first sentence of the message only + // will be displayed when visible space is limited. + Message Message `json:"message" yaml:"message" mapstructure:"message"` + + // A positive integer specifying the number of times this logically unique result + // was observed in this run. + OccurrenceCount *int `json:"occurrenceCount,omitempty" yaml:"occurrenceCount,omitempty" mapstructure:"occurrenceCount,omitempty"` + + // A set of strings that contribute to the stable, unique identity of the result. + PartialFingerprints ResultPartialFingerprints `json:"partialFingerprints,omitempty" yaml:"partialFingerprints,omitempty" mapstructure:"partialFingerprints,omitempty"` + + // Key/value pairs that provide additional information about the result. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // Information about how and when the result was detected. + Provenance *ResultProvenance `json:"provenance,omitempty" yaml:"provenance,omitempty" mapstructure:"provenance,omitempty"` + + // A number representing the priority or importance of the result. + Rank float64 `json:"rank,omitempty" yaml:"rank,omitempty" mapstructure:"rank,omitempty"` + + // A set of locations relevant to this result. + RelatedLocations []Location `json:"relatedLocations,omitempty" yaml:"relatedLocations,omitempty" mapstructure:"relatedLocations,omitempty"` + + // A reference used to locate the rule descriptor relevant to this result. + Rule *ReportingDescriptorReference `json:"rule,omitempty" yaml:"rule,omitempty" mapstructure:"rule,omitempty"` + + // The stable, unique identifier of the rule, if any, to which this result is + // relevant. + RuleId *string `json:"ruleId,omitempty" yaml:"ruleId,omitempty" mapstructure:"ruleId,omitempty"` + + // The index within the tool component rules array of the rule object associated + // with this result. + RuleIndex int `json:"ruleIndex,omitempty" yaml:"ruleIndex,omitempty" mapstructure:"ruleIndex,omitempty"` + + // An array of 'stack' objects relevant to the result. + Stacks []Stack `json:"stacks,omitempty" yaml:"stacks,omitempty" mapstructure:"stacks,omitempty"` + + // A set of suppressions relevant to this result. + Suppressions []Suppression `json:"suppressions,omitempty" yaml:"suppressions,omitempty" mapstructure:"suppressions,omitempty"` + + // An array of references to taxonomy reporting descriptors that are applicable to + // the result. + Taxa []ReportingDescriptorReference `json:"taxa,omitempty" yaml:"taxa,omitempty" mapstructure:"taxa,omitempty"` + + // A web request associated with this result. + WebRequest *WebRequest `json:"webRequest,omitempty" yaml:"webRequest,omitempty" mapstructure:"webRequest,omitempty"` + + // A web response associated with this result. + WebResponse *WebResponse `json:"webResponse,omitempty" yaml:"webResponse,omitempty" mapstructure:"webResponse,omitempty"` + + // The URIs of the work items associated with this result. + WorkItemUris []string `json:"workItemUris,omitempty" yaml:"workItemUris,omitempty" mapstructure:"workItemUris,omitempty"` +} + +type ResultBaselineState string + +const ResultBaselineStateAbsent ResultBaselineState = "absent" +const ResultBaselineStateNew ResultBaselineState = "new" +const ResultBaselineStateUnchanged ResultBaselineState = "unchanged" +const ResultBaselineStateUpdated ResultBaselineState = "updated" + +var enumValues_ResultBaselineState = []interface{}{ + "new", + "unchanged", + "updated", + "absent", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultBaselineState) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ResultBaselineState { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ResultBaselineState, v) + } + *j = ResultBaselineState(v) + return nil +} + +// A set of strings each of which individually defines a stable, unique identity +// for the result. +type ResultFingerprints map[string]string + +type ResultKind string + +const ResultKindFail ResultKind = "fail" +const ResultKindInformational ResultKind = "informational" +const ResultKindNotApplicable ResultKind = "notApplicable" +const ResultKindOpen ResultKind = "open" +const ResultKindPass ResultKind = "pass" +const ResultKindReview ResultKind = "review" + +var enumValues_ResultKind = []interface{}{ + "notApplicable", + "pass", + "fail", + "review", + "open", + "informational", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultKind) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ResultKind { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ResultKind, v) + } + *j = ResultKind(v) + return nil +} + +type ResultLevel string + +const ResultLevelError ResultLevel = "error" +const ResultLevelNone ResultLevel = "none" +const ResultLevelNote ResultLevel = "note" +const ResultLevelWarning ResultLevel = "warning" + +var enumValues_ResultLevel = []interface{}{ + "none", + "note", + "warning", + "error", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultLevel) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ResultLevel { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ResultLevel, v) + } + *j = ResultLevel(v) + return nil +} + +// A set of strings that contribute to the stable, unique identity of the result. +type ResultPartialFingerprints map[string]string + +// Contains information about how and when a result was detected. +type ResultProvenance struct { + // An array of physicalLocation objects which specify the portions of an analysis + // tool's output that a converter transformed into the result. + ConversionSources []PhysicalLocation `json:"conversionSources,omitempty" yaml:"conversionSources,omitempty" mapstructure:"conversionSources,omitempty"` + + // A GUID-valued string equal to the automationDetails.guid property of the run in + // which the result was first detected. + FirstDetectionRunGuid *string `json:"firstDetectionRunGuid,omitempty" yaml:"firstDetectionRunGuid,omitempty" mapstructure:"firstDetectionRunGuid,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the result was + // first detected. See "Date/time properties" in the SARIF spec for the required + // format. + FirstDetectionTimeUtc *time.Time `json:"firstDetectionTimeUtc,omitempty" yaml:"firstDetectionTimeUtc,omitempty" mapstructure:"firstDetectionTimeUtc,omitempty"` + + // The index within the run.invocations array of the invocation object which + // describes the tool invocation that detected the result. + InvocationIndex int `json:"invocationIndex,omitempty" yaml:"invocationIndex,omitempty" mapstructure:"invocationIndex,omitempty"` + + // A GUID-valued string equal to the automationDetails.guid property of the run in + // which the result was most recently detected. + LastDetectionRunGuid *string `json:"lastDetectionRunGuid,omitempty" yaml:"lastDetectionRunGuid,omitempty" mapstructure:"lastDetectionRunGuid,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which the result was most + // recently detected. See "Date/time properties" in the SARIF spec for the + // required format. + LastDetectionTimeUtc *time.Time `json:"lastDetectionTimeUtc,omitempty" yaml:"lastDetectionTimeUtc,omitempty" mapstructure:"lastDetectionTimeUtc,omitempty"` + + // Key/value pairs that provide additional information about the result. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ResultProvenance) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ResultProvenance + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["conversionSources"]; !ok || v == nil { + plain.ConversionSources = []PhysicalLocation{} + } + if plain.FirstDetectionRunGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.FirstDetectionRunGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "FirstDetectionRunGuid") + } + } + if v, ok := raw["invocationIndex"]; !ok || v == nil { + plain.InvocationIndex = -1.0 + } + if -1 > plain.InvocationIndex { + return fmt.Errorf("field %s: must be >= %v", "invocationIndex", -1) + } + if plain.LastDetectionRunGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.LastDetectionRunGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "LastDetectionRunGuid") + } + } + *j = ResultProvenance(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Result) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["message"]; raw != nil && !ok { + return fmt.Errorf("field message in Result: required") + } + type Plain Result + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["attachments"]; !ok || v == nil { + plain.Attachments = []Attachment{} + } + if v, ok := raw["codeFlows"]; !ok || v == nil { + plain.CodeFlows = []CodeFlow{} + } + if plain.CorrelationGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.CorrelationGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "CorrelationGuid") + } + } + if v, ok := raw["fixes"]; !ok || v == nil { + plain.Fixes = []Fix{} + } + if v, ok := raw["graphTraversals"]; !ok || v == nil { + plain.GraphTraversals = []GraphTraversal{} + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []Graph{} + } + if v, ok := raw["kind"]; !ok || v == nil { + plain.Kind = "fail" + } + if v, ok := raw["level"]; !ok || v == nil { + plain.Level = "warning" + } + if v, ok := raw["locations"]; !ok || v == nil { + plain.Locations = []Location{} + } + if plain.OccurrenceCount != nil && 1 > *plain.OccurrenceCount { + return fmt.Errorf("field %s: must be >= %v", "occurrenceCount", 1) + } + if v, ok := raw["rank"]; !ok || v == nil { + plain.Rank = -1.0 + } + if 100 < plain.Rank { + return fmt.Errorf("field %s: must be <= %v", "rank", 100) + } + if -1 > plain.Rank { + return fmt.Errorf("field %s: must be >= %v", "rank", -1) + } + if v, ok := raw["relatedLocations"]; !ok || v == nil { + plain.RelatedLocations = []Location{} + } + if v, ok := raw["ruleIndex"]; !ok || v == nil { + plain.RuleIndex = -1.0 + } + if -1 > plain.RuleIndex { + return fmt.Errorf("field %s: must be >= %v", "ruleIndex", -1) + } + if v, ok := raw["stacks"]; !ok || v == nil { + plain.Stacks = []Stack{} + } + if v, ok := raw["taxa"]; !ok || v == nil { + plain.Taxa = []ReportingDescriptorReference{} + } + *j = Result(plain) + return nil +} + +// Describes a single run of an analysis tool, and contains the reported output of +// that run. +type Run struct { + // Addresses associated with this run instance, if any. + Addresses []Address `json:"addresses,omitempty" yaml:"addresses,omitempty" mapstructure:"addresses,omitempty"` + + // An array of artifact objects relevant to the run. + Artifacts []Artifact `json:"artifacts,omitempty" yaml:"artifacts,omitempty" mapstructure:"artifacts,omitempty"` + + // Automation details that describe this run. + AutomationDetails *RunAutomationDetails `json:"automationDetails,omitempty" yaml:"automationDetails,omitempty" mapstructure:"automationDetails,omitempty"` + + // The 'guid' property of a previous SARIF 'run' that comprises the baseline that + // was used to compute result 'baselineState' properties for the run. + BaselineGuid *string `json:"baselineGuid,omitempty" yaml:"baselineGuid,omitempty" mapstructure:"baselineGuid,omitempty"` + + // Specifies the unit in which the tool measures columns. + ColumnKind *RunColumnKind `json:"columnKind,omitempty" yaml:"columnKind,omitempty" mapstructure:"columnKind,omitempty"` + + // A conversion object that describes how a converter transformed an analysis + // tool's native reporting format into the SARIF format. + Conversion *Conversion `json:"conversion,omitempty" yaml:"conversion,omitempty" mapstructure:"conversion,omitempty"` + + // Specifies the default encoding for any artifact object that refers to a text + // file. + DefaultEncoding *string `json:"defaultEncoding,omitempty" yaml:"defaultEncoding,omitempty" mapstructure:"defaultEncoding,omitempty"` + + // Specifies the default source language for any artifact object that refers to a + // text file that contains source code. + DefaultSourceLanguage *string `json:"defaultSourceLanguage,omitempty" yaml:"defaultSourceLanguage,omitempty" mapstructure:"defaultSourceLanguage,omitempty"` + + // References to external property files that should be inlined with the content + // of a root log file. + ExternalPropertyFileReferences *ExternalPropertyFileReferences `json:"externalPropertyFileReferences,omitempty" yaml:"externalPropertyFileReferences,omitempty" mapstructure:"externalPropertyFileReferences,omitempty"` + + // An array of zero or more unique graph objects associated with the run. + Graphs []Graph `json:"graphs,omitempty" yaml:"graphs,omitempty" mapstructure:"graphs,omitempty"` + + // Describes the invocation of the analysis tool. + Invocations []Invocation `json:"invocations,omitempty" yaml:"invocations,omitempty" mapstructure:"invocations,omitempty"` + + // The language of the messages emitted into the log file during this run + // (expressed as an ISO 639-1 two-letter lowercase culture code) and an optional + // region (expressed as an ISO 3166-1 two-letter uppercase subculture code + // associated with a country or region). The casing is recommended but not + // required (in order for this data to conform to RFC5646). + Language *Language `json:"language,omitempty" yaml:"language,omitempty" mapstructure:"language,omitempty"` + + // An array of logical locations such as namespaces, types or functions. + LogicalLocations []LogicalLocation `json:"logicalLocations,omitempty" yaml:"logicalLocations,omitempty" mapstructure:"logicalLocations,omitempty"` + + // An ordered list of character sequences that were treated as line breaks when + // computing region information for the run. + NewlineSequences []string `json:"newlineSequences,omitempty" yaml:"newlineSequences,omitempty" mapstructure:"newlineSequences,omitempty"` + + // The artifact location specified by each uriBaseId symbol on the machine where + // the tool originally ran. + OriginalUriBaseIds RunOriginalUriBaseIds `json:"originalUriBaseIds,omitempty" yaml:"originalUriBaseIds,omitempty" mapstructure:"originalUriBaseIds,omitempty"` + + // Contains configurations that may potentially override both + // reportingDescriptor.defaultConfiguration (the tool's default severities) and + // invocation.configurationOverrides (severities established at run-time from the + // command line). + Policies []ToolComponent `json:"policies,omitempty" yaml:"policies,omitempty" mapstructure:"policies,omitempty"` + + // Key/value pairs that provide additional information about the run. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // An array of strings used to replace sensitive information in a redaction-aware + // property. + RedactionTokens []string `json:"redactionTokens,omitempty" yaml:"redactionTokens,omitempty" mapstructure:"redactionTokens,omitempty"` + + // The set of results contained in an SARIF log. The results array can be omitted + // when a run is solely exporting rules metadata. It must be present (but may be + // empty) if a log file represents an actual scan. + Results []Result `json:"results,omitempty" yaml:"results,omitempty" mapstructure:"results,omitempty"` + + // Automation details that describe the aggregate of runs to which this run + // belongs. + RunAggregates []RunAutomationDetails `json:"runAggregates,omitempty" yaml:"runAggregates,omitempty" mapstructure:"runAggregates,omitempty"` + + // A specialLocations object that defines locations of special significance to + // SARIF consumers. + SpecialLocations *SpecialLocations `json:"specialLocations,omitempty" yaml:"specialLocations,omitempty" mapstructure:"specialLocations,omitempty"` + + // An array of toolComponent objects relevant to a taxonomy in which results are + // categorized. + Taxonomies []ToolComponent `json:"taxonomies,omitempty" yaml:"taxonomies,omitempty" mapstructure:"taxonomies,omitempty"` + + // An array of threadFlowLocation objects cached at run level. + ThreadFlowLocations []ThreadFlowLocation `json:"threadFlowLocations,omitempty" yaml:"threadFlowLocations,omitempty" mapstructure:"threadFlowLocations,omitempty"` + + // Information about the tool or tool pipeline that generated the results in this + // run. A run can only contain results produced by a single tool or tool pipeline. + // A run can aggregate results from multiple log files, as long as context around + // the tool run (tool command-line arguments and the like) is identical for all + // aggregated files. + Tool Tool `json:"tool" yaml:"tool" mapstructure:"tool"` + + // The set of available translations of the localized data provided by the tool. + Translations []ToolComponent `json:"translations,omitempty" yaml:"translations,omitempty" mapstructure:"translations,omitempty"` + + // Specifies the revision in version control of the artifacts that were scanned. + VersionControlProvenance []VersionControlDetails `json:"versionControlProvenance,omitempty" yaml:"versionControlProvenance,omitempty" mapstructure:"versionControlProvenance,omitempty"` + + // An array of request objects cached at run level. + WebRequests []WebRequest `json:"webRequests,omitempty" yaml:"webRequests,omitempty" mapstructure:"webRequests,omitempty"` + + // An array of response objects cached at run level. + WebResponses []WebResponse `json:"webResponses,omitempty" yaml:"webResponses,omitempty" mapstructure:"webResponses,omitempty"` +} + +// Information that describes a run's identity and role within an engineering +// system process. +type RunAutomationDetails struct { + // A stable, unique identifier for the equivalence class of runs to which this + // object's containing run object belongs in the form of a GUID. + CorrelationGuid *string `json:"correlationGuid,omitempty" yaml:"correlationGuid,omitempty" mapstructure:"correlationGuid,omitempty"` + + // A description of the identity and role played within the engineering system by + // this object's containing run object. + Description *Message `json:"description,omitempty" yaml:"description,omitempty" mapstructure:"description,omitempty"` + + // A stable, unique identifier for this object's containing run object in the form + // of a GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // A hierarchical string that uniquely identifies this object's containing run + // object. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // Key/value pairs that provide additional information about the run automation + // details. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *RunAutomationDetails) UnmarshalJSON(b []byte) error { + type Plain RunAutomationDetails + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.CorrelationGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.CorrelationGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "CorrelationGuid") + } + } + *j = RunAutomationDetails(plain) + return nil +} + +type RunColumnKind string + +const RunColumnKindUnicodeCodePoints RunColumnKind = "unicodeCodePoints" +const RunColumnKindUtf16CodeUnits RunColumnKind = "utf16CodeUnits" + +var enumValues_RunColumnKind = []interface{}{ + "utf16CodeUnits", + "unicodeCodePoints", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *RunColumnKind) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_RunColumnKind { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_RunColumnKind, v) + } + *j = RunColumnKind(v) + return nil +} + +// The artifact location specified by each uriBaseId symbol on the machine where +// the tool originally ran. +type RunOriginalUriBaseIds map[string]ArtifactLocation + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Run) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["tool"]; raw != nil && !ok { + return fmt.Errorf("field tool in Run: required") + } + type Plain Run + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["addresses"]; !ok || v == nil { + plain.Addresses = []Address{} + } + if plain.BaselineGuid != nil { + if matched, _ := regexp.MatchString("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", string(*plain.BaselineGuid)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$", "BaselineGuid") + } + } + if v, ok := raw["graphs"]; !ok || v == nil { + plain.Graphs = []Graph{} + } + if v, ok := raw["invocations"]; !ok || v == nil { + plain.Invocations = []Invocation{} + } + if v, ok := raw["logicalLocations"]; !ok || v == nil { + plain.LogicalLocations = []LogicalLocation{} + } + if v, ok := raw["newlineSequences"]; !ok || v == nil { + plain.NewlineSequences = []string{ + "\r\n", + "\n", + } + } + if plain.NewlineSequences != nil && len(plain.NewlineSequences) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "newlineSequences", 1) + } + if v, ok := raw["policies"]; !ok || v == nil { + plain.Policies = []ToolComponent{} + } + if v, ok := raw["redactionTokens"]; !ok || v == nil { + plain.RedactionTokens = []string{} + } + if v, ok := raw["runAggregates"]; !ok || v == nil { + plain.RunAggregates = []RunAutomationDetails{} + } + if v, ok := raw["taxonomies"]; !ok || v == nil { + plain.Taxonomies = []ToolComponent{} + } + if v, ok := raw["threadFlowLocations"]; !ok || v == nil { + plain.ThreadFlowLocations = []ThreadFlowLocation{} + } + if v, ok := raw["translations"]; !ok || v == nil { + plain.Translations = []ToolComponent{} + } + if v, ok := raw["versionControlProvenance"]; !ok || v == nil { + plain.VersionControlProvenance = []VersionControlDetails{} + } + if v, ok := raw["webRequests"]; !ok || v == nil { + plain.WebRequests = []WebRequest{} + } + if v, ok := raw["webResponses"]; !ok || v == nil { + plain.WebResponses = []WebResponse{} + } + *j = Run(plain) + return nil +} + +// Static Analysis Results Format (SARIF) Version 2.2 JSON Schema: a standard +// format for the output of static analysis tools. +type SchemaJson struct { + // The URI of the JSON schema corresponding to the version. + Schema *string `json:"$schema,omitempty" yaml:"$schema,omitempty" mapstructure:"$schema,omitempty"` + + // A stable, unique identifier for the external property file in the form of a + // GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // References to external property files that share data between runs. + InlineExternalProperties []ExternalProperties `json:"inlineExternalProperties,omitempty" yaml:"inlineExternalProperties,omitempty" mapstructure:"inlineExternalProperties,omitempty"` + + // Key/value pairs that provide additional information about the log file. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The set of runs contained in this log file. + Runs []Run `json:"runs" yaml:"runs" mapstructure:"runs"` + + // The SARIF format version of this log file. + Version SchemaJsonVersion `json:"version" yaml:"version" mapstructure:"version"` +} + +type SchemaJsonVersion string + +const SchemaJsonVersionA22 SchemaJsonVersion = "2.2" + +var enumValues_SchemaJsonVersion = []interface{}{ + "2.2", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SchemaJsonVersion) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_SchemaJsonVersion { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_SchemaJsonVersion, v) + } + *j = SchemaJsonVersion(v) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SchemaJson) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["runs"]; raw != nil && !ok { + return fmt.Errorf("field runs in SchemaJson: required") + } + if _, ok := raw["version"]; raw != nil && !ok { + return fmt.Errorf("field version in SchemaJson: required") + } + type Plain SchemaJson + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = SchemaJson(plain) + return nil +} + +// Defines locations of special significance to SARIF consumers. +type SpecialLocations struct { + // Provides a suggestion to SARIF consumers to display file paths relative to the + // specified location. + DisplayBase *ArtifactLocation `json:"displayBase,omitempty" yaml:"displayBase,omitempty" mapstructure:"displayBase,omitempty"` + + // Key/value pairs that provide additional information about the special + // locations. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// A call stack that is relevant to a result. +type Stack struct { + // An array of stack frames that represents a sequence of calls, rendered in + // reverse chronological order, that comprise the call stack. + Frames []StackFrame `json:"frames" yaml:"frames" mapstructure:"frames"` + + // A message relevant to this call stack. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the stack. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// A function call within a stack trace. +type StackFrame struct { + // The location to which this stack frame refers. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // The name of the module that contains the code of this stack frame. + Module *string `json:"module,omitempty" yaml:"module,omitempty" mapstructure:"module,omitempty"` + + // The parameters of the call that is executing. + Parameters []string `json:"parameters,omitempty" yaml:"parameters,omitempty" mapstructure:"parameters,omitempty"` + + // Key/value pairs that provide additional information about the stack frame. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The thread identifier of the stack frame. + ThreadId *int `json:"threadId,omitempty" yaml:"threadId,omitempty" mapstructure:"threadId,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *StackFrame) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain StackFrame + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["parameters"]; !ok || v == nil { + plain.Parameters = []string{} + } + *j = StackFrame(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Stack) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["frames"]; raw != nil && !ok { + return fmt.Errorf("field frames in Stack: required") + } + type Plain Stack + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Stack(plain) + return nil +} + +// A suppression that is relevant to a result. +type Suppression struct { + // A stable, unique identifier for the suprression in the form of a GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // A string representing the justification for the suppression. + Justification *string `json:"justification,omitempty" yaml:"justification,omitempty" mapstructure:"justification,omitempty"` + + // A string that indicates where the suppression is persisted. + Kind SuppressionKind `json:"kind" yaml:"kind" mapstructure:"kind"` + + // Identifies the location associated with the suppression. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // Key/value pairs that provide additional information about the suppression. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A string that indicates the review status of the suppression. + Status *SuppressionStatus `json:"status,omitempty" yaml:"status,omitempty" mapstructure:"status,omitempty"` +} + +type SuppressionKind string + +const SuppressionKindExternal SuppressionKind = "external" +const SuppressionKindInSource SuppressionKind = "inSource" + +var enumValues_SuppressionKind = []interface{}{ + "inSource", + "external", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SuppressionKind) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_SuppressionKind { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_SuppressionKind, v) + } + *j = SuppressionKind(v) + return nil +} + +type SuppressionStatus string + +const SuppressionStatusAccepted SuppressionStatus = "accepted" +const SuppressionStatusRejected SuppressionStatus = "rejected" +const SuppressionStatusUnderReview SuppressionStatus = "underReview" + +var enumValues_SuppressionStatus = []interface{}{ + "accepted", + "underReview", + "rejected", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *SuppressionStatus) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_SuppressionStatus { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_SuppressionStatus, v) + } + *j = SuppressionStatus(v) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Suppression) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["kind"]; raw != nil && !ok { + return fmt.Errorf("field kind in Suppression: required") + } + type Plain Suppression + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = Suppression(plain) + return nil +} + +// Describes a sequence of code locations that specify a path through a single +// thread of execution such as an operating system or fiber. +type ThreadFlow struct { + // An string that uniquely identifies the threadFlow within the codeFlow in which + // it occurs. + Id *string `json:"id,omitempty" yaml:"id,omitempty" mapstructure:"id,omitempty"` + + // Values of relevant expressions at the start of the thread flow that remain + // constant. + ImmutableState ThreadFlowImmutableState `json:"immutableState,omitempty" yaml:"immutableState,omitempty" mapstructure:"immutableState,omitempty"` + + // Values of relevant expressions at the start of the thread flow that may change + // during thread flow execution. + InitialState ThreadFlowInitialState `json:"initialState,omitempty" yaml:"initialState,omitempty" mapstructure:"initialState,omitempty"` + + // A temporally ordered array of 'threadFlowLocation' objects, each of which + // describes a location visited by the tool while producing the result. + Locations []ThreadFlowLocation `json:"locations" yaml:"locations" mapstructure:"locations"` + + // A message relevant to the thread flow. + Message *Message `json:"message,omitempty" yaml:"message,omitempty" mapstructure:"message,omitempty"` + + // Key/value pairs that provide additional information about the thread flow. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// Values of relevant expressions at the start of the thread flow that remain +// constant. +type ThreadFlowImmutableState map[string]MultiformatMessageString + +// Values of relevant expressions at the start of the thread flow that may change +// during thread flow execution. +type ThreadFlowInitialState map[string]MultiformatMessageString + +// A location visited by an analysis tool while simulating or monitoring the +// execution of a program. +type ThreadFlowLocation struct { + // An integer representing the temporal order in which execution reached this + // location. + ExecutionOrder int `json:"executionOrder,omitempty" yaml:"executionOrder,omitempty" mapstructure:"executionOrder,omitempty"` + + // The Coordinated Universal Time (UTC) date and time at which this location was + // executed. + ExecutionTimeUtc *time.Time `json:"executionTimeUtc,omitempty" yaml:"executionTimeUtc,omitempty" mapstructure:"executionTimeUtc,omitempty"` + + // Specifies the importance of this location in understanding the code flow in + // which it occurs. The order from most to least important is "essential", + // "important", "unimportant". Default: "important". + Importance ThreadFlowLocationImportance `json:"importance,omitempty" yaml:"importance,omitempty" mapstructure:"importance,omitempty"` + + // The index within the run threadFlowLocations array. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // A set of distinct strings that categorize the thread flow location. Well-known + // kinds include 'acquire', 'release', 'enter', 'exit', 'call', 'return', + // 'branch', 'implicit', 'false', 'true', 'caution', 'danger', 'unknown', + // 'unreachable', 'taint', 'function', 'handler', 'lock', 'memory', 'resource', + // 'scope' and 'value'. + Kinds []string `json:"kinds,omitempty" yaml:"kinds,omitempty" mapstructure:"kinds,omitempty"` + + // The code location. + Location *Location `json:"location,omitempty" yaml:"location,omitempty" mapstructure:"location,omitempty"` + + // The name of the module that contains the code that is executing. + Module *string `json:"module,omitempty" yaml:"module,omitempty" mapstructure:"module,omitempty"` + + // An integer representing a containment hierarchy within the thread flow. + NestingLevel *int `json:"nestingLevel,omitempty" yaml:"nestingLevel,omitempty" mapstructure:"nestingLevel,omitempty"` + + // Key/value pairs that provide additional information about the threadflow + // location. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The call stack leading to this location. + Stack *Stack `json:"stack,omitempty" yaml:"stack,omitempty" mapstructure:"stack,omitempty"` + + // A dictionary, each of whose keys specifies a variable or expression, the + // associated value of which represents the variable or expression value. For an + // annotation of kind 'continuation', for example, this dictionary might hold the + // current assumed values of a set of global variables. + State ThreadFlowLocationState `json:"state,omitempty" yaml:"state,omitempty" mapstructure:"state,omitempty"` + + // An array of references to rule or taxonomy reporting descriptors that are + // applicable to the thread flow location. + Taxa []ReportingDescriptorReference `json:"taxa,omitempty" yaml:"taxa,omitempty" mapstructure:"taxa,omitempty"` + + // A web request associated with this thread flow location. + WebRequest *WebRequest `json:"webRequest,omitempty" yaml:"webRequest,omitempty" mapstructure:"webRequest,omitempty"` + + // A web response associated with this thread flow location. + WebResponse *WebResponse `json:"webResponse,omitempty" yaml:"webResponse,omitempty" mapstructure:"webResponse,omitempty"` +} + +type ThreadFlowLocationImportance string + +const ThreadFlowLocationImportanceEssential ThreadFlowLocationImportance = "essential" +const ThreadFlowLocationImportanceImportant ThreadFlowLocationImportance = "important" +const ThreadFlowLocationImportanceUnimportant ThreadFlowLocationImportance = "unimportant" + +var enumValues_ThreadFlowLocationImportance = []interface{}{ + "important", + "essential", + "unimportant", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ThreadFlowLocationImportance) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ThreadFlowLocationImportance { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ThreadFlowLocationImportance, v) + } + *j = ThreadFlowLocationImportance(v) + return nil +} + +// A dictionary, each of whose keys specifies a variable or expression, the +// associated value of which represents the variable or expression value. For an +// annotation of kind 'continuation', for example, this dictionary might hold the +// current assumed values of a set of global variables. +type ThreadFlowLocationState map[string]MultiformatMessageString + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ThreadFlowLocation) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ThreadFlowLocation + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["executionOrder"]; !ok || v == nil { + plain.ExecutionOrder = -1.0 + } + if -1 > plain.ExecutionOrder { + return fmt.Errorf("field %s: must be >= %v", "executionOrder", -1) + } + if v, ok := raw["importance"]; !ok || v == nil { + plain.Importance = "important" + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["kinds"]; !ok || v == nil { + plain.Kinds = []string{} + } + if plain.NestingLevel != nil && 0 > *plain.NestingLevel { + return fmt.Errorf("field %s: must be >= %v", "nestingLevel", 0) + } + if v, ok := raw["taxa"]; !ok || v == nil { + plain.Taxa = []ReportingDescriptorReference{} + } + *j = ThreadFlowLocation(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ThreadFlow) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["locations"]; raw != nil && !ok { + return fmt.Errorf("field locations in ThreadFlow: required") + } + type Plain ThreadFlow + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if plain.Locations != nil && len(plain.Locations) < 1 { + return fmt.Errorf("field %s length: must be >= %d", "locations", 1) + } + *j = ThreadFlow(plain) + return nil +} + +// The analysis tool that was run. +type Tool struct { + // The analysis tool that was run. + Driver ToolComponent `json:"driver" yaml:"driver" mapstructure:"driver"` + + // Tool extensions that contributed to or reconfigured the analysis tool that was + // run. + Extensions []ToolComponent `json:"extensions,omitempty" yaml:"extensions,omitempty" mapstructure:"extensions,omitempty"` + + // Key/value pairs that provide additional information about the tool. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// A component, such as a plug-in or the driver, of the analysis tool that was run. +type ToolComponent struct { + // The component which is strongly associated with this component. For a + // translation, this refers to the component which has been translated. For an + // extension, this is the driver that provides the extension's plugin model. + AssociatedComponent *ToolComponentReference `json:"associatedComponent,omitempty" yaml:"associatedComponent,omitempty" mapstructure:"associatedComponent,omitempty"` + + // The kinds of data contained in this object. + Contents []ToolComponentContentsElem `json:"contents,omitempty" yaml:"contents,omitempty" mapstructure:"contents,omitempty"` + + // The binary version of the tool component's primary executable file expressed as + // four non-negative integers separated by a period (for operating systems that + // express file versions in this way). + DottedQuadFileVersion *string `json:"dottedQuadFileVersion,omitempty" yaml:"dottedQuadFileVersion,omitempty" mapstructure:"dottedQuadFileVersion,omitempty"` + + // The absolute URI from which the tool component can be downloaded. + DownloadUri *string `json:"downloadUri,omitempty" yaml:"downloadUri,omitempty" mapstructure:"downloadUri,omitempty"` + + // A comprehensive description of the tool component. + FullDescription *MultiformatMessageString `json:"fullDescription,omitempty" yaml:"fullDescription,omitempty" mapstructure:"fullDescription,omitempty"` + + // The name of the tool component along with its version and any other useful + // identifying information, such as its locale. + FullName *string `json:"fullName,omitempty" yaml:"fullName,omitempty" mapstructure:"fullName,omitempty"` + + // A dictionary, each of whose keys is a resource identifier and each of whose + // values is a multiformatMessageString object, which holds message strings in + // plain text and (optionally) Markdown format. The strings can include + // placeholders, which can be used to construct a message in combination with an + // arbitrary number of additional string arguments. + GlobalMessageStrings ToolComponentGlobalMessageStrings `json:"globalMessageStrings,omitempty" yaml:"globalMessageStrings,omitempty" mapstructure:"globalMessageStrings,omitempty"` + + // A unique identifier for the tool component in the form of a GUID. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // The absolute URI at which information about this version of the tool component + // can be found. + InformationUri *string `json:"informationUri,omitempty" yaml:"informationUri,omitempty" mapstructure:"informationUri,omitempty"` + + // Specifies whether this object contains a complete definition of the localizable + // and/or non-localizable data for this component, as opposed to including only + // data that is relevant to the results persisted to this log file. + IsComprehensive bool `json:"isComprehensive,omitempty" yaml:"isComprehensive,omitempty" mapstructure:"isComprehensive,omitempty"` + + // The language of the messages emitted into the log file during this run + // (expressed as an ISO 639-1 two-letter lowercase language code) and an optional + // region (expressed as an ISO 3166-1 two-letter uppercase subculture code + // associated with a country or region). The casing is recommended but not + // required (in order for this data to conform to RFC5646). + Language *Language `json:"language,omitempty" yaml:"language,omitempty" mapstructure:"language,omitempty"` + + // The semantic version of the localized strings defined in this component; + // maintained by components that provide translations. + LocalizedDataSemanticVersion *string `json:"localizedDataSemanticVersion,omitempty" yaml:"localizedDataSemanticVersion,omitempty" mapstructure:"localizedDataSemanticVersion,omitempty"` + + // An array of the artifactLocation objects associated with the tool component. + Locations []ArtifactLocation `json:"locations,omitempty" yaml:"locations,omitempty" mapstructure:"locations,omitempty"` + + // The minimum value of localizedDataSemanticVersion required in translations + // consumed by this component; used by components that consume translations. + MinimumRequiredLocalizedDataSemanticVersion *string `json:"minimumRequiredLocalizedDataSemanticVersion,omitempty" yaml:"minimumRequiredLocalizedDataSemanticVersion,omitempty" mapstructure:"minimumRequiredLocalizedDataSemanticVersion,omitempty"` + + // The name of the tool component. + Name string `json:"name" yaml:"name" mapstructure:"name"` + + // An array of reportingDescriptor objects relevant to the notifications related + // to the configuration and runtime execution of the tool component. + Notifications []ReportingDescriptor `json:"notifications,omitempty" yaml:"notifications,omitempty" mapstructure:"notifications,omitempty"` + + // The organization or company that produced the tool component. + Organization *string `json:"organization,omitempty" yaml:"organization,omitempty" mapstructure:"organization,omitempty"` + + // A product suite to which the tool component belongs. + Product *string `json:"product,omitempty" yaml:"product,omitempty" mapstructure:"product,omitempty"` + + // A localizable string containing the name of the suite of products to which the + // tool component belongs. + ProductSuite *string `json:"productSuite,omitempty" yaml:"productSuite,omitempty" mapstructure:"productSuite,omitempty"` + + // Key/value pairs that provide additional information about the tool component. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A string specifying the UTC date (and optionally, the time) of the component's + // release. + ReleaseDateUtc *string `json:"releaseDateUtc,omitempty" yaml:"releaseDateUtc,omitempty" mapstructure:"releaseDateUtc,omitempty"` + + // An array of reportingDescriptor objects relevant to the analysis performed by + // the tool component. + Rules []ReportingDescriptor `json:"rules,omitempty" yaml:"rules,omitempty" mapstructure:"rules,omitempty"` + + // The tool component version in the format specified by Semantic Versioning 2.0. + SemanticVersion *string `json:"semanticVersion,omitempty" yaml:"semanticVersion,omitempty" mapstructure:"semanticVersion,omitempty"` + + // A brief description of the tool component. + ShortDescription *MultiformatMessageString `json:"shortDescription,omitempty" yaml:"shortDescription,omitempty" mapstructure:"shortDescription,omitempty"` + + // An array of toolComponentReference objects to declare the taxonomies supported + // by the tool component. + SupportedTaxonomies []ToolComponentReference `json:"supportedTaxonomies,omitempty" yaml:"supportedTaxonomies,omitempty" mapstructure:"supportedTaxonomies,omitempty"` + + // An array of reportingDescriptor objects relevant to the definitions of both + // standalone and tool-defined taxonomies. + Taxa []ReportingDescriptor `json:"taxa,omitempty" yaml:"taxa,omitempty" mapstructure:"taxa,omitempty"` + + // Translation metadata, required for a translation, not populated by other + // component types. + TranslationMetadata *TranslationMetadata `json:"translationMetadata,omitempty" yaml:"translationMetadata,omitempty" mapstructure:"translationMetadata,omitempty"` + + // The tool component version, in whatever format the component natively provides. + Version *string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` +} + +type ToolComponentContentsElem string + +const ToolComponentContentsElemLocalizedData ToolComponentContentsElem = "localizedData" +const ToolComponentContentsElemNonLocalizedData ToolComponentContentsElem = "nonLocalizedData" + +var enumValues_ToolComponentContentsElem = []interface{}{ + "localizedData", + "nonLocalizedData", +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ToolComponentContentsElem) UnmarshalJSON(b []byte) error { + var v string + if err := json.Unmarshal(b, &v); err != nil { + return err + } + var ok bool + for _, expected := range enumValues_ToolComponentContentsElem { + if reflect.DeepEqual(v, expected) { + ok = true + break + } + } + if !ok { + return fmt.Errorf("invalid value (expected one of %#v): %#v", enumValues_ToolComponentContentsElem, v) + } + *j = ToolComponentContentsElem(v) + return nil +} + +// A dictionary, each of whose keys is a resource identifier and each of whose +// values is a multiformatMessageString object, which holds message strings in +// plain text and (optionally) Markdown format. The strings can include +// placeholders, which can be used to construct a message in combination with an +// arbitrary number of additional string arguments. +type ToolComponentGlobalMessageStrings map[string]MultiformatMessageString + +// Identifies a particular toolComponent object, either the driver or an extension. +type ToolComponentReference struct { + // The 'guid' property of the referenced toolComponent. + Guid *Guid `json:"guid,omitempty" yaml:"guid,omitempty" mapstructure:"guid,omitempty"` + + // An index into the referenced toolComponent in tool.extensions. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // The 'name' property of the referenced toolComponent. + Name *string `json:"name,omitempty" yaml:"name,omitempty" mapstructure:"name,omitempty"` + + // Key/value pairs that provide additional information about the + // toolComponentReference. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ToolComponentReference) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain ToolComponentReference + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = ToolComponentReference(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *ToolComponent) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["name"]; raw != nil && !ok { + return fmt.Errorf("field name in ToolComponent: required") + } + type Plain ToolComponent + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["contents"]; !ok || v == nil { + plain.Contents = []ToolComponentContentsElem{ + "localizedData", + "nonLocalizedData", + } + } + if plain.DottedQuadFileVersion != nil { + if matched, _ := regexp.MatchString(`[0-9]+(\.[0-9]+){3}`, string(*plain.DottedQuadFileVersion)); !matched { + return fmt.Errorf("field %s pattern match: must match %s", `[0-9]+(\.[0-9]+){3}`, "DottedQuadFileVersion") + } + } + if v, ok := raw["isComprehensive"]; !ok || v == nil { + plain.IsComprehensive = false + } + if v, ok := raw["locations"]; !ok || v == nil { + plain.Locations = []ArtifactLocation{} + } + if v, ok := raw["notifications"]; !ok || v == nil { + plain.Notifications = []ReportingDescriptor{} + } + if v, ok := raw["rules"]; !ok || v == nil { + plain.Rules = []ReportingDescriptor{} + } + if v, ok := raw["supportedTaxonomies"]; !ok || v == nil { + plain.SupportedTaxonomies = []ToolComponentReference{} + } + if v, ok := raw["taxa"]; !ok || v == nil { + plain.Taxa = []ReportingDescriptor{} + } + *j = ToolComponent(plain) + return nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *Tool) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["driver"]; raw != nil && !ok { + return fmt.Errorf("field driver in Tool: required") + } + type Plain Tool + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["extensions"]; !ok || v == nil { + plain.Extensions = []ToolComponent{} + } + *j = Tool(plain) + return nil +} + +// Provides additional metadata related to translation. +type TranslationMetadata struct { + // The absolute URI from which the translation metadata can be downloaded. + DownloadUri *string `json:"downloadUri,omitempty" yaml:"downloadUri,omitempty" mapstructure:"downloadUri,omitempty"` + + // A comprehensive description of the translation metadata. + FullDescription *MultiformatMessageString `json:"fullDescription,omitempty" yaml:"fullDescription,omitempty" mapstructure:"fullDescription,omitempty"` + + // The full name associated with the translation metadata. + FullName *string `json:"fullName,omitempty" yaml:"fullName,omitempty" mapstructure:"fullName,omitempty"` + + // The absolute URI from which information related to the translation metadata can + // be downloaded. + InformationUri *string `json:"informationUri,omitempty" yaml:"informationUri,omitempty" mapstructure:"informationUri,omitempty"` + + // The name associated with the translation metadata. + Name string `json:"name" yaml:"name" mapstructure:"name"` + + // Key/value pairs that provide additional information about the translation + // metadata. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // A brief description of the translation metadata. + ShortDescription *MultiformatMessageString `json:"shortDescription,omitempty" yaml:"shortDescription,omitempty" mapstructure:"shortDescription,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *TranslationMetadata) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["name"]; raw != nil && !ok { + return fmt.Errorf("field name in TranslationMetadata: required") + } + type Plain TranslationMetadata + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = TranslationMetadata(plain) + return nil +} + +// Specifies the information necessary to retrieve a desired revision from a +// version control system. +type VersionControlDetails struct { + // A Coordinated Universal Time (UTC) date and time that can be used to + // synchronize an enlistment to the state of the repository at that time. + AsOfTimeUtc *time.Time `json:"asOfTimeUtc,omitempty" yaml:"asOfTimeUtc,omitempty" mapstructure:"asOfTimeUtc,omitempty"` + + // The name of a branch containing the revision. + Branch *string `json:"branch,omitempty" yaml:"branch,omitempty" mapstructure:"branch,omitempty"` + + // The location in the local file system to which the root of the repository was + // mapped at the time of the analysis. + MappedTo *ArtifactLocation `json:"mappedTo,omitempty" yaml:"mappedTo,omitempty" mapstructure:"mappedTo,omitempty"` + + // Key/value pairs that provide additional information about the version control + // details. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The absolute URI of the repository. + RepositoryUri string `json:"repositoryUri" yaml:"repositoryUri" mapstructure:"repositoryUri"` + + // A string that uniquely and permanently identifies the revision within the + // repository. + RevisionId *string `json:"revisionId,omitempty" yaml:"revisionId,omitempty" mapstructure:"revisionId,omitempty"` + + // A tag that has been applied to the revision. + RevisionTag *string `json:"revisionTag,omitempty" yaml:"revisionTag,omitempty" mapstructure:"revisionTag,omitempty"` +} + +// UnmarshalJSON implements json.Unmarshaler. +func (j *VersionControlDetails) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + if _, ok := raw["repositoryUri"]; raw != nil && !ok { + return fmt.Errorf("field repositoryUri in VersionControlDetails: required") + } + type Plain VersionControlDetails + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + *j = VersionControlDetails(plain) + return nil +} + +// Describes an HTTP request. +type WebRequest struct { + // The body of the request. + Body *ArtifactContent `json:"body,omitempty" yaml:"body,omitempty" mapstructure:"body,omitempty"` + + // The request headers. + Headers WebRequestHeaders `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // The index within the run.webRequests array of the request object associated + // with this result. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // The HTTP method. Well-known values are 'GET', 'PUT', 'POST', 'DELETE', 'PATCH', + // 'HEAD', 'OPTIONS', 'TRACE', 'CONNECT'. + Method *string `json:"method,omitempty" yaml:"method,omitempty" mapstructure:"method,omitempty"` + + // The request parameters. + Parameters WebRequestParameters `json:"parameters,omitempty" yaml:"parameters,omitempty" mapstructure:"parameters,omitempty"` + + // Key/value pairs that provide additional information about the request. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The request protocol. Example: 'http'. + Protocol *string `json:"protocol,omitempty" yaml:"protocol,omitempty" mapstructure:"protocol,omitempty"` + + // The target of the request. + Target *string `json:"target,omitempty" yaml:"target,omitempty" mapstructure:"target,omitempty"` + + // The request version. Example: '1.1'. + Version *string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` +} + +// The request headers. +type WebRequestHeaders map[string]string + +// The request parameters. +type WebRequestParameters map[string]string + +// UnmarshalJSON implements json.Unmarshaler. +func (j *WebRequest) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain WebRequest + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + *j = WebRequest(plain) + return nil +} + +// Describes the response to an HTTP request. +type WebResponse struct { + // The body of the response. + Body *ArtifactContent `json:"body,omitempty" yaml:"body,omitempty" mapstructure:"body,omitempty"` + + // The response headers. + Headers WebResponseHeaders `json:"headers,omitempty" yaml:"headers,omitempty" mapstructure:"headers,omitempty"` + + // The index within the run.webResponses array of the response object associated + // with this result. + Index int `json:"index,omitempty" yaml:"index,omitempty" mapstructure:"index,omitempty"` + + // Specifies whether a response was received from the server. + NoResponseReceived bool `json:"noResponseReceived,omitempty" yaml:"noResponseReceived,omitempty" mapstructure:"noResponseReceived,omitempty"` + + // Key/value pairs that provide additional information about the response. + Properties *PropertyBag `json:"properties,omitempty" yaml:"properties,omitempty" mapstructure:"properties,omitempty"` + + // The response protocol. Example: 'http'. + Protocol *string `json:"protocol,omitempty" yaml:"protocol,omitempty" mapstructure:"protocol,omitempty"` + + // The response reason. Example: 'Not found'. + ReasonPhrase *string `json:"reasonPhrase,omitempty" yaml:"reasonPhrase,omitempty" mapstructure:"reasonPhrase,omitempty"` + + // The response status code. Example: 451. + StatusCode *int `json:"statusCode,omitempty" yaml:"statusCode,omitempty" mapstructure:"statusCode,omitempty"` + + // The response version. Example: '1.1'. + Version *string `json:"version,omitempty" yaml:"version,omitempty" mapstructure:"version,omitempty"` +} + +// The response headers. +type WebResponseHeaders map[string]string + +// UnmarshalJSON implements json.Unmarshaler. +func (j *WebResponse) UnmarshalJSON(b []byte) error { + var raw map[string]interface{} + if err := json.Unmarshal(b, &raw); err != nil { + return err + } + type Plain WebResponse + var plain Plain + if err := json.Unmarshal(b, &plain); err != nil { + return err + } + if v, ok := raw["index"]; !ok || v == nil { + plain.Index = -1.0 + } + if -1 > plain.Index { + return fmt.Errorf("field %s: must be >= %v", "index", -1) + } + if v, ok := raw["noResponseReceived"]; !ok || v == nil { + plain.NoResponseReceived = false + } + *j = WebResponse(plain) + return nil +} diff --git a/sarif/testdata/gosec_v2.1.0.json b/sarif/testdata/gosec_v2.1.0.json new file mode 100644 index 0000000..5eaccbd --- /dev/null +++ b/sarif/testdata/gosec_v2.1.0.json @@ -0,0 +1,1314 @@ +{ + "runs": [ + { + "results": [ + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 11, + "endLine": 106, + "snippet": { + "text": "token := rand.Int()" + }, + "sourceLanguage": "go", + "startColumn": 11, + "startLine": 106 + } + } + } + ], + "message": { + "text": "Use of weak random number generator (math/rand instead of crypto/rand)" + }, + "ruleId": "G404" + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 13, + "endLine": 98, + "snippet": { + "text": "config := \u0026tls.Config{\nMinVersion: tls.VersionSSL30,\n}\n" + }, + "sourceLanguage": "go", + "startColumn": 13, + "startLine": 96 + } + } + } + ], + "message": { + "text": "TLS MinVersion too low." + }, + "ruleId": "G402", + "ruleIndex": 1 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 77, + "snippet": { + "text": "pass := \"' OR 1=1--\"" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 77 + } + } + } + ], + "message": { + "text": "Potential hardcoded credentials" + }, + "ruleId": "G101", + "ruleIndex": 2 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 21, + "endLine": 138, + "snippet": { + "text": "var intVal int16 = int16(num)" + }, + "sourceLanguage": "go", + "startColumn": 21, + "startLine": 138 + } + } + } + ], + "message": { + "text": "Potential Integer overflow made by strconv.Atoi result conversion to int16/32" + }, + "ruleId": "G109", + "ruleIndex": 3 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 15, + "endLine": 114, + "snippet": { + "text": "cipher, _ := rc4.NewCipher([]byte(\"secret\"))" + }, + "sourceLanguage": "go", + "startColumn": 15, + "startLine": 114 + } + } + } + ], + "message": { + "text": "Use of weak cryptographic primitive" + }, + "ruleId": "G401", + "ruleIndex": 4 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 14, + "endLine": 88, + "snippet": { + "text": "block, _ := des.NewCipher(key)" + }, + "sourceLanguage": "go", + "startColumn": 14, + "startLine": 88 + } + } + } + ], + "message": { + "text": "Use of weak cryptographic primitive" + }, + "ruleId": "G401", + "ruleIndex": 4 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 10, + "endLine": 36, + "snippet": { + "text": "hash := md5.New()" + }, + "sourceLanguage": "go", + "startColumn": 10, + "startLine": 36 + } + } + } + ], + "message": { + "text": "Use of weak cryptographic primitive" + }, + "ruleId": "G401", + "ruleIndex": 4 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 12, + "endLine": 152, + "snippet": { + "text": "log.Fatal(http.ListenAndServe(\":8080\", nil))" + }, + "sourceLanguage": "go", + "startColumn": 12, + "startLine": 152 + } + } + } + ], + "message": { + "text": "Use of net/http serve function that has no support for setting timeouts" + }, + "ruleId": "G114", + "ruleIndex": 5 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 11, + "endLine": 78, + "snippet": { + "text": "query := fmt.Sprintf(\"SELECT * FROM users WHERE username='%s' AND password='%s'\", username, pass)" + }, + "sourceLanguage": "go", + "startColumn": 11, + "startLine": 78 + } + } + } + ], + "message": { + "text": "SQL string formatting" + }, + "ruleId": "G201", + "ruleIndex": 6 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 16, + "endLine": 47, + "snippet": { + "text": "data, err := os.ReadFile(filePath)" + }, + "sourceLanguage": "go", + "startColumn": 16, + "startLine": 47 + } + } + } + ], + "message": { + "text": "Potential file inclusion via variable" + }, + "ruleId": "G304", + "ruleIndex": 7 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 129, + "snippet": { + "text": "http.Get(url)" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 129 + } + } + } + ], + "message": { + "text": "Potential HTTP request made with variable url" + }, + "ruleId": "G107", + "ruleIndex": 8 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 10, + "endLine": 149, + "snippet": { + "text": "_, _ = io.Copy(os.Stdout, gzr)" + }, + "sourceLanguage": "go", + "startColumn": 10, + "startLine": 149 + } + } + } + ], + "message": { + "text": "Potential DoS vulnerability via decompression bomb" + }, + "ruleId": "G110", + "ruleIndex": 9 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 121, + "snippet": { + "text": "defer resp.Body.Close()" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 121 + } + } + } + ], + "message": { + "text": "Deferring unsafe method \"Close\" on type \"io.ReadCloser\"" + }, + "ruleId": "G307", + "ruleIndex": 10 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 69, + "snippet": { + "text": "defer f.Close()" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 69 + } + } + } + ], + "message": { + "text": "Deferring unsafe method \"Close\" on type \"*os.File\"" + }, + "ruleId": "G307", + "ruleIndex": 10 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 7, + "snippet": { + "text": "\"crypto/rc4\"" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 7 + } + } + } + ], + "message": { + "text": "Blocklisted import crypto/rc4: weak cryptographic primitive" + }, + "ruleId": "G503", + "ruleIndex": 11 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 6, + "snippet": { + "text": "\"crypto/md5\"" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 6 + } + } + } + ], + "message": { + "text": "Blocklisted import crypto/md5: weak cryptographic primitive" + }, + "ruleId": "G501", + "ruleIndex": 12 + }, + { + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 5, + "snippet": { + "text": "\"crypto/des\"" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 5 + } + } + } + ], + "message": { + "text": "Blocklisted import crypto/des: weak cryptographic primitive" + }, + "ruleId": "G502", + "ruleIndex": 13 + }, + { + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 129, + "snippet": { + "text": "http.Get(url)" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 129 + } + } + } + ], + "message": { + "text": "Errors unhandled." + }, + "ruleId": "G104", + "ruleIndex": 14 + }, + { + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 80, + "snippet": { + "text": "db.Exec(query)" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 80 + } + } + } + ], + "message": { + "text": "Errors unhandled." + }, + "ruleId": "G104", + "ruleIndex": 14 + }, + { + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 2, + "endLine": 62, + "snippet": { + "text": "cmd.Run()" + }, + "sourceLanguage": "go", + "startColumn": 2, + "startLine": 62 + } + } + } + ], + "message": { + "text": "Errors unhandled." + }, + "ruleId": "G104", + "ruleIndex": 14 + }, + { + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.go" + }, + "region": { + "endColumn": 3, + "endLine": 52, + "snippet": { + "text": "w.Write(data)" + }, + "sourceLanguage": "go", + "startColumn": 3, + "startLine": 52 + } + } + } + ], + "message": { + "text": "Errors unhandled." + }, + "ruleId": "G104", + "ruleIndex": 14 + } + ], + "taxonomies": [ + { + "downloadUri": "https://cwe.mitre.org/data/xml/cwec_v4.4.xml.zip", + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "informationUri": "https://cwe.mitre.org/data/published/cwe_v4.4.pdf/", + "isComprehensive": true, + "language": "en", + "minimumRequiredLocalizedDataSemanticVersion": "4.4", + "name": "CWE", + "organization": "MITRE", + "releaseDateUtc": "2021-03-15", + "shortDescription": { + "text": "The MITRE Common Weakness Enumeration" + }, + "taxa": [ + { + "fullDescription": { + "text": "The software performs a calculation that can produce an integer overflow or wraparound, when the logic assumes that the resulting value will always be larger than the original value. This can introduce other weaknesses when the calculation is used for resource management or execution control." + }, + "guid": "c71e4fa0-720e-3e82-8b67-b2d44d0c604b", + "helpUri": "https://cwe.mitre.org/data/definitions/190.html", + "id": "190", + "shortDescription": { + "text": "Integer Overflow or Wraparound" + } + }, + { + "fullDescription": { + "text": "The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory." + }, + "guid": "3e718404-88bc-3f17-883e-e85e74078a76", + "helpUri": "https://cwe.mitre.org/data/definitions/22.html", + "id": "22", + "shortDescription": { + "text": "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')" + } + }, + { + "fullDescription": { + "text": "The software does not validate, or incorrectly validates, a certificate." + }, + "guid": "09e885ea-951b-3143-801a-241b3aa9e6c9", + "helpUri": "https://cwe.mitre.org/data/definitions/295.html", + "id": "295", + "shortDescription": { + "text": "Improper Certificate Validation" + } + }, + { + "fullDescription": { + "text": "The software stores or transmits sensitive data using an encryption scheme that is theoretically sound, but is not strong enough for the level of protection required." + }, + "guid": "fe6ccccf-c3a1-354b-b67c-6c76007360e6", + "helpUri": "https://cwe.mitre.org/data/definitions/326.html", + "id": "326", + "shortDescription": { + "text": "Inadequate Encryption Strength" + } + }, + { + "fullDescription": { + "text": "The use of a broken or risky cryptographic algorithm is an unnecessary risk that may result in the exposure of sensitive information." + }, + "guid": "3d8ac75a-952a-30cd-ab4f-911c879d8d2b", + "helpUri": "https://cwe.mitre.org/data/definitions/327.html", + "id": "327", + "shortDescription": { + "text": "Use of a Broken or Risky Cryptographic Algorithm" + } + }, + { + "fullDescription": { + "text": "The product uses a Pseudo-Random Number Generator (PRNG) in a security context, but the PRNG's algorithm is not cryptographically strong." + }, + "guid": "0512047f-75a2-3ac3-bb28-97df3a80efbe", + "helpUri": "https://cwe.mitre.org/data/definitions/338.html", + "id": "338", + "shortDescription": { + "text": "Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)" + } + }, + { + "fullDescription": { + "text": "The software does not handle or incorrectly handles a compressed input with a very high compression ratio that produces a large output." + }, + "guid": "8f97f42f-c62a-3d38-b26d-97951029c895", + "helpUri": "https://cwe.mitre.org/data/definitions/409.html", + "id": "409", + "shortDescription": { + "text": "Improper Handling of Highly Compressed Data (Data Amplification)" + } + }, + { + "fullDescription": { + "text": "The program invokes a potentially dangerous function that could introduce a vulnerability if it is used incorrectly, but the function can also be used safely." + }, + "guid": "f97fef5f-b85b-3d63-9932-7053f298803d", + "helpUri": "https://cwe.mitre.org/data/definitions/676.html", + "id": "676", + "shortDescription": { + "text": "Use of Potentially Dangerous Function" + } + }, + { + "fullDescription": { + "text": "The software does not properly anticipate or handle exceptional conditions that rarely occur during normal operation of the software." + }, + "guid": "7df38d1d-038e-3ced-8601-8d9265b90a25", + "helpUri": "https://cwe.mitre.org/data/definitions/703.html", + "id": "703", + "shortDescription": { + "text": "Improper Check or Handling of Exceptional Conditions" + } + }, + { + "fullDescription": { + "text": "The software contains hard-coded credentials, such as a password or cryptographic key, which it uses for its own inbound authentication, outbound communication to external components, or encryption of internal data." + }, + "guid": "93d834a1-2cc5-38db-837f-66dfc7d711cc", + "helpUri": "https://cwe.mitre.org/data/definitions/798.html", + "id": "798", + "shortDescription": { + "text": "Use of Hard-coded Credentials" + } + }, + { + "fullDescription": { + "text": "The software constructs a string for a command to executed by a separate component\nin another control sphere, but it does not properly delimit the\nintended arguments, options, or switches within that command string." + }, + "guid": "d684c7e2-3856-3079-900b-f59c57ace34b", + "helpUri": "https://cwe.mitre.org/data/definitions/88.html", + "id": "88", + "shortDescription": { + "text": "Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')" + } + }, + { + "fullDescription": { + "text": "The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component." + }, + "guid": "6bd55435-166c-3594-bc06-5e0dea916067", + "helpUri": "https://cwe.mitre.org/data/definitions/89.html", + "id": "89", + "shortDescription": { + "text": "Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')" + } + } + ], + "version": "4.4" + } + ], + "tool": { + "driver": { + "guid": "8b518d5f-906d-39f9-894b-d327b1a421c5", + "informationUri": "https://github.com/securego/gosec/", + "name": "gosec", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Potential hardcoded credentials" + }, + "help": { + "text": "Potential hardcoded credentials\nSeverity: HIGH\nConfidence: LOW\n" + }, + "id": "G101", + "name": "Use of Hard-coded Credentials", + "properties": { + "precision": "low", + "tags": [ + "security", + "HIGH" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "93d834a1-2cc5-38db-837f-66dfc7d711cc", + "id": "798", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Potential hardcoded credentials" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "fullDescription": { + "text": "Errors unhandled." + }, + "help": { + "text": "Errors unhandled.\nSeverity: LOW\nConfidence: HIGH\n" + }, + "id": "G104", + "name": "Improper Check or Handling of Exceptional Conditions", + "properties": { + "precision": "high", + "tags": [ + "security", + "LOW" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "7df38d1d-038e-3ced-8601-8d9265b90a25", + "id": "703", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Errors unhandled." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Potential HTTP request made with variable url" + }, + "help": { + "text": "Potential HTTP request made with variable url\nSeverity: MEDIUM\nConfidence: MEDIUM\n" + }, + "id": "G107", + "name": "Improper Neutralization of Argument Delimiters in a Command ('Argument Injection')", + "properties": { + "precision": "medium", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "d684c7e2-3856-3079-900b-f59c57ace34b", + "id": "88", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Potential HTTP request made with variable url" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Potential Integer overflow made by strconv.Atoi result conversion to int16/32" + }, + "help": { + "text": "Potential Integer overflow made by strconv.Atoi result conversion to int16/32\nSeverity: HIGH\nConfidence: MEDIUM\n" + }, + "id": "G109", + "name": "Integer Overflow or Wraparound", + "properties": { + "precision": "medium", + "tags": [ + "security", + "HIGH" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "c71e4fa0-720e-3e82-8b67-b2d44d0c604b", + "id": "190", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Potential Integer overflow made by strconv.Atoi result conversion to int16/32" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Potential DoS vulnerability via decompression bomb" + }, + "help": { + "text": "Potential DoS vulnerability via decompression bomb\nSeverity: MEDIUM\nConfidence: MEDIUM\n" + }, + "id": "G110", + "name": "Improper Handling of Highly Compressed Data (Data Amplification)", + "properties": { + "precision": "medium", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "8f97f42f-c62a-3d38-b26d-97951029c895", + "id": "409", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Potential DoS vulnerability via decompression bomb" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Use of net/http serve function that has no support for setting timeouts" + }, + "help": { + "text": "Use of net/http serve function that has no support for setting timeouts\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G114", + "name": "Use of Potentially Dangerous Function", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "f97fef5f-b85b-3d63-9932-7053f298803d", + "id": "676", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Use of net/http serve function that has no support for setting timeouts" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "SQL string formatting" + }, + "help": { + "text": "SQL string formatting\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G201", + "name": "Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "6bd55435-166c-3594-bc06-5e0dea916067", + "id": "89", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "SQL string formatting" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Potential file inclusion via variable" + }, + "help": { + "text": "Potential file inclusion via variable\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G304", + "name": "Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "3e718404-88bc-3f17-883e-e85e74078a76", + "id": "22", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Potential file inclusion via variable" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Deferring unsafe method \"Close\" on type \"io.ReadCloser\"" + }, + "help": { + "text": "Deferring unsafe method \"Close\" on type \"io.ReadCloser\"\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G307", + "name": "Improper Check or Handling of Exceptional Conditions", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "7df38d1d-038e-3ced-8601-8d9265b90a25", + "id": "703", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Deferring unsafe method \"Close\" on type \"io.ReadCloser\"" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Use of weak cryptographic primitive" + }, + "help": { + "text": "Use of weak cryptographic primitive\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G401", + "name": "Inadequate Encryption Strength", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "fe6ccccf-c3a1-354b-b67c-6c76007360e6", + "id": "326", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Use of weak cryptographic primitive" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "TLS MinVersion too low." + }, + "help": { + "text": "TLS MinVersion too low.\nSeverity: HIGH\nConfidence: HIGH\n" + }, + "id": "G402", + "name": "Improper Certificate Validation", + "properties": { + "precision": "high", + "tags": [ + "security", + "HIGH" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "09e885ea-951b-3143-801a-241b3aa9e6c9", + "id": "295", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "TLS MinVersion too low." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Use of weak random number generator (math/rand instead of crypto/rand)" + }, + "help": { + "text": "Use of weak random number generator (math/rand instead of crypto/rand)\nSeverity: HIGH\nConfidence: MEDIUM\n" + }, + "id": "G404", + "name": "Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)", + "properties": { + "precision": "medium", + "tags": [ + "security", + "HIGH" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "0512047f-75a2-3ac3-bb28-97df3a80efbe", + "id": "338", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Use of weak random number generator (math/rand instead of crypto/rand)" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Blocklisted import crypto/md5: weak cryptographic primitive" + }, + "help": { + "text": "Blocklisted import crypto/md5: weak cryptographic primitive\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G501", + "name": "Use of a Broken or Risky Cryptographic Algorithm", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "3d8ac75a-952a-30cd-ab4f-911c879d8d2b", + "id": "327", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Blocklisted import crypto/md5: weak cryptographic primitive" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Blocklisted import crypto/des: weak cryptographic primitive" + }, + "help": { + "text": "Blocklisted import crypto/des: weak cryptographic primitive\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G502", + "name": "Use of a Broken or Risky Cryptographic Algorithm", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "3d8ac75a-952a-30cd-ab4f-911c879d8d2b", + "id": "327", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Blocklisted import crypto/des: weak cryptographic primitive" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "fullDescription": { + "text": "Blocklisted import crypto/rc4: weak cryptographic primitive" + }, + "help": { + "text": "Blocklisted import crypto/rc4: weak cryptographic primitive\nSeverity: MEDIUM\nConfidence: HIGH\n" + }, + "id": "G503", + "name": "Use of a Broken or Risky Cryptographic Algorithm", + "properties": { + "precision": "high", + "tags": [ + "security", + "MEDIUM" + ] + }, + "relationships": [ + { + "kinds": [ + "superset" + ], + "target": { + "guid": "3d8ac75a-952a-30cd-ab4f-911c879d8d2b", + "id": "327", + "toolComponent": { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + } + } + ], + "shortDescription": { + "text": "Blocklisted import crypto/rc4: weak cryptographic primitive" + } + } + ], + "semanticVersion": "dev", + "supportedTaxonomies": [ + { + "guid": "f2856fc0-85b7-373f-83e7-6f8582243547", + "name": "CWE" + } + ], + "version": "dev" + } + } + } + ], + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "version": "2.1.0" +} \ No newline at end of file diff --git a/sarif/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/sarif/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md new file mode 100644 index 0000000..c758234 --- /dev/null +++ b/sarif/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md @@ -0,0 +1,96 @@ +## 1.5.0 + +* New option `IgnoreUntaggedFields` to ignore decoding to any fields + without `mapstructure` (or the configured tag name) set [GH-277] +* New option `ErrorUnset` which makes it an error if any fields + in a target struct are not set by the decoding process. [GH-225] +* New function `OrComposeDecodeHookFunc` to help compose decode hooks. [GH-240] +* Decoding to slice from array no longer crashes [GH-265] +* Decode nested struct pointers to map [GH-271] +* Fix issue where `,squash` was ignored if `Squash` option was set. [GH-280] +* Fix issue where fields with `,omitempty` would sometimes decode + into a map with an empty string key [GH-281] + +## 1.4.3 + +* Fix cases where `json.Number` didn't decode properly [GH-261] + +## 1.4.2 + +* Custom name matchers to support any sort of casing, formatting, etc. for + field names. [GH-250] +* Fix possible panic in ComposeDecodeHookFunc [GH-251] + +## 1.4.1 + +* Fix regression where `*time.Time` value would be set to empty and not be sent + to decode hooks properly [GH-232] + +## 1.4.0 + +* A new decode hook type `DecodeHookFuncValue` has been added that has + access to the full values. [GH-183] +* Squash is now supported with embedded fields that are struct pointers [GH-205] +* Empty strings will convert to 0 for all numeric types when weakly decoding [GH-206] + +## 1.3.3 + +* Decoding maps from maps creates a settable value for decode hooks [GH-203] + +## 1.3.2 + +* Decode into interface type with a struct value is supported [GH-187] + +## 1.3.1 + +* Squash should only squash embedded structs. [GH-194] + +## 1.3.0 + +* Added `",omitempty"` support. This will ignore zero values in the source + structure when encoding. [GH-145] + +## 1.2.3 + +* Fix duplicate entries in Keys list with pointer values. [GH-185] + +## 1.2.2 + +* Do not add unsettable (unexported) values to the unused metadata key + or "remain" value. [GH-150] + +## 1.2.1 + +* Go modules checksum mismatch fix + +## 1.2.0 + +* Added support to capture unused values in a field using the `",remain"` value + in the mapstructure tag. There is an example to showcase usage. +* Added `DecoderConfig` option to always squash embedded structs +* `json.Number` can decode into `uint` types +* Empty slices are preserved and not replaced with nil slices +* Fix panic that can occur in when decoding a map into a nil slice of structs +* Improved package documentation for godoc + +## 1.1.2 + +* Fix error when decode hook decodes interface implementation into interface + type. [GH-140] + +## 1.1.1 + +* Fix panic that can happen in `decodePtr` + +## 1.1.0 + +* Added `StringToIPHookFunc` to convert `string` to `net.IP` and `net.IPNet` [GH-133] +* Support struct to struct decoding [GH-137] +* If source map value is nil, then destination map value is nil (instead of empty) +* If source slice value is nil, then destination slice value is nil (instead of empty) +* If source pointer is nil, then destination pointer is set to nil (instead of + allocated zero value of type) + +## 1.0.0 + +* Initial tagged stable release. diff --git a/sarif/vendor/github.com/mitchellh/mapstructure/LICENSE b/sarif/vendor/github.com/mitchellh/mapstructure/LICENSE new file mode 100644 index 0000000..f9c841a --- /dev/null +++ b/sarif/vendor/github.com/mitchellh/mapstructure/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +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: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO 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. diff --git a/sarif/vendor/github.com/mitchellh/mapstructure/README.md b/sarif/vendor/github.com/mitchellh/mapstructure/README.md new file mode 100644 index 0000000..0018dc7 --- /dev/null +++ b/sarif/vendor/github.com/mitchellh/mapstructure/README.md @@ -0,0 +1,46 @@ +# mapstructure [![Godoc](https://godoc.org/github.com/mitchellh/mapstructure?status.svg)](https://godoc.org/github.com/mitchellh/mapstructure) + +mapstructure is a Go library for decoding generic map values to structures +and vice versa, while providing helpful error handling. + +This library is most useful when decoding values from some data stream (JSON, +Gob, etc.) where you don't _quite_ know the structure of the underlying data +until you read a part of it. You can therefore read a `map[string]interface{}` +and use this library to decode it into the proper underlying native Go +structure. + +## Installation + +Standard `go get`: + +``` +$ go get github.com/mitchellh/mapstructure +``` + +## Usage & Example + +For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/mapstructure). + +The `Decode` function has examples associated with it there. + +## But Why?! + +Go offers fantastic standard libraries for decoding formats such as JSON. +The standard method is to have a struct pre-created, and populate that struct +from the bytes of the encoded format. This is great, but the problem is if +you have configuration or an encoding that changes slightly depending on +specific fields. For example, consider this JSON: + +```json +{ + "type": "person", + "name": "Mitchell" +} +``` + +Perhaps we can't populate a specific structure without first reading +the "type" field from the JSON. We could always do two passes over the +decoding of the JSON (reading the "type" first, and the rest later). +However, it is much simpler to just decode this into a `map[string]interface{}` +structure, read the "type" key, then use something like this library +to decode it into the proper structure. diff --git a/sarif/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/sarif/vendor/github.com/mitchellh/mapstructure/decode_hooks.go new file mode 100644 index 0000000..3a754ca --- /dev/null +++ b/sarif/vendor/github.com/mitchellh/mapstructure/decode_hooks.go @@ -0,0 +1,279 @@ +package mapstructure + +import ( + "encoding" + "errors" + "fmt" + "net" + "reflect" + "strconv" + "strings" + "time" +) + +// typedDecodeHook takes a raw DecodeHookFunc (an interface{}) and turns +// it into the proper DecodeHookFunc type, such as DecodeHookFuncType. +func typedDecodeHook(h DecodeHookFunc) DecodeHookFunc { + // Create variables here so we can reference them with the reflect pkg + var f1 DecodeHookFuncType + var f2 DecodeHookFuncKind + var f3 DecodeHookFuncValue + + // Fill in the variables into this interface and the rest is done + // automatically using the reflect package. + potential := []interface{}{f1, f2, f3} + + v := reflect.ValueOf(h) + vt := v.Type() + for _, raw := range potential { + pt := reflect.ValueOf(raw).Type() + if vt.ConvertibleTo(pt) { + return v.Convert(pt).Interface() + } + } + + return nil +} + +// DecodeHookExec executes the given decode hook. This should be used +// since it'll naturally degrade to the older backwards compatible DecodeHookFunc +// that took reflect.Kind instead of reflect.Type. +func DecodeHookExec( + raw DecodeHookFunc, + from reflect.Value, to reflect.Value) (interface{}, error) { + + switch f := typedDecodeHook(raw).(type) { + case DecodeHookFuncType: + return f(from.Type(), to.Type(), from.Interface()) + case DecodeHookFuncKind: + return f(from.Kind(), to.Kind(), from.Interface()) + case DecodeHookFuncValue: + return f(from, to) + default: + return nil, errors.New("invalid decode hook signature") + } +} + +// ComposeDecodeHookFunc creates a single DecodeHookFunc that +// automatically composes multiple DecodeHookFuncs. +// +// The composed funcs are called in order, with the result of the +// previous transformation. +func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + var err error + data := f.Interface() + + newFrom := f + for _, f1 := range fs { + data, err = DecodeHookExec(f1, newFrom, t) + if err != nil { + return nil, err + } + newFrom = reflect.ValueOf(data) + } + + return data, nil + } +} + +// OrComposeDecodeHookFunc executes all input hook functions until one of them returns no error. In that case its value is returned. +// If all hooks return an error, OrComposeDecodeHookFunc returns an error concatenating all error messages. +func OrComposeDecodeHookFunc(ff ...DecodeHookFunc) DecodeHookFunc { + return func(a, b reflect.Value) (interface{}, error) { + var allErrs string + var out interface{} + var err error + + for _, f := range ff { + out, err = DecodeHookExec(f, a, b) + if err != nil { + allErrs += err.Error() + "\n" + continue + } + + return out, nil + } + + return nil, errors.New(allErrs) + } +} + +// StringToSliceHookFunc returns a DecodeHookFunc that converts +// string to []string by splitting on the given sep. +func StringToSliceHookFunc(sep string) DecodeHookFunc { + return func( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + if f != reflect.String || t != reflect.Slice { + return data, nil + } + + raw := data.(string) + if raw == "" { + return []string{}, nil + } + + return strings.Split(raw, sep), nil + } +} + +// StringToTimeDurationHookFunc returns a DecodeHookFunc that converts +// strings to time.Duration. +func StringToTimeDurationHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Duration(5)) { + return data, nil + } + + // Convert it by parsing + return time.ParseDuration(data.(string)) + } +} + +// StringToIPHookFunc returns a DecodeHookFunc that converts +// strings to net.IP +func StringToIPHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IP{}) { + return data, nil + } + + // Convert it by parsing + ip := net.ParseIP(data.(string)) + if ip == nil { + return net.IP{}, fmt.Errorf("failed parsing ip %v", data) + } + + return ip, nil + } +} + +// StringToIPNetHookFunc returns a DecodeHookFunc that converts +// strings to net.IPNet +func StringToIPNetHookFunc() DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(net.IPNet{}) { + return data, nil + } + + // Convert it by parsing + _, net, err := net.ParseCIDR(data.(string)) + return net, err + } +} + +// StringToTimeHookFunc returns a DecodeHookFunc that converts +// strings to time.Time. +func StringToTimeHookFunc(layout string) DecodeHookFunc { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + if t != reflect.TypeOf(time.Time{}) { + return data, nil + } + + // Convert it by parsing + return time.Parse(layout, data.(string)) + } +} + +// WeaklyTypedHook is a DecodeHookFunc which adds support for weak typing to +// the decoder. +// +// Note that this is significantly different from the WeaklyTypedInput option +// of the DecoderConfig. +func WeaklyTypedHook( + f reflect.Kind, + t reflect.Kind, + data interface{}) (interface{}, error) { + dataVal := reflect.ValueOf(data) + switch t { + case reflect.String: + switch f { + case reflect.Bool: + if dataVal.Bool() { + return "1", nil + } + return "0", nil + case reflect.Float32: + return strconv.FormatFloat(dataVal.Float(), 'f', -1, 64), nil + case reflect.Int: + return strconv.FormatInt(dataVal.Int(), 10), nil + case reflect.Slice: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + if elemKind == reflect.Uint8 { + return string(dataVal.Interface().([]uint8)), nil + } + case reflect.Uint: + return strconv.FormatUint(dataVal.Uint(), 10), nil + } + } + + return data, nil +} + +func RecursiveStructToMapHookFunc() DecodeHookFunc { + return func(f reflect.Value, t reflect.Value) (interface{}, error) { + if f.Kind() != reflect.Struct { + return f.Interface(), nil + } + + var i interface{} = struct{}{} + if t.Type() != reflect.TypeOf(&i).Elem() { + return f.Interface(), nil + } + + m := make(map[string]interface{}) + t.Set(reflect.ValueOf(m)) + + return f.Interface(), nil + } +} + +// TextUnmarshallerHookFunc returns a DecodeHookFunc that applies +// strings to the UnmarshalText function, when the target type +// implements the encoding.TextUnmarshaler interface +func TextUnmarshallerHookFunc() DecodeHookFuncType { + return func( + f reflect.Type, + t reflect.Type, + data interface{}) (interface{}, error) { + if f.Kind() != reflect.String { + return data, nil + } + result := reflect.New(t).Interface() + unmarshaller, ok := result.(encoding.TextUnmarshaler) + if !ok { + return data, nil + } + if err := unmarshaller.UnmarshalText([]byte(data.(string))); err != nil { + return nil, err + } + return result, nil + } +} diff --git a/sarif/vendor/github.com/mitchellh/mapstructure/error.go b/sarif/vendor/github.com/mitchellh/mapstructure/error.go new file mode 100644 index 0000000..47a99e5 --- /dev/null +++ b/sarif/vendor/github.com/mitchellh/mapstructure/error.go @@ -0,0 +1,50 @@ +package mapstructure + +import ( + "errors" + "fmt" + "sort" + "strings" +) + +// Error implements the error interface and can represents multiple +// errors that occur in the course of a single decode. +type Error struct { + Errors []string +} + +func (e *Error) Error() string { + points := make([]string, len(e.Errors)) + for i, err := range e.Errors { + points[i] = fmt.Sprintf("* %s", err) + } + + sort.Strings(points) + return fmt.Sprintf( + "%d error(s) decoding:\n\n%s", + len(e.Errors), strings.Join(points, "\n")) +} + +// WrappedErrors implements the errwrap.Wrapper interface to make this +// return value more useful with the errwrap and go-multierror libraries. +func (e *Error) WrappedErrors() []error { + if e == nil { + return nil + } + + result := make([]error, len(e.Errors)) + for i, e := range e.Errors { + result[i] = errors.New(e) + } + + return result +} + +func appendErrors(errors []string, err error) []string { + switch e := err.(type) { + case *Error: + return append(errors, e.Errors...) + default: + return append(errors, e.Error()) + } +} diff --git a/sarif/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/sarif/vendor/github.com/mitchellh/mapstructure/mapstructure.go new file mode 100644 index 0000000..1efb22a --- /dev/null +++ b/sarif/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -0,0 +1,1540 @@ +// Package mapstructure exposes functionality to convert one arbitrary +// Go type into another, typically to convert a map[string]interface{} +// into a native Go structure. +// +// The Go structure can be arbitrarily complex, containing slices, +// other structs, etc. and the decoder will properly decode nested +// maps and so on into the proper structures in the native Go struct. +// See the examples to see what the decoder is capable of. +// +// The simplest function to start with is Decode. +// +// Field Tags +// +// When decoding to a struct, mapstructure will use the field name by +// default to perform the mapping. For example, if a struct has a field +// "Username" then mapstructure will look for a key in the source value +// of "username" (case insensitive). +// +// type User struct { +// Username string +// } +// +// You can change the behavior of mapstructure by using struct tags. +// The default struct tag that mapstructure looks for is "mapstructure" +// but you can customize it using DecoderConfig. +// +// Renaming Fields +// +// To rename the key that mapstructure looks for, use the "mapstructure" +// tag and set a value directly. For example, to change the "username" example +// above to "user": +// +// type User struct { +// Username string `mapstructure:"user"` +// } +// +// Embedded Structs and Squashing +// +// Embedded structs are treated as if they're another field with that name. +// By default, the two structs below are equivalent when decoding with +// mapstructure: +// +// type Person struct { +// Name string +// } +// +// type Friend struct { +// Person +// } +// +// type Friend struct { +// Person Person +// } +// +// This would require an input that looks like below: +// +// map[string]interface{}{ +// "person": map[string]interface{}{"name": "alice"}, +// } +// +// If your "person" value is NOT nested, then you can append ",squash" to +// your tag value and mapstructure will treat it as if the embedded struct +// were part of the struct directly. Example: +// +// type Friend struct { +// Person `mapstructure:",squash"` +// } +// +// Now the following input would be accepted: +// +// map[string]interface{}{ +// "name": "alice", +// } +// +// When decoding from a struct to a map, the squash tag squashes the struct +// fields into a single map. Using the example structs from above: +// +// Friend{Person: Person{Name: "alice"}} +// +// Will be decoded into a map: +// +// map[string]interface{}{ +// "name": "alice", +// } +// +// DecoderConfig has a field that changes the behavior of mapstructure +// to always squash embedded structs. +// +// Remainder Values +// +// If there are any unmapped keys in the source value, mapstructure by +// default will silently ignore them. You can error by setting ErrorUnused +// in DecoderConfig. If you're using Metadata you can also maintain a slice +// of the unused keys. +// +// You can also use the ",remain" suffix on your tag to collect all unused +// values in a map. The field with this tag MUST be a map type and should +// probably be a "map[string]interface{}" or "map[interface{}]interface{}". +// See example below: +// +// type Friend struct { +// Name string +// Other map[string]interface{} `mapstructure:",remain"` +// } +// +// Given the input below, Other would be populated with the other +// values that weren't used (everything but "name"): +// +// map[string]interface{}{ +// "name": "bob", +// "address": "123 Maple St.", +// } +// +// Omit Empty Values +// +// When decoding from a struct to any other value, you may use the +// ",omitempty" suffix on your tag to omit that value if it equates to +// the zero value. The zero value of all types is specified in the Go +// specification. +// +// For example, the zero type of a numeric type is zero ("0"). If the struct +// field value is zero and a numeric type, the field is empty, and it won't +// be encoded into the destination type. +// +// type Source struct { +// Age int `mapstructure:",omitempty"` +// } +// +// Unexported fields +// +// Since unexported (private) struct fields cannot be set outside the package +// where they are defined, the decoder will simply skip them. +// +// For this output type definition: +// +// type Exported struct { +// private string // this unexported field will be skipped +// Public string +// } +// +// Using this map as input: +// +// map[string]interface{}{ +// "private": "I will be ignored", +// "Public": "I made it through!", +// } +// +// The following struct will be decoded: +// +// type Exported struct { +// private: "" // field is left with an empty string (zero value) +// Public: "I made it through!" +// } +// +// Other Configuration +// +// mapstructure is highly configurable. See the DecoderConfig struct +// for other features and options that are supported. +package mapstructure + +import ( + "encoding/json" + "errors" + "fmt" + "reflect" + "sort" + "strconv" + "strings" +) + +// DecodeHookFunc is the callback function that can be used for +// data transformations. See "DecodeHook" in the DecoderConfig +// struct. +// +// The type must be one of DecodeHookFuncType, DecodeHookFuncKind, or +// DecodeHookFuncValue. +// Values are a superset of Types (Values can return types), and Types are a +// superset of Kinds (Types can return Kinds) and are generally a richer thing +// to use, but Kinds are simpler if you only need those. +// +// The reason DecodeHookFunc is multi-typed is for backwards compatibility: +// we started with Kinds and then realized Types were the better solution, +// but have a promise to not break backwards compat so we now support +// both. +type DecodeHookFunc interface{} + +// DecodeHookFuncType is a DecodeHookFunc which has complete information about +// the source and target types. +type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface{}, error) + +// DecodeHookFuncKind is a DecodeHookFunc which knows only the Kinds of the +// source and target types. +type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) + +// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target +// values. +type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) + +// DecoderConfig is the configuration that is used to create a new decoder +// and allows customization of various aspects of decoding. +type DecoderConfig struct { + // DecodeHook, if set, will be called before any decoding and any + // type conversion (if WeaklyTypedInput is on). This lets you modify + // the values before they're set down onto the resulting struct. The + // DecodeHook is called for every map and value in the input. This means + // that if a struct has embedded fields with squash tags the decode hook + // is called only once with all of the input data, not once for each + // embedded struct. + // + // If an error is returned, the entire decode will fail with that error. + DecodeHook DecodeHookFunc + + // If ErrorUnused is true, then it is an error for there to exist + // keys in the original map that were unused in the decoding process + // (extra keys). + ErrorUnused bool + + // If ErrorUnset is true, then it is an error for there to exist + // fields in the result that were not set in the decoding process + // (extra fields). This only applies to decoding to a struct. This + // will affect all nested structs as well. + ErrorUnset bool + + // ZeroFields, if set to true, will zero fields before writing them. + // For example, a map will be emptied before decoded values are put in + // it. If this is false, a map will be merged. + ZeroFields bool + + // If WeaklyTypedInput is true, the decoder will make the following + // "weak" conversions: + // + // - bools to string (true = "1", false = "0") + // - numbers to string (base 10) + // - bools to int/uint (true = 1, false = 0) + // - strings to int/uint (base implied by prefix) + // - int to bool (true if value != 0) + // - string to bool (accepts: 1, t, T, TRUE, true, True, 0, f, F, + // FALSE, false, False. Anything else is an error) + // - empty array = empty map and vice versa + // - negative numbers to overflowed uint values (base 10) + // - slice of maps to a merged map + // - single values are converted to slices if required. Each + // element is weakly decoded. For example: "4" can become []int{4} + // if the target type is an int slice. + // + WeaklyTypedInput bool + + // Squash will squash embedded structs. A squash tag may also be + // added to an individual struct field using a tag. For example: + // + // type Parent struct { + // Child `mapstructure:",squash"` + // } + Squash bool + + // Metadata is the struct that will contain extra metadata about + // the decoding. If this is nil, then no metadata will be tracked. + Metadata *Metadata + + // Result is a pointer to the struct that will contain the decoded + // value. + Result interface{} + + // The tag name that mapstructure reads for field names. This + // defaults to "mapstructure" + TagName string + + // IgnoreUntaggedFields ignores all struct fields without explicit + // TagName, comparable to `mapstructure:"-"` as default behaviour. + IgnoreUntaggedFields bool + + // MatchName is the function used to match the map key to the struct + // field name or tag. Defaults to `strings.EqualFold`. This can be used + // to implement case-sensitive tag values, support snake casing, etc. + MatchName func(mapKey, fieldName string) bool +} + +// A Decoder takes a raw interface value and turns it into structured +// data, keeping track of rich error information along the way in case +// anything goes wrong. Unlike the basic top-level Decode method, you can +// more finely control how the Decoder behaves using the DecoderConfig +// structure. The top-level Decode method is just a convenience that sets +// up the most basic Decoder. +type Decoder struct { + config *DecoderConfig +} + +// Metadata contains information about decoding a structure that +// is tedious or difficult to get otherwise. +type Metadata struct { + // Keys are the keys of the structure which were successfully decoded + Keys []string + + // Unused is a slice of keys that were found in the raw value but + // weren't decoded since there was no matching field in the result interface + Unused []string + + // Unset is a slice of field names that were found in the result interface + // but weren't set in the decoding process since there was no matching value + // in the input + Unset []string +} + +// Decode takes an input structure and uses reflection to translate it to +// the output structure. output must be a pointer to a map or struct. +func Decode(input interface{}, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecode is the same as Decode but is shorthand to enable +// WeaklyTypedInput. See DecoderConfig for more info. +func WeakDecode(input, output interface{}) error { + config := &DecoderConfig{ + Metadata: nil, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// DecodeMetadata is the same as Decode, but is shorthand to +// enable metadata collection. See DecoderConfig for more info. +func DecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// WeakDecodeMetadata is the same as Decode, but is shorthand to +// enable both WeaklyTypedInput and metadata collection. See +// DecoderConfig for more info. +func WeakDecodeMetadata(input interface{}, output interface{}, metadata *Metadata) error { + config := &DecoderConfig{ + Metadata: metadata, + Result: output, + WeaklyTypedInput: true, + } + + decoder, err := NewDecoder(config) + if err != nil { + return err + } + + return decoder.Decode(input) +} + +// NewDecoder returns a new decoder for the given configuration. Once +// a decoder has been returned, the same configuration must not be used +// again. +func NewDecoder(config *DecoderConfig) (*Decoder, error) { + val := reflect.ValueOf(config.Result) + if val.Kind() != reflect.Ptr { + return nil, errors.New("result must be a pointer") + } + + val = val.Elem() + if !val.CanAddr() { + return nil, errors.New("result must be addressable (a pointer)") + } + + if config.Metadata != nil { + if config.Metadata.Keys == nil { + config.Metadata.Keys = make([]string, 0) + } + + if config.Metadata.Unused == nil { + config.Metadata.Unused = make([]string, 0) + } + + if config.Metadata.Unset == nil { + config.Metadata.Unset = make([]string, 0) + } + } + + if config.TagName == "" { + config.TagName = "mapstructure" + } + + if config.MatchName == nil { + config.MatchName = strings.EqualFold + } + + result := &Decoder{ + config: config, + } + + return result, nil +} + +// Decode decodes the given raw interface to the target pointer specified +// by the configuration. +func (d *Decoder) Decode(input interface{}) error { + return d.decode("", input, reflect.ValueOf(d.config.Result).Elem()) +} + +// Decodes an unknown data type into a specific reflection value. +func (d *Decoder) decode(name string, input interface{}, outVal reflect.Value) error { + var inputVal reflect.Value + if input != nil { + inputVal = reflect.ValueOf(input) + + // We need to check here if input is a typed nil. Typed nils won't + // match the "input == nil" below so we check that here. + if inputVal.Kind() == reflect.Ptr && inputVal.IsNil() { + input = nil + } + } + + if input == nil { + // If the data is nil, then we don't set anything, unless ZeroFields is set + // to true. + if d.config.ZeroFields { + outVal.Set(reflect.Zero(outVal.Type())) + + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + } + return nil + } + + if !inputVal.IsValid() { + // If the input value is invalid, then we just set the value + // to be the zero value. + outVal.Set(reflect.Zero(outVal.Type())) + if d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + return nil + } + + if d.config.DecodeHook != nil { + // We have a DecodeHook, so let's pre-process the input. + var err error + input, err = DecodeHookExec(d.config.DecodeHook, inputVal, outVal) + if err != nil { + return fmt.Errorf("error decoding '%s': %s", name, err) + } + } + + var err error + outputKind := getKind(outVal) + addMetaKey := true + switch outputKind { + case reflect.Bool: + err = d.decodeBool(name, input, outVal) + case reflect.Interface: + err = d.decodeBasic(name, input, outVal) + case reflect.String: + err = d.decodeString(name, input, outVal) + case reflect.Int: + err = d.decodeInt(name, input, outVal) + case reflect.Uint: + err = d.decodeUint(name, input, outVal) + case reflect.Float32: + err = d.decodeFloat(name, input, outVal) + case reflect.Struct: + err = d.decodeStruct(name, input, outVal) + case reflect.Map: + err = d.decodeMap(name, input, outVal) + case reflect.Ptr: + addMetaKey, err = d.decodePtr(name, input, outVal) + case reflect.Slice: + err = d.decodeSlice(name, input, outVal) + case reflect.Array: + err = d.decodeArray(name, input, outVal) + case reflect.Func: + err = d.decodeFunc(name, input, outVal) + default: + // If we reached this point then we weren't able to decode it + return fmt.Errorf("%s: unsupported type: %s", name, outputKind) + } + + // If we reached here, then we successfully decoded SOMETHING, so + // mark the key as used if we're tracking metainput. + if addMetaKey && d.config.Metadata != nil && name != "" { + d.config.Metadata.Keys = append(d.config.Metadata.Keys, name) + } + + return err +} + +// This decodes a basic type (bool, int, string, etc.) and sets the +// value to "data" of that type. +func (d *Decoder) decodeBasic(name string, data interface{}, val reflect.Value) error { + if val.IsValid() && val.Elem().IsValid() { + elem := val.Elem() + + // If we can't address this element, then its not writable. Instead, + // we make a copy of the value (which is a pointer and therefore + // writable), decode into that, and replace the whole value. + copied := false + if !elem.CanAddr() { + copied = true + + // Make *T + copy := reflect.New(elem.Type()) + + // *T = elem + copy.Elem().Set(elem) + + // Set elem so we decode into it + elem = copy + } + + // Decode. If we have an error then return. We also return right + // away if we're not a copy because that means we decoded directly. + if err := d.decode(name, data, elem); err != nil || !copied { + return err + } + + // If we're a copy, we need to set te final result + val.Set(elem.Elem()) + return nil + } + + dataVal := reflect.ValueOf(data) + + // If the input data is a pointer, and the assigned type is the dereference + // of that exact pointer, then indirect it so that we can assign it. + // Example: *string to string + if dataVal.Kind() == reflect.Ptr && dataVal.Type().Elem() == val.Type() { + dataVal = reflect.Indirect(dataVal) + } + + if !dataVal.IsValid() { + dataVal = reflect.Zero(val.Type()) + } + + dataValType := dataVal.Type() + if !dataValType.AssignableTo(val.Type()) { + return fmt.Errorf( + "'%s' expected type '%s', got '%s'", + name, val.Type(), dataValType) + } + + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeString(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + converted := true + switch { + case dataKind == reflect.String: + val.SetString(dataVal.String()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetString("1") + } else { + val.SetString("0") + } + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatInt(dataVal.Int(), 10)) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatUint(dataVal.Uint(), 10)) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetString(strconv.FormatFloat(dataVal.Float(), 'f', -1, 64)) + case dataKind == reflect.Slice && d.config.WeaklyTypedInput, + dataKind == reflect.Array && d.config.WeaklyTypedInput: + dataType := dataVal.Type() + elemKind := dataType.Elem().Kind() + switch elemKind { + case reflect.Uint8: + var uints []uint8 + if dataKind == reflect.Array { + uints = make([]uint8, dataVal.Len(), dataVal.Len()) + for i := range uints { + uints[i] = dataVal.Index(i).Interface().(uint8) + } + } else { + uints = dataVal.Interface().([]uint8) + } + val.SetString(string(uints)) + default: + converted = false + } + default: + converted = false + } + + if !converted { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeInt(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetInt(dataVal.Int()) + case dataKind == reflect.Uint: + val.SetInt(int64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetInt(int64(dataVal.Float())) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetInt(1) + } else { + val.SetInt(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseInt(str, 0, val.Type().Bits()) + if err == nil { + val.SetInt(i) + } else { + return fmt.Errorf("cannot parse '%s' as int: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Int64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetInt(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeUint(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + i := dataVal.Int() + if i < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %d overflows uint", + name, i) + } + val.SetUint(uint64(i)) + case dataKind == reflect.Uint: + val.SetUint(dataVal.Uint()) + case dataKind == reflect.Float32: + f := dataVal.Float() + if f < 0 && !d.config.WeaklyTypedInput { + return fmt.Errorf("cannot parse '%s', %f overflows uint", + name, f) + } + val.SetUint(uint64(f)) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetUint(1) + } else { + val.SetUint(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + i, err := strconv.ParseUint(str, 0, val.Type().Bits()) + if err == nil { + val.SetUint(i) + } else { + return fmt.Errorf("cannot parse '%s' as uint: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := strconv.ParseUint(string(jn), 0, 64) + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetUint(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeBool(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + + switch { + case dataKind == reflect.Bool: + val.SetBool(dataVal.Bool()) + case dataKind == reflect.Int && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Int() != 0) + case dataKind == reflect.Uint && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Uint() != 0) + case dataKind == reflect.Float32 && d.config.WeaklyTypedInput: + val.SetBool(dataVal.Float() != 0) + case dataKind == reflect.String && d.config.WeaklyTypedInput: + b, err := strconv.ParseBool(dataVal.String()) + if err == nil { + val.SetBool(b) + } else if dataVal.String() == "" { + val.SetBool(false) + } else { + return fmt.Errorf("cannot parse '%s' as bool: %s", name, err) + } + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeFloat(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataKind := getKind(dataVal) + dataType := dataVal.Type() + + switch { + case dataKind == reflect.Int: + val.SetFloat(float64(dataVal.Int())) + case dataKind == reflect.Uint: + val.SetFloat(float64(dataVal.Uint())) + case dataKind == reflect.Float32: + val.SetFloat(dataVal.Float()) + case dataKind == reflect.Bool && d.config.WeaklyTypedInput: + if dataVal.Bool() { + val.SetFloat(1) + } else { + val.SetFloat(0) + } + case dataKind == reflect.String && d.config.WeaklyTypedInput: + str := dataVal.String() + if str == "" { + str = "0" + } + + f, err := strconv.ParseFloat(str, val.Type().Bits()) + if err == nil { + val.SetFloat(f) + } else { + return fmt.Errorf("cannot parse '%s' as float: %s", name, err) + } + case dataType.PkgPath() == "encoding/json" && dataType.Name() == "Number": + jn := data.(json.Number) + i, err := jn.Float64() + if err != nil { + return fmt.Errorf( + "error decoding json.Number into %s: %s", name, err) + } + val.SetFloat(i) + default: + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + + return nil +} + +func (d *Decoder) decodeMap(name string, data interface{}, val reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // By default we overwrite keys in the current map + valMap := val + + // If the map is nil or we're purposely zeroing fields, make a new map + if valMap.IsNil() || d.config.ZeroFields { + // Make a new map to hold our result + mapType := reflect.MapOf(valKeyType, valElemType) + valMap = reflect.MakeMap(mapType) + } + + // Check input type and based on the input type jump to the proper func + dataVal := reflect.Indirect(reflect.ValueOf(data)) + switch dataVal.Kind() { + case reflect.Map: + return d.decodeMapFromMap(name, dataVal, val, valMap) + + case reflect.Struct: + return d.decodeMapFromStruct(name, dataVal, val, valMap) + + case reflect.Array, reflect.Slice: + if d.config.WeaklyTypedInput { + return d.decodeMapFromSlice(name, dataVal, val, valMap) + } + + fallthrough + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeMapFromSlice(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + // Special case for BC reasons (covered by tests) + if dataVal.Len() == 0 { + val.Set(valMap) + return nil + } + + for i := 0; i < dataVal.Len(); i++ { + err := d.decode( + name+"["+strconv.Itoa(i)+"]", + dataVal.Index(i).Interface(), val) + if err != nil { + return err + } + } + + return nil +} + +func (d *Decoder) decodeMapFromMap(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + valType := val.Type() + valKeyType := valType.Key() + valElemType := valType.Elem() + + // Accumulate errors + errors := make([]string, 0) + + // If the input data is empty, then we just match what the input data is. + if dataVal.Len() == 0 { + if dataVal.IsNil() { + if !val.IsNil() { + val.Set(dataVal) + } + } else { + // Set to empty allocated value + val.Set(valMap) + } + + return nil + } + + for _, k := range dataVal.MapKeys() { + fieldName := name + "[" + k.String() + "]" + + // First decode the key into the proper type + currentKey := reflect.Indirect(reflect.New(valKeyType)) + if err := d.decode(fieldName, k.Interface(), currentKey); err != nil { + errors = appendErrors(errors, err) + continue + } + + // Next decode the data into the proper type + v := dataVal.MapIndex(k).Interface() + currentVal := reflect.Indirect(reflect.New(valElemType)) + if err := d.decode(fieldName, v, currentVal); err != nil { + errors = appendErrors(errors, err) + continue + } + + valMap.SetMapIndex(currentKey, currentVal) + } + + // Set the built up map to the value + val.Set(valMap) + + // If we had errors, return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeMapFromStruct(name string, dataVal reflect.Value, val reflect.Value, valMap reflect.Value) error { + typ := dataVal.Type() + for i := 0; i < typ.NumField(); i++ { + // Get the StructField first since this is a cheap operation. If the + // field is unexported, then ignore it. + f := typ.Field(i) + if f.PkgPath != "" { + continue + } + + // Next get the actual value of this field and verify it is assignable + // to the map value. + v := dataVal.Field(i) + if !v.Type().AssignableTo(valMap.Type().Elem()) { + return fmt.Errorf("cannot assign type '%s' to map value field of type '%s'", v.Type(), valMap.Type().Elem()) + } + + tagValue := f.Tag.Get(d.config.TagName) + keyName := f.Name + + if tagValue == "" && d.config.IgnoreUntaggedFields { + continue + } + + // If Squash is set in the config, we squash the field down. + squash := d.config.Squash && v.Kind() == reflect.Struct && f.Anonymous + + v = dereferencePtrToStructIfNeeded(v, d.config.TagName) + + // Determine the name of the key in the map + if index := strings.Index(tagValue, ","); index != -1 { + if tagValue[:index] == "-" { + continue + } + // If "omitempty" is specified in the tag, it ignores empty values. + if strings.Index(tagValue[index+1:], "omitempty") != -1 && isEmptyValue(v) { + continue + } + + // If "squash" is specified in the tag, we squash the field down. + squash = squash || strings.Index(tagValue[index+1:], "squash") != -1 + if squash { + // When squashing, the embedded type can be a pointer to a struct. + if v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct { + v = v.Elem() + } + + // The final type must be a struct + if v.Kind() != reflect.Struct { + return fmt.Errorf("cannot squash non-struct type '%s'", v.Type()) + } + } + if keyNameTagValue := tagValue[:index]; keyNameTagValue != "" { + keyName = keyNameTagValue + } + } else if len(tagValue) > 0 { + if tagValue == "-" { + continue + } + keyName = tagValue + } + + switch v.Kind() { + // this is an embedded struct, so handle it differently + case reflect.Struct: + x := reflect.New(v.Type()) + x.Elem().Set(v) + + vType := valMap.Type() + vKeyType := vType.Key() + vElemType := vType.Elem() + mType := reflect.MapOf(vKeyType, vElemType) + vMap := reflect.MakeMap(mType) + + // Creating a pointer to a map so that other methods can completely + // overwrite the map if need be (looking at you decodeMapFromMap). The + // indirection allows the underlying map to be settable (CanSet() == true) + // where as reflect.MakeMap returns an unsettable map. + addrVal := reflect.New(vMap.Type()) + reflect.Indirect(addrVal).Set(vMap) + + err := d.decode(keyName, x.Interface(), reflect.Indirect(addrVal)) + if err != nil { + return err + } + + // the underlying map may have been completely overwritten so pull + // it indirectly out of the enclosing value. + vMap = reflect.Indirect(addrVal) + + if squash { + for _, k := range vMap.MapKeys() { + valMap.SetMapIndex(k, vMap.MapIndex(k)) + } + } else { + valMap.SetMapIndex(reflect.ValueOf(keyName), vMap) + } + + default: + valMap.SetMapIndex(reflect.ValueOf(keyName), v) + } + } + + if val.CanAddr() { + val.Set(valMap) + } + + return nil +} + +func (d *Decoder) decodePtr(name string, data interface{}, val reflect.Value) (bool, error) { + // If the input data is nil, then we want to just set the output + // pointer to be nil as well. + isNil := data == nil + if !isNil { + switch v := reflect.Indirect(reflect.ValueOf(data)); v.Kind() { + case reflect.Chan, + reflect.Func, + reflect.Interface, + reflect.Map, + reflect.Ptr, + reflect.Slice: + isNil = v.IsNil() + } + } + if isNil { + if !val.IsNil() && val.CanSet() { + nilValue := reflect.New(val.Type()).Elem() + val.Set(nilValue) + } + + return true, nil + } + + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + valType := val.Type() + valElemType := valType.Elem() + if val.CanSet() { + realVal := val + if realVal.IsNil() || d.config.ZeroFields { + realVal = reflect.New(valElemType) + } + + if err := d.decode(name, data, reflect.Indirect(realVal)); err != nil { + return false, err + } + + val.Set(realVal) + } else { + if err := d.decode(name, data, reflect.Indirect(val)); err != nil { + return false, err + } + } + return false, nil +} + +func (d *Decoder) decodeFunc(name string, data interface{}, val reflect.Value) error { + // Create an element of the concrete (non pointer) type and decode + // into that. Then set the value of the pointer to this type. + dataVal := reflect.Indirect(reflect.ValueOf(data)) + if val.Type() != dataVal.Type() { + return fmt.Errorf( + "'%s' expected type '%s', got unconvertible type '%s', value: '%v'", + name, val.Type(), dataVal.Type(), data) + } + val.Set(dataVal) + return nil +} + +func (d *Decoder) decodeSlice(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + sliceType := reflect.SliceOf(valElemType) + + // If we have a non array/slice type then we first attempt to convert. + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Slice and array we use the normal logic + case dataValKind == reflect.Slice, dataValKind == reflect.Array: + break + + // Empty maps turn into empty slices + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.MakeSlice(sliceType, 0, 0)) + return nil + } + // Create slice of maps of other sizes + return d.decodeSlice(name, []interface{}{data}, val) + + case dataValKind == reflect.String && valElemType.Kind() == reflect.Uint8: + return d.decodeSlice(name, []byte(dataVal.String()), val) + + // All other types we try to convert to the slice type + // and "lift" it into it. i.e. a string becomes a string slice. + default: + // Just re-try this function with data as a slice. + return d.decodeSlice(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + } + + // If the input value is nil, then don't allocate since empty != nil + if dataValKind != reflect.Array && dataVal.IsNil() { + return nil + } + + valSlice := val + if valSlice.IsNil() || d.config.ZeroFields { + // Make a new slice to hold our result, same size as the original data. + valSlice = reflect.MakeSlice(sliceType, dataVal.Len(), dataVal.Len()) + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + for valSlice.Len() <= i { + valSlice = reflect.Append(valSlice, reflect.Zero(valElemType)) + } + currentField := valSlice.Index(i) + + fieldName := name + "[" + strconv.Itoa(i) + "]" + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the slice we built up + val.Set(valSlice) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeArray(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + dataValKind := dataVal.Kind() + valType := val.Type() + valElemType := valType.Elem() + arrayType := reflect.ArrayOf(valType.Len(), valElemType) + + valArray := val + + if valArray.Interface() == reflect.Zero(valArray.Type()).Interface() || d.config.ZeroFields { + // Check input type + if dataValKind != reflect.Array && dataValKind != reflect.Slice { + if d.config.WeaklyTypedInput { + switch { + // Empty maps turn into empty arrays + case dataValKind == reflect.Map: + if dataVal.Len() == 0 { + val.Set(reflect.Zero(arrayType)) + return nil + } + + // All other types we try to convert to the array type + // and "lift" it into it. i.e. a string becomes a string array. + default: + // Just re-try this function with data as a slice. + return d.decodeArray(name, []interface{}{data}, val) + } + } + + return fmt.Errorf( + "'%s': source data must be an array or slice, got %s", name, dataValKind) + + } + if dataVal.Len() > arrayType.Len() { + return fmt.Errorf( + "'%s': expected source data to have length less or equal to %d, got %d", name, arrayType.Len(), dataVal.Len()) + + } + + // Make a new array to hold our result, same size as the original data. + valArray = reflect.New(arrayType).Elem() + } + + // Accumulate any errors + errors := make([]string, 0) + + for i := 0; i < dataVal.Len(); i++ { + currentData := dataVal.Index(i).Interface() + currentField := valArray.Index(i) + + fieldName := name + "[" + strconv.Itoa(i) + "]" + if err := d.decode(fieldName, currentData, currentField); err != nil { + errors = appendErrors(errors, err) + } + } + + // Finally, set the value to the array we built up + val.Set(valArray) + + // If there were errors, we return those + if len(errors) > 0 { + return &Error{errors} + } + + return nil +} + +func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { + dataVal := reflect.Indirect(reflect.ValueOf(data)) + + // If the type of the value to write to and the data match directly, + // then we just set it directly instead of recursing into the structure. + if dataVal.Type() == val.Type() { + val.Set(dataVal) + return nil + } + + dataValKind := dataVal.Kind() + switch dataValKind { + case reflect.Map: + return d.decodeStructFromMap(name, dataVal, val) + + case reflect.Struct: + // Not the most efficient way to do this but we can optimize later if + // we want to. To convert from struct to struct we go to map first + // as an intermediary. + + // Make a new map to hold our result + mapType := reflect.TypeOf((map[string]interface{})(nil)) + mval := reflect.MakeMap(mapType) + + // Creating a pointer to a map so that other methods can completely + // overwrite the map if need be (looking at you decodeMapFromMap). The + // indirection allows the underlying map to be settable (CanSet() == true) + // where as reflect.MakeMap returns an unsettable map. + addrVal := reflect.New(mval.Type()) + + reflect.Indirect(addrVal).Set(mval) + if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil { + return err + } + + result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val) + return result + + default: + return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) + } +} + +func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { + dataValType := dataVal.Type() + if kind := dataValType.Key().Kind(); kind != reflect.String && kind != reflect.Interface { + return fmt.Errorf( + "'%s' needs a map with string keys, has '%s' keys", + name, dataValType.Key().Kind()) + } + + dataValKeys := make(map[reflect.Value]struct{}) + dataValKeysUnused := make(map[interface{}]struct{}) + for _, dataValKey := range dataVal.MapKeys() { + dataValKeys[dataValKey] = struct{}{} + dataValKeysUnused[dataValKey.Interface()] = struct{}{} + } + + targetValKeysUnused := make(map[interface{}]struct{}) + errors := make([]string, 0) + + // This slice will keep track of all the structs we'll be decoding. + // There can be more than one struct if there are embedded structs + // that are squashed. + structs := make([]reflect.Value, 1, 5) + structs[0] = val + + // Compile the list of all the fields that we're going to be decoding + // from all the structs. + type field struct { + field reflect.StructField + val reflect.Value + } + + // remainField is set to a valid field set with the "remain" tag if + // we are keeping track of remaining values. + var remainField *field + + fields := []field{} + for len(structs) > 0 { + structVal := structs[0] + structs = structs[1:] + + structType := structVal.Type() + + for i := 0; i < structType.NumField(); i++ { + fieldType := structType.Field(i) + fieldVal := structVal.Field(i) + if fieldVal.Kind() == reflect.Ptr && fieldVal.Elem().Kind() == reflect.Struct { + // Handle embedded struct pointers as embedded structs. + fieldVal = fieldVal.Elem() + } + + // If "squash" is specified in the tag, we squash the field down. + squash := d.config.Squash && fieldVal.Kind() == reflect.Struct && fieldType.Anonymous + remain := false + + // We always parse the tags cause we're looking for other tags too + tagParts := strings.Split(fieldType.Tag.Get(d.config.TagName), ",") + for _, tag := range tagParts[1:] { + if tag == "squash" { + squash = true + break + } + + if tag == "remain" { + remain = true + break + } + } + + if squash { + if fieldVal.Kind() != reflect.Struct { + errors = appendErrors(errors, + fmt.Errorf("%s: unsupported type for squash: %s", fieldType.Name, fieldVal.Kind())) + } else { + structs = append(structs, fieldVal) + } + continue + } + + // Build our field + if remain { + remainField = &field{fieldType, fieldVal} + } else { + // Normal struct field, store it away + fields = append(fields, field{fieldType, fieldVal}) + } + } + } + + // for fieldType, field := range fields { + for _, f := range fields { + field, fieldValue := f.field, f.val + fieldName := field.Name + + tagValue := field.Tag.Get(d.config.TagName) + tagValue = strings.SplitN(tagValue, ",", 2)[0] + if tagValue != "" { + fieldName = tagValue + } + + rawMapKey := reflect.ValueOf(fieldName) + rawMapVal := dataVal.MapIndex(rawMapKey) + if !rawMapVal.IsValid() { + // Do a slower search by iterating over each key and + // doing case-insensitive search. + for dataValKey := range dataValKeys { + mK, ok := dataValKey.Interface().(string) + if !ok { + // Not a string key + continue + } + + if d.config.MatchName(mK, fieldName) { + rawMapKey = dataValKey + rawMapVal = dataVal.MapIndex(dataValKey) + break + } + } + + if !rawMapVal.IsValid() { + // There was no matching key in the map for the value in + // the struct. Remember it for potential errors and metadata. + targetValKeysUnused[fieldName] = struct{}{} + continue + } + } + + if !fieldValue.IsValid() { + // This should never happen + panic("field is not valid") + } + + // If we can't set the field, then it is unexported or something, + // and we just continue onwards. + if !fieldValue.CanSet() { + continue + } + + // Delete the key we're using from the unused map so we stop tracking + delete(dataValKeysUnused, rawMapKey.Interface()) + + // If the name is empty string, then we're at the root, and we + // don't dot-join the fields. + if name != "" { + fieldName = name + "." + fieldName + } + + if err := d.decode(fieldName, rawMapVal.Interface(), fieldValue); err != nil { + errors = appendErrors(errors, err) + } + } + + // If we have a "remain"-tagged field and we have unused keys then + // we put the unused keys directly into the remain field. + if remainField != nil && len(dataValKeysUnused) > 0 { + // Build a map of only the unused values + remain := map[interface{}]interface{}{} + for key := range dataValKeysUnused { + remain[key] = dataVal.MapIndex(reflect.ValueOf(key)).Interface() + } + + // Decode it as-if we were just decoding this map onto our map. + if err := d.decodeMap(name, remain, remainField.val); err != nil { + errors = appendErrors(errors, err) + } + + // Set the map to nil so we have none so that the next check will + // not error (ErrorUnused) + dataValKeysUnused = nil + } + + if d.config.ErrorUnused && len(dataValKeysUnused) > 0 { + keys := make([]string, 0, len(dataValKeysUnused)) + for rawKey := range dataValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has invalid keys: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if d.config.ErrorUnset && len(targetValKeysUnused) > 0 { + keys := make([]string, 0, len(targetValKeysUnused)) + for rawKey := range targetValKeysUnused { + keys = append(keys, rawKey.(string)) + } + sort.Strings(keys) + + err := fmt.Errorf("'%s' has unset fields: %s", name, strings.Join(keys, ", ")) + errors = appendErrors(errors, err) + } + + if len(errors) > 0 { + return &Error{errors} + } + + // Add the unused keys to the list of unused keys if we're tracking metadata + if d.config.Metadata != nil { + for rawKey := range dataValKeysUnused { + key := rawKey.(string) + if name != "" { + key = name + "." + key + } + + d.config.Metadata.Unused = append(d.config.Metadata.Unused, key) + } + for rawKey := range targetValKeysUnused { + key := rawKey.(string) + if name != "" { + key = name + "." + key + } + + d.config.Metadata.Unset = append(d.config.Metadata.Unset, key) + } + } + + return nil +} + +func isEmptyValue(v reflect.Value) bool { + switch getKind(v) { + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func getKind(val reflect.Value) reflect.Kind { + kind := val.Kind() + + switch { + case kind >= reflect.Int && kind <= reflect.Int64: + return reflect.Int + case kind >= reflect.Uint && kind <= reflect.Uint64: + return reflect.Uint + case kind >= reflect.Float32 && kind <= reflect.Float64: + return reflect.Float32 + default: + return kind + } +} + +func isStructTypeConvertibleToMap(typ reflect.Type, checkMapstructureTags bool, tagName string) bool { + for i := 0; i < typ.NumField(); i++ { + f := typ.Field(i) + if f.PkgPath == "" && !checkMapstructureTags { // check for unexported fields + return true + } + if checkMapstructureTags && f.Tag.Get(tagName) != "" { // check for mapstructure tags inside + return true + } + } + return false +} + +func dereferencePtrToStructIfNeeded(v reflect.Value, tagName string) reflect.Value { + if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct { + return v + } + deref := v.Elem() + derefT := deref.Type() + if isStructTypeConvertibleToMap(derefT, true, tagName) { + return deref + } + return v +} diff --git a/sarif/vendor/modules.txt b/sarif/vendor/modules.txt new file mode 100644 index 0000000..707d58d --- /dev/null +++ b/sarif/vendor/modules.txt @@ -0,0 +1,3 @@ +# github.com/mitchellh/mapstructure v1.5.0 +## explicit; go 1.14 +github.com/mitchellh/mapstructure