sarif-ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE +21 -0
- data/README.md +191 -0
- data/Rakefile +10 -0
- data/lib/sarif/address.rb +67 -0
- data/lib/sarif/artifact.rb +76 -0
- data/lib/sarif/artifact_change.rb +46 -0
- data/lib/sarif/artifact_content.rb +49 -0
- data/lib/sarif/artifact_location.rb +52 -0
- data/lib/sarif/attachment.rb +52 -0
- data/lib/sarif/code_flow.rb +46 -0
- data/lib/sarif/configuration_override.rb +46 -0
- data/lib/sarif/conversion.rb +49 -0
- data/lib/sarif/edge.rb +52 -0
- data/lib/sarif/edge_traversal.rb +52 -0
- data/lib/sarif/exception.rb +52 -0
- data/lib/sarif/external_properties.rb +100 -0
- data/lib/sarif/external_property_file_reference.rb +49 -0
- data/lib/sarif/external_property_file_references.rb +88 -0
- data/lib/sarif/fix.rb +46 -0
- data/lib/sarif/graph.rb +49 -0
- data/lib/sarif/graph_traversal.rb +58 -0
- data/lib/sarif/invocation.rb +115 -0
- data/lib/sarif/location.rb +58 -0
- data/lib/sarif/location_relationship.rb +49 -0
- data/lib/sarif/log.rb +52 -0
- data/lib/sarif/logical_location.rb +58 -0
- data/lib/sarif/message.rb +52 -0
- data/lib/sarif/multiformat_message_string.rb +46 -0
- data/lib/sarif/node.rb +52 -0
- data/lib/sarif/notification.rb +64 -0
- data/lib/sarif/physical_location.rb +52 -0
- data/lib/sarif/property_bag.rb +40 -0
- data/lib/sarif/rectangle.rb +55 -0
- data/lib/sarif/region.rb +73 -0
- data/lib/sarif/replacement.rb +46 -0
- data/lib/sarif/reporting_configuration.rb +52 -0
- data/lib/sarif/reporting_descriptor.rb +79 -0
- data/lib/sarif/reporting_descriptor_reference.rb +52 -0
- data/lib/sarif/reporting_descriptor_relationship.rb +49 -0
- data/lib/sarif/result.rb +127 -0
- data/lib/sarif/result_provenance.rb +58 -0
- data/lib/sarif/run.rb +121 -0
- data/lib/sarif/run_automation_details.rb +52 -0
- data/lib/sarif/schema/sarif-schema-2.1.0.json +3389 -0
- data/lib/sarif/special_locations.rb +43 -0
- data/lib/sarif/stack.rb +46 -0
- data/lib/sarif/stack_frame.rb +52 -0
- data/lib/sarif/suppression.rb +55 -0
- data/lib/sarif/thread_flow.rb +55 -0
- data/lib/sarif/thread_flow_location.rb +79 -0
- data/lib/sarif/tool.rb +46 -0
- data/lib/sarif/tool_component.rb +121 -0
- data/lib/sarif/tool_component_reference.rb +49 -0
- data/lib/sarif/translation_metadata.rb +58 -0
- data/lib/sarif/version.rb +5 -0
- data/lib/sarif/version_control_details.rb +58 -0
- data/lib/sarif/web_request.rb +64 -0
- data/lib/sarif/web_response.rb +64 -0
- data/lib/sarif.rb +121 -0
- data/sig/sarif.rbs +4 -0
- metadata +106 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# The runtime environment of the analysis tool run.
|
|
5
|
+
class Invocation
|
|
6
|
+
attr_accessor :command_line, :arguments, :response_files, :start_time_utc, :end_time_utc, :exit_code, :rule_configuration_overrides, :notification_configuration_overrides, :tool_execution_notifications, :tool_configuration_notifications, :exit_code_description, :exit_signal_name, :exit_signal_number, :process_start_failure_message, :execution_successful, :machine, :account, :process_id, :executable_location, :working_directory, :environment_variables, :stdin, :stdout, :stderr, :stdout_stderr, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(command_line: nil, arguments: nil, response_files: nil, start_time_utc: nil, end_time_utc: nil, exit_code: nil, rule_configuration_overrides: [], notification_configuration_overrides: [], tool_execution_notifications: [], tool_configuration_notifications: [], exit_code_description: nil, exit_signal_name: nil, exit_signal_number: nil, process_start_failure_message: nil, execution_successful:, machine: nil, account: nil, process_id: nil, executable_location: nil, working_directory: nil, environment_variables: nil, stdin: nil, stdout: nil, stderr: nil, stdout_stderr: nil, properties: nil)
|
|
9
|
+
@command_line = command_line
|
|
10
|
+
@arguments = arguments
|
|
11
|
+
@response_files = response_files
|
|
12
|
+
@start_time_utc = start_time_utc
|
|
13
|
+
@end_time_utc = end_time_utc
|
|
14
|
+
@exit_code = exit_code
|
|
15
|
+
@rule_configuration_overrides = rule_configuration_overrides
|
|
16
|
+
@notification_configuration_overrides = notification_configuration_overrides
|
|
17
|
+
@tool_execution_notifications = tool_execution_notifications
|
|
18
|
+
@tool_configuration_notifications = tool_configuration_notifications
|
|
19
|
+
@exit_code_description = exit_code_description
|
|
20
|
+
@exit_signal_name = exit_signal_name
|
|
21
|
+
@exit_signal_number = exit_signal_number
|
|
22
|
+
@process_start_failure_message = process_start_failure_message
|
|
23
|
+
@execution_successful = execution_successful
|
|
24
|
+
@machine = machine
|
|
25
|
+
@account = account
|
|
26
|
+
@process_id = process_id
|
|
27
|
+
@executable_location = executable_location
|
|
28
|
+
@working_directory = working_directory
|
|
29
|
+
@environment_variables = environment_variables
|
|
30
|
+
@stdin = stdin
|
|
31
|
+
@stdout = stdout
|
|
32
|
+
@stderr = stderr
|
|
33
|
+
@stdout_stderr = stdout_stderr
|
|
34
|
+
@properties = properties
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def to_h
|
|
38
|
+
h = {}
|
|
39
|
+
h["commandLine"] = @command_line unless @command_line.nil?
|
|
40
|
+
h["arguments"] = @arguments if @arguments&.any?
|
|
41
|
+
h["responseFiles"] = @response_files&.map(&:to_h) if @response_files&.any?
|
|
42
|
+
h["startTimeUtc"] = @start_time_utc unless @start_time_utc.nil?
|
|
43
|
+
h["endTimeUtc"] = @end_time_utc unless @end_time_utc.nil?
|
|
44
|
+
h["exitCode"] = @exit_code unless @exit_code.nil?
|
|
45
|
+
h["ruleConfigurationOverrides"] = @rule_configuration_overrides&.map(&:to_h) if @rule_configuration_overrides&.any?
|
|
46
|
+
h["notificationConfigurationOverrides"] = @notification_configuration_overrides&.map(&:to_h) if @notification_configuration_overrides&.any?
|
|
47
|
+
h["toolExecutionNotifications"] = @tool_execution_notifications&.map(&:to_h) if @tool_execution_notifications&.any?
|
|
48
|
+
h["toolConfigurationNotifications"] = @tool_configuration_notifications&.map(&:to_h) if @tool_configuration_notifications&.any?
|
|
49
|
+
h["exitCodeDescription"] = @exit_code_description unless @exit_code_description.nil?
|
|
50
|
+
h["exitSignalName"] = @exit_signal_name unless @exit_signal_name.nil?
|
|
51
|
+
h["exitSignalNumber"] = @exit_signal_number unless @exit_signal_number.nil?
|
|
52
|
+
h["processStartFailureMessage"] = @process_start_failure_message unless @process_start_failure_message.nil?
|
|
53
|
+
h["executionSuccessful"] = @execution_successful
|
|
54
|
+
h["machine"] = @machine unless @machine.nil?
|
|
55
|
+
h["account"] = @account unless @account.nil?
|
|
56
|
+
h["processId"] = @process_id unless @process_id.nil?
|
|
57
|
+
h["executableLocation"] = @executable_location&.to_h unless @executable_location.nil?
|
|
58
|
+
h["workingDirectory"] = @working_directory&.to_h unless @working_directory.nil?
|
|
59
|
+
h["environmentVariables"] = @environment_variables unless @environment_variables.nil?
|
|
60
|
+
h["stdin"] = @stdin&.to_h unless @stdin.nil?
|
|
61
|
+
h["stdout"] = @stdout&.to_h unless @stdout.nil?
|
|
62
|
+
h["stderr"] = @stderr&.to_h unless @stderr.nil?
|
|
63
|
+
h["stdoutStderr"] = @stdout_stderr&.to_h unless @stdout_stderr.nil?
|
|
64
|
+
h["properties"] = @properties unless @properties.nil?
|
|
65
|
+
h
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def to_json(pretty: false)
|
|
69
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.from_hash(h)
|
|
73
|
+
return nil if h.nil?
|
|
74
|
+
new(
|
|
75
|
+
command_line: h["commandLine"],
|
|
76
|
+
arguments: h["arguments"],
|
|
77
|
+
response_files: h["responseFiles"]&.map { |v| ArtifactLocation.from_hash(v) },
|
|
78
|
+
start_time_utc: h["startTimeUtc"],
|
|
79
|
+
end_time_utc: h["endTimeUtc"],
|
|
80
|
+
exit_code: h["exitCode"],
|
|
81
|
+
rule_configuration_overrides: h["ruleConfigurationOverrides"]&.map { |v| ConfigurationOverride.from_hash(v) } || [],
|
|
82
|
+
notification_configuration_overrides: h["notificationConfigurationOverrides"]&.map { |v| ConfigurationOverride.from_hash(v) } || [],
|
|
83
|
+
tool_execution_notifications: h["toolExecutionNotifications"]&.map { |v| Notification.from_hash(v) } || [],
|
|
84
|
+
tool_configuration_notifications: h["toolConfigurationNotifications"]&.map { |v| Notification.from_hash(v) } || [],
|
|
85
|
+
exit_code_description: h["exitCodeDescription"],
|
|
86
|
+
exit_signal_name: h["exitSignalName"],
|
|
87
|
+
exit_signal_number: h["exitSignalNumber"],
|
|
88
|
+
process_start_failure_message: h["processStartFailureMessage"],
|
|
89
|
+
execution_successful: h["executionSuccessful"],
|
|
90
|
+
machine: h["machine"],
|
|
91
|
+
account: h["account"],
|
|
92
|
+
process_id: h["processId"],
|
|
93
|
+
executable_location: ArtifactLocation.from_hash(h["executableLocation"]),
|
|
94
|
+
working_directory: ArtifactLocation.from_hash(h["workingDirectory"]),
|
|
95
|
+
environment_variables: h["environmentVariables"],
|
|
96
|
+
stdin: ArtifactLocation.from_hash(h["stdin"]),
|
|
97
|
+
stdout: ArtifactLocation.from_hash(h["stdout"]),
|
|
98
|
+
stderr: ArtifactLocation.from_hash(h["stderr"]),
|
|
99
|
+
stdout_stderr: ArtifactLocation.from_hash(h["stdoutStderr"]),
|
|
100
|
+
properties: h["properties"]
|
|
101
|
+
)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def ==(other)
|
|
105
|
+
return false unless other.is_a?(Invocation)
|
|
106
|
+
@command_line == other.command_line && @arguments == other.arguments && @response_files == other.response_files && @start_time_utc == other.start_time_utc && @end_time_utc == other.end_time_utc && @exit_code == other.exit_code && @rule_configuration_overrides == other.rule_configuration_overrides && @notification_configuration_overrides == other.notification_configuration_overrides && @tool_execution_notifications == other.tool_execution_notifications && @tool_configuration_notifications == other.tool_configuration_notifications && @exit_code_description == other.exit_code_description && @exit_signal_name == other.exit_signal_name && @exit_signal_number == other.exit_signal_number && @process_start_failure_message == other.process_start_failure_message && @execution_successful == other.execution_successful && @machine == other.machine && @account == other.account && @process_id == other.process_id && @executable_location == other.executable_location && @working_directory == other.working_directory && @environment_variables == other.environment_variables && @stdin == other.stdin && @stdout == other.stdout && @stderr == other.stderr && @stdout_stderr == other.stdout_stderr && @properties == other.properties
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
alias eql? ==
|
|
110
|
+
|
|
111
|
+
def hash
|
|
112
|
+
[@command_line, @arguments, @response_files, @start_time_utc, @end_time_utc, @exit_code, @rule_configuration_overrides, @notification_configuration_overrides, @tool_execution_notifications, @tool_configuration_notifications, @exit_code_description, @exit_signal_name, @exit_signal_number, @process_start_failure_message, @execution_successful, @machine, @account, @process_id, @executable_location, @working_directory, @environment_variables, @stdin, @stdout, @stderr, @stdout_stderr, @properties].hash
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# A location within a programming artifact.
|
|
5
|
+
class Location
|
|
6
|
+
attr_accessor :id, :physical_location, :logical_locations, :message, :annotations, :relationships, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(id: -1, physical_location: nil, logical_locations: [], message: nil, annotations: [], relationships: [], properties: nil)
|
|
9
|
+
@id = id
|
|
10
|
+
@physical_location = physical_location
|
|
11
|
+
@logical_locations = logical_locations
|
|
12
|
+
@message = message
|
|
13
|
+
@annotations = annotations
|
|
14
|
+
@relationships = relationships
|
|
15
|
+
@properties = properties
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_h
|
|
19
|
+
h = {}
|
|
20
|
+
h["id"] = @id if @id && @id != -1
|
|
21
|
+
h["physicalLocation"] = @physical_location&.to_h unless @physical_location.nil?
|
|
22
|
+
h["logicalLocations"] = @logical_locations&.map(&:to_h) if @logical_locations&.any?
|
|
23
|
+
h["message"] = @message&.to_h unless @message.nil?
|
|
24
|
+
h["annotations"] = @annotations&.map(&:to_h) if @annotations&.any?
|
|
25
|
+
h["relationships"] = @relationships&.map(&:to_h) if @relationships&.any?
|
|
26
|
+
h["properties"] = @properties unless @properties.nil?
|
|
27
|
+
h
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_json(pretty: false)
|
|
31
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.from_hash(h)
|
|
35
|
+
return nil if h.nil?
|
|
36
|
+
new(
|
|
37
|
+
id: h["id"] || -1,
|
|
38
|
+
physical_location: PhysicalLocation.from_hash(h["physicalLocation"]),
|
|
39
|
+
logical_locations: h["logicalLocations"]&.map { |v| LogicalLocation.from_hash(v) } || [],
|
|
40
|
+
message: Message.from_hash(h["message"]),
|
|
41
|
+
annotations: h["annotations"]&.map { |v| Region.from_hash(v) } || [],
|
|
42
|
+
relationships: h["relationships"]&.map { |v| LocationRelationship.from_hash(v) } || [],
|
|
43
|
+
properties: h["properties"]
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def ==(other)
|
|
48
|
+
return false unless other.is_a?(Location)
|
|
49
|
+
@id == other.id && @physical_location == other.physical_location && @logical_locations == other.logical_locations && @message == other.message && @annotations == other.annotations && @relationships == other.relationships && @properties == other.properties
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
alias eql? ==
|
|
53
|
+
|
|
54
|
+
def hash
|
|
55
|
+
[@id, @physical_location, @logical_locations, @message, @annotations, @relationships, @properties].hash
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Information about the relation of one location to another.
|
|
5
|
+
class LocationRelationship
|
|
6
|
+
attr_accessor :target, :kinds, :description, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(target:, kinds: ["relevant"], description: nil, properties: nil)
|
|
9
|
+
@target = target
|
|
10
|
+
@kinds = kinds
|
|
11
|
+
@description = description
|
|
12
|
+
@properties = properties
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
h = {}
|
|
17
|
+
h["target"] = @target
|
|
18
|
+
h["kinds"] = @kinds if @kinds&.any?
|
|
19
|
+
h["description"] = @description&.to_h unless @description.nil?
|
|
20
|
+
h["properties"] = @properties unless @properties.nil?
|
|
21
|
+
h
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_json(pretty: false)
|
|
25
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.from_hash(h)
|
|
29
|
+
return nil if h.nil?
|
|
30
|
+
new(
|
|
31
|
+
target: h["target"],
|
|
32
|
+
kinds: h.key?("kinds") ? h["kinds"] : ["relevant"],
|
|
33
|
+
description: Message.from_hash(h["description"]),
|
|
34
|
+
properties: h["properties"]
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ==(other)
|
|
39
|
+
return false unless other.is_a?(LocationRelationship)
|
|
40
|
+
@target == other.target && @kinds == other.kinds && @description == other.description && @properties == other.properties
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
alias eql? ==
|
|
44
|
+
|
|
45
|
+
def hash
|
|
46
|
+
[@target, @kinds, @description, @properties].hash
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/sarif/log.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Static Analysis Results Format (SARIF) Version 2.1.0 JSON Schema: a standard format for the output of static analysis tools.
|
|
5
|
+
class Log
|
|
6
|
+
attr_accessor :schema_uri, :version, :runs, :inline_external_properties, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(schema_uri: nil, version:, runs:, inline_external_properties: nil, properties: nil)
|
|
9
|
+
@schema_uri = schema_uri
|
|
10
|
+
@version = version
|
|
11
|
+
@runs = runs
|
|
12
|
+
@inline_external_properties = inline_external_properties
|
|
13
|
+
@properties = properties
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
h = {}
|
|
18
|
+
h["$schema"] = @schema_uri unless @schema_uri.nil?
|
|
19
|
+
h["version"] = @version&.to_s
|
|
20
|
+
h["runs"] = @runs&.map(&:to_h)
|
|
21
|
+
h["inlineExternalProperties"] = @inline_external_properties&.map(&:to_h) if @inline_external_properties&.any?
|
|
22
|
+
h["properties"] = @properties unless @properties.nil?
|
|
23
|
+
h
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_json(pretty: false)
|
|
27
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.from_hash(h)
|
|
31
|
+
return nil if h.nil?
|
|
32
|
+
new(
|
|
33
|
+
schema_uri: h["$schema"],
|
|
34
|
+
version: h["version"],
|
|
35
|
+
runs: h["runs"]&.map { |v| Run.from_hash(v) },
|
|
36
|
+
inline_external_properties: h["inlineExternalProperties"]&.map { |v| ExternalProperties.from_hash(v) },
|
|
37
|
+
properties: h["properties"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
return false unless other.is_a?(Log)
|
|
43
|
+
@schema_uri == other.schema_uri && @version == other.version && @runs == other.runs && @inline_external_properties == other.inline_external_properties && @properties == other.properties
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
[@schema_uri, @version, @runs, @inline_external_properties, @properties].hash
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# A logical location of a construct that produced a result.
|
|
5
|
+
class LogicalLocation
|
|
6
|
+
attr_accessor :name, :index, :fully_qualified_name, :decorated_name, :parent_index, :kind, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(name: nil, index: -1, fully_qualified_name: nil, decorated_name: nil, parent_index: -1, kind: nil, properties: nil)
|
|
9
|
+
@name = name
|
|
10
|
+
@index = index
|
|
11
|
+
@fully_qualified_name = fully_qualified_name
|
|
12
|
+
@decorated_name = decorated_name
|
|
13
|
+
@parent_index = parent_index
|
|
14
|
+
@kind = kind
|
|
15
|
+
@properties = properties
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_h
|
|
19
|
+
h = {}
|
|
20
|
+
h["name"] = @name unless @name.nil?
|
|
21
|
+
h["index"] = @index if @index && @index != -1
|
|
22
|
+
h["fullyQualifiedName"] = @fully_qualified_name unless @fully_qualified_name.nil?
|
|
23
|
+
h["decoratedName"] = @decorated_name unless @decorated_name.nil?
|
|
24
|
+
h["parentIndex"] = @parent_index if @parent_index && @parent_index != -1
|
|
25
|
+
h["kind"] = @kind unless @kind.nil?
|
|
26
|
+
h["properties"] = @properties unless @properties.nil?
|
|
27
|
+
h
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_json(pretty: false)
|
|
31
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.from_hash(h)
|
|
35
|
+
return nil if h.nil?
|
|
36
|
+
new(
|
|
37
|
+
name: h["name"],
|
|
38
|
+
index: h["index"] || -1,
|
|
39
|
+
fully_qualified_name: h["fullyQualifiedName"],
|
|
40
|
+
decorated_name: h["decoratedName"],
|
|
41
|
+
parent_index: h["parentIndex"] || -1,
|
|
42
|
+
kind: h["kind"],
|
|
43
|
+
properties: h["properties"]
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def ==(other)
|
|
48
|
+
return false unless other.is_a?(LogicalLocation)
|
|
49
|
+
@name == other.name && @index == other.index && @fully_qualified_name == other.fully_qualified_name && @decorated_name == other.decorated_name && @parent_index == other.parent_index && @kind == other.kind && @properties == other.properties
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
alias eql? ==
|
|
53
|
+
|
|
54
|
+
def hash
|
|
55
|
+
[@name, @index, @fully_qualified_name, @decorated_name, @parent_index, @kind, @properties].hash
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Encapsulates a message intended to be read by the end user.
|
|
5
|
+
class Message
|
|
6
|
+
attr_accessor :text, :markdown, :id, :arguments, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(text: nil, markdown: nil, id: nil, arguments: [], properties: nil)
|
|
9
|
+
@text = text
|
|
10
|
+
@markdown = markdown
|
|
11
|
+
@id = id
|
|
12
|
+
@arguments = arguments
|
|
13
|
+
@properties = properties
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
h = {}
|
|
18
|
+
h["text"] = @text unless @text.nil?
|
|
19
|
+
h["markdown"] = @markdown unless @markdown.nil?
|
|
20
|
+
h["id"] = @id unless @id.nil?
|
|
21
|
+
h["arguments"] = @arguments if @arguments&.any?
|
|
22
|
+
h["properties"] = @properties unless @properties.nil?
|
|
23
|
+
h
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_json(pretty: false)
|
|
27
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.from_hash(h)
|
|
31
|
+
return nil if h.nil?
|
|
32
|
+
new(
|
|
33
|
+
text: h["text"],
|
|
34
|
+
markdown: h["markdown"],
|
|
35
|
+
id: h["id"],
|
|
36
|
+
arguments: h["arguments"] || [],
|
|
37
|
+
properties: h["properties"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
return false unless other.is_a?(Message)
|
|
43
|
+
@text == other.text && @markdown == other.markdown && @id == other.id && @arguments == other.arguments && @properties == other.properties
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
[@text, @markdown, @id, @arguments, @properties].hash
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# A message string or message format string rendered in multiple formats.
|
|
5
|
+
class MultiformatMessageString
|
|
6
|
+
attr_accessor :text, :markdown, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(text:, markdown: nil, properties: nil)
|
|
9
|
+
@text = text
|
|
10
|
+
@markdown = markdown
|
|
11
|
+
@properties = properties
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_h
|
|
15
|
+
h = {}
|
|
16
|
+
h["text"] = @text
|
|
17
|
+
h["markdown"] = @markdown unless @markdown.nil?
|
|
18
|
+
h["properties"] = @properties unless @properties.nil?
|
|
19
|
+
h
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_json(pretty: false)
|
|
23
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.from_hash(h)
|
|
27
|
+
return nil if h.nil?
|
|
28
|
+
new(
|
|
29
|
+
text: h["text"],
|
|
30
|
+
markdown: h["markdown"],
|
|
31
|
+
properties: h["properties"]
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def ==(other)
|
|
36
|
+
return false unless other.is_a?(MultiformatMessageString)
|
|
37
|
+
@text == other.text && @markdown == other.markdown && @properties == other.properties
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
alias eql? ==
|
|
41
|
+
|
|
42
|
+
def hash
|
|
43
|
+
[@text, @markdown, @properties].hash
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/sarif/node.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Represents a node in a graph.
|
|
5
|
+
class Node
|
|
6
|
+
attr_accessor :id, :label, :location, :children, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(id:, label: nil, location: nil, children: [], properties: nil)
|
|
9
|
+
@id = id
|
|
10
|
+
@label = label
|
|
11
|
+
@location = location
|
|
12
|
+
@children = children
|
|
13
|
+
@properties = properties
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
h = {}
|
|
18
|
+
h["id"] = @id
|
|
19
|
+
h["label"] = @label&.to_h unless @label.nil?
|
|
20
|
+
h["location"] = @location&.to_h unless @location.nil?
|
|
21
|
+
h["children"] = @children&.map(&:to_h) if @children&.any?
|
|
22
|
+
h["properties"] = @properties unless @properties.nil?
|
|
23
|
+
h
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_json(pretty: false)
|
|
27
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.from_hash(h)
|
|
31
|
+
return nil if h.nil?
|
|
32
|
+
new(
|
|
33
|
+
id: h["id"],
|
|
34
|
+
label: Message.from_hash(h["label"]),
|
|
35
|
+
location: Location.from_hash(h["location"]),
|
|
36
|
+
children: h["children"]&.map { |v| Node.from_hash(v) } || [],
|
|
37
|
+
properties: h["properties"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
return false unless other.is_a?(Node)
|
|
43
|
+
@id == other.id && @label == other.label && @location == other.location && @children == other.children && @properties == other.properties
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
[@id, @label, @location, @children, @properties].hash
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Describes a condition relevant to the tool itself, as opposed to being relevant to a target being analyzed by the tool.
|
|
5
|
+
class Notification
|
|
6
|
+
attr_accessor :locations, :message, :level, :thread_id, :time_utc, :exception, :descriptor, :associated_rule, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(locations: [], message:, level: "warning", thread_id: nil, time_utc: nil, exception: nil, descriptor: nil, associated_rule: nil, properties: nil)
|
|
9
|
+
@locations = locations
|
|
10
|
+
@message = message
|
|
11
|
+
@level = level
|
|
12
|
+
@thread_id = thread_id
|
|
13
|
+
@time_utc = time_utc
|
|
14
|
+
@exception = exception
|
|
15
|
+
@descriptor = descriptor
|
|
16
|
+
@associated_rule = associated_rule
|
|
17
|
+
@properties = properties
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_h
|
|
21
|
+
h = {}
|
|
22
|
+
h["locations"] = @locations&.map(&:to_h) if @locations&.any?
|
|
23
|
+
h["message"] = @message&.to_h
|
|
24
|
+
h["level"] = @level&.to_s if @level && @level != "warning"
|
|
25
|
+
h["threadId"] = @thread_id unless @thread_id.nil?
|
|
26
|
+
h["timeUtc"] = @time_utc unless @time_utc.nil?
|
|
27
|
+
h["exception"] = @exception&.to_h unless @exception.nil?
|
|
28
|
+
h["descriptor"] = @descriptor&.to_h unless @descriptor.nil?
|
|
29
|
+
h["associatedRule"] = @associated_rule&.to_h unless @associated_rule.nil?
|
|
30
|
+
h["properties"] = @properties unless @properties.nil?
|
|
31
|
+
h
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_json(pretty: false)
|
|
35
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.from_hash(h)
|
|
39
|
+
return nil if h.nil?
|
|
40
|
+
new(
|
|
41
|
+
locations: h["locations"]&.map { |v| Location.from_hash(v) } || [],
|
|
42
|
+
message: Message.from_hash(h["message"]),
|
|
43
|
+
level: h["level"] || "warning",
|
|
44
|
+
thread_id: h["threadId"],
|
|
45
|
+
time_utc: h["timeUtc"],
|
|
46
|
+
exception: Exception.from_hash(h["exception"]),
|
|
47
|
+
descriptor: ReportingDescriptorReference.from_hash(h["descriptor"]),
|
|
48
|
+
associated_rule: ReportingDescriptorReference.from_hash(h["associatedRule"]),
|
|
49
|
+
properties: h["properties"]
|
|
50
|
+
)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def ==(other)
|
|
54
|
+
return false unless other.is_a?(Notification)
|
|
55
|
+
@locations == other.locations && @message == other.message && @level == other.level && @thread_id == other.thread_id && @time_utc == other.time_utc && @exception == other.exception && @descriptor == other.descriptor && @associated_rule == other.associated_rule && @properties == other.properties
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
alias eql? ==
|
|
59
|
+
|
|
60
|
+
def hash
|
|
61
|
+
[@locations, @message, @level, @thread_id, @time_utc, @exception, @descriptor, @associated_rule, @properties].hash
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# 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.
|
|
5
|
+
class PhysicalLocation
|
|
6
|
+
attr_accessor :address, :artifact_location, :region, :context_region, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(address: nil, artifact_location: nil, region: nil, context_region: nil, properties: nil)
|
|
9
|
+
@address = address
|
|
10
|
+
@artifact_location = artifact_location
|
|
11
|
+
@region = region
|
|
12
|
+
@context_region = context_region
|
|
13
|
+
@properties = properties
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
h = {}
|
|
18
|
+
h["address"] = @address&.to_h unless @address.nil?
|
|
19
|
+
h["artifactLocation"] = @artifact_location&.to_h unless @artifact_location.nil?
|
|
20
|
+
h["region"] = @region&.to_h unless @region.nil?
|
|
21
|
+
h["contextRegion"] = @context_region&.to_h unless @context_region.nil?
|
|
22
|
+
h["properties"] = @properties unless @properties.nil?
|
|
23
|
+
h
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def to_json(pretty: false)
|
|
27
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.from_hash(h)
|
|
31
|
+
return nil if h.nil?
|
|
32
|
+
new(
|
|
33
|
+
address: Address.from_hash(h["address"]),
|
|
34
|
+
artifact_location: ArtifactLocation.from_hash(h["artifactLocation"]),
|
|
35
|
+
region: Region.from_hash(h["region"]),
|
|
36
|
+
context_region: Region.from_hash(h["contextRegion"]),
|
|
37
|
+
properties: h["properties"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
return false unless other.is_a?(PhysicalLocation)
|
|
43
|
+
@address == other.address && @artifact_location == other.artifact_location && @region == other.region && @context_region == other.context_region && @properties == other.properties
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
[@address, @artifact_location, @region, @context_region, @properties].hash
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Key/value pairs that provide additional information about the object.
|
|
5
|
+
class PropertyBag
|
|
6
|
+
attr_accessor :tags
|
|
7
|
+
|
|
8
|
+
def initialize(tags: [])
|
|
9
|
+
@tags = tags
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_h
|
|
13
|
+
h = {}
|
|
14
|
+
h["tags"] = @tags if @tags&.any?
|
|
15
|
+
h
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_json(pretty: false)
|
|
19
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.from_hash(h)
|
|
23
|
+
return nil if h.nil?
|
|
24
|
+
new(
|
|
25
|
+
tags: h["tags"] || []
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def ==(other)
|
|
30
|
+
return false unless other.is_a?(PropertyBag)
|
|
31
|
+
@tags == other.tags
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
alias eql? ==
|
|
35
|
+
|
|
36
|
+
def hash
|
|
37
|
+
[@tags].hash
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|