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,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Describes how a converter transformed the output of a static analysis tool from the analysis tool's native output format into the SARIF format.
|
|
5
|
+
class Conversion
|
|
6
|
+
attr_accessor :tool, :invocation, :analysis_tool_log_files, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(tool:, invocation: nil, analysis_tool_log_files: [], properties: nil)
|
|
9
|
+
@tool = tool
|
|
10
|
+
@invocation = invocation
|
|
11
|
+
@analysis_tool_log_files = analysis_tool_log_files
|
|
12
|
+
@properties = properties
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
h = {}
|
|
17
|
+
h["tool"] = @tool&.to_h
|
|
18
|
+
h["invocation"] = @invocation&.to_h unless @invocation.nil?
|
|
19
|
+
h["analysisToolLogFiles"] = @analysis_tool_log_files&.map(&:to_h) if @analysis_tool_log_files&.any?
|
|
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
|
+
tool: Tool.from_hash(h["tool"]),
|
|
32
|
+
invocation: Invocation.from_hash(h["invocation"]),
|
|
33
|
+
analysis_tool_log_files: h["analysisToolLogFiles"]&.map { |v| ArtifactLocation.from_hash(v) } || [],
|
|
34
|
+
properties: h["properties"]
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ==(other)
|
|
39
|
+
return false unless other.is_a?(Conversion)
|
|
40
|
+
@tool == other.tool && @invocation == other.invocation && @analysis_tool_log_files == other.analysis_tool_log_files && @properties == other.properties
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
alias eql? ==
|
|
44
|
+
|
|
45
|
+
def hash
|
|
46
|
+
[@tool, @invocation, @analysis_tool_log_files, @properties].hash
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/sarif/edge.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Represents a directed edge in a graph.
|
|
5
|
+
class Edge
|
|
6
|
+
attr_accessor :id, :label, :source_node_id, :target_node_id, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(id:, label: nil, source_node_id:, target_node_id:, properties: nil)
|
|
9
|
+
@id = id
|
|
10
|
+
@label = label
|
|
11
|
+
@source_node_id = source_node_id
|
|
12
|
+
@target_node_id = target_node_id
|
|
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["sourceNodeId"] = @source_node_id
|
|
21
|
+
h["targetNodeId"] = @target_node_id
|
|
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
|
+
source_node_id: h["sourceNodeId"],
|
|
36
|
+
target_node_id: h["targetNodeId"],
|
|
37
|
+
properties: h["properties"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
return false unless other.is_a?(Edge)
|
|
43
|
+
@id == other.id && @label == other.label && @source_node_id == other.source_node_id && @target_node_id == other.target_node_id && @properties == other.properties
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
[@id, @label, @source_node_id, @target_node_id, @properties].hash
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Represents the traversal of a single edge during a graph traversal.
|
|
5
|
+
class EdgeTraversal
|
|
6
|
+
attr_accessor :edge_id, :message, :final_state, :step_over_edge_count, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(edge_id:, message: nil, final_state: nil, step_over_edge_count: nil, properties: nil)
|
|
9
|
+
@edge_id = edge_id
|
|
10
|
+
@message = message
|
|
11
|
+
@final_state = final_state
|
|
12
|
+
@step_over_edge_count = step_over_edge_count
|
|
13
|
+
@properties = properties
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
h = {}
|
|
18
|
+
h["edgeId"] = @edge_id
|
|
19
|
+
h["message"] = @message&.to_h unless @message.nil?
|
|
20
|
+
h["finalState"] = @final_state unless @final_state.nil?
|
|
21
|
+
h["stepOverEdgeCount"] = @step_over_edge_count unless @step_over_edge_count.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
|
+
edge_id: h["edgeId"],
|
|
34
|
+
message: Message.from_hash(h["message"]),
|
|
35
|
+
final_state: h["finalState"],
|
|
36
|
+
step_over_edge_count: h["stepOverEdgeCount"],
|
|
37
|
+
properties: h["properties"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
return false unless other.is_a?(EdgeTraversal)
|
|
43
|
+
@edge_id == other.edge_id && @message == other.message && @final_state == other.final_state && @step_over_edge_count == other.step_over_edge_count && @properties == other.properties
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
[@edge_id, @message, @final_state, @step_over_edge_count, @properties].hash
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Describes a runtime exception encountered during the execution of an analysis tool.
|
|
5
|
+
class Exception
|
|
6
|
+
attr_accessor :kind, :message, :stack, :inner_exceptions, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(kind: nil, message: nil, stack: nil, inner_exceptions: [], properties: nil)
|
|
9
|
+
@kind = kind
|
|
10
|
+
@message = message
|
|
11
|
+
@stack = stack
|
|
12
|
+
@inner_exceptions = inner_exceptions
|
|
13
|
+
@properties = properties
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_h
|
|
17
|
+
h = {}
|
|
18
|
+
h["kind"] = @kind unless @kind.nil?
|
|
19
|
+
h["message"] = @message unless @message.nil?
|
|
20
|
+
h["stack"] = @stack&.to_h unless @stack.nil?
|
|
21
|
+
h["innerExceptions"] = @inner_exceptions&.map(&:to_h) if @inner_exceptions&.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
|
+
kind: h["kind"],
|
|
34
|
+
message: h["message"],
|
|
35
|
+
stack: Stack.from_hash(h["stack"]),
|
|
36
|
+
inner_exceptions: h["innerExceptions"]&.map { |v| Exception.from_hash(v) } || [],
|
|
37
|
+
properties: h["properties"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ==(other)
|
|
42
|
+
return false unless other.is_a?(Exception)
|
|
43
|
+
@kind == other.kind && @message == other.message && @stack == other.stack && @inner_exceptions == other.inner_exceptions && @properties == other.properties
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
alias eql? ==
|
|
47
|
+
|
|
48
|
+
def hash
|
|
49
|
+
[@kind, @message, @stack, @inner_exceptions, @properties].hash
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# The top-level element of an external property file.
|
|
5
|
+
class ExternalProperties
|
|
6
|
+
attr_accessor :schema, :version, :guid, :run_guid, :conversion, :graphs, :externalized_properties, :artifacts, :invocations, :logical_locations, :thread_flow_locations, :results, :taxonomies, :driver, :extensions, :policies, :translations, :addresses, :web_requests, :web_responses, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(schema: nil, version: nil, guid: nil, run_guid: nil, conversion: nil, graphs: [], externalized_properties: nil, artifacts: nil, invocations: [], logical_locations: [], thread_flow_locations: [], results: [], taxonomies: [], driver: nil, extensions: [], policies: [], translations: [], addresses: [], web_requests: [], web_responses: [], properties: nil)
|
|
9
|
+
@schema = schema
|
|
10
|
+
@version = version
|
|
11
|
+
@guid = guid
|
|
12
|
+
@run_guid = run_guid
|
|
13
|
+
@conversion = conversion
|
|
14
|
+
@graphs = graphs
|
|
15
|
+
@externalized_properties = externalized_properties
|
|
16
|
+
@artifacts = artifacts
|
|
17
|
+
@invocations = invocations
|
|
18
|
+
@logical_locations = logical_locations
|
|
19
|
+
@thread_flow_locations = thread_flow_locations
|
|
20
|
+
@results = results
|
|
21
|
+
@taxonomies = taxonomies
|
|
22
|
+
@driver = driver
|
|
23
|
+
@extensions = extensions
|
|
24
|
+
@policies = policies
|
|
25
|
+
@translations = translations
|
|
26
|
+
@addresses = addresses
|
|
27
|
+
@web_requests = web_requests
|
|
28
|
+
@web_responses = web_responses
|
|
29
|
+
@properties = properties
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_h
|
|
33
|
+
h = {}
|
|
34
|
+
h["schema"] = @schema unless @schema.nil?
|
|
35
|
+
h["version"] = @version&.to_s unless @version.nil?
|
|
36
|
+
h["guid"] = @guid unless @guid.nil?
|
|
37
|
+
h["runGuid"] = @run_guid unless @run_guid.nil?
|
|
38
|
+
h["conversion"] = @conversion&.to_h unless @conversion.nil?
|
|
39
|
+
h["graphs"] = @graphs&.map(&:to_h) if @graphs&.any?
|
|
40
|
+
h["externalizedProperties"] = @externalized_properties unless @externalized_properties.nil?
|
|
41
|
+
h["artifacts"] = @artifacts&.map(&:to_h) if @artifacts&.any?
|
|
42
|
+
h["invocations"] = @invocations&.map(&:to_h) if @invocations&.any?
|
|
43
|
+
h["logicalLocations"] = @logical_locations&.map(&:to_h) if @logical_locations&.any?
|
|
44
|
+
h["threadFlowLocations"] = @thread_flow_locations&.map(&:to_h) if @thread_flow_locations&.any?
|
|
45
|
+
h["results"] = @results&.map(&:to_h) if @results&.any?
|
|
46
|
+
h["taxonomies"] = @taxonomies&.map(&:to_h) if @taxonomies&.any?
|
|
47
|
+
h["driver"] = @driver&.to_h unless @driver.nil?
|
|
48
|
+
h["extensions"] = @extensions&.map(&:to_h) if @extensions&.any?
|
|
49
|
+
h["policies"] = @policies&.map(&:to_h) if @policies&.any?
|
|
50
|
+
h["translations"] = @translations&.map(&:to_h) if @translations&.any?
|
|
51
|
+
h["addresses"] = @addresses&.map(&:to_h) if @addresses&.any?
|
|
52
|
+
h["webRequests"] = @web_requests&.map(&:to_h) if @web_requests&.any?
|
|
53
|
+
h["webResponses"] = @web_responses&.map(&:to_h) if @web_responses&.any?
|
|
54
|
+
h["properties"] = @properties unless @properties.nil?
|
|
55
|
+
h
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def to_json(pretty: false)
|
|
59
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.from_hash(h)
|
|
63
|
+
return nil if h.nil?
|
|
64
|
+
new(
|
|
65
|
+
schema: h["schema"],
|
|
66
|
+
version: h["version"],
|
|
67
|
+
guid: h["guid"],
|
|
68
|
+
run_guid: h["runGuid"],
|
|
69
|
+
conversion: Conversion.from_hash(h["conversion"]),
|
|
70
|
+
graphs: h["graphs"]&.map { |v| Graph.from_hash(v) } || [],
|
|
71
|
+
externalized_properties: h["externalizedProperties"],
|
|
72
|
+
artifacts: h["artifacts"]&.map { |v| Artifact.from_hash(v) },
|
|
73
|
+
invocations: h["invocations"]&.map { |v| Invocation.from_hash(v) } || [],
|
|
74
|
+
logical_locations: h["logicalLocations"]&.map { |v| LogicalLocation.from_hash(v) } || [],
|
|
75
|
+
thread_flow_locations: h["threadFlowLocations"]&.map { |v| ThreadFlowLocation.from_hash(v) } || [],
|
|
76
|
+
results: h["results"]&.map { |v| Result.from_hash(v) } || [],
|
|
77
|
+
taxonomies: h["taxonomies"]&.map { |v| ToolComponent.from_hash(v) } || [],
|
|
78
|
+
driver: ToolComponent.from_hash(h["driver"]),
|
|
79
|
+
extensions: h["extensions"]&.map { |v| ToolComponent.from_hash(v) } || [],
|
|
80
|
+
policies: h["policies"]&.map { |v| ToolComponent.from_hash(v) } || [],
|
|
81
|
+
translations: h["translations"]&.map { |v| ToolComponent.from_hash(v) } || [],
|
|
82
|
+
addresses: h["addresses"]&.map { |v| Address.from_hash(v) } || [],
|
|
83
|
+
web_requests: h["webRequests"]&.map { |v| WebRequest.from_hash(v) } || [],
|
|
84
|
+
web_responses: h["webResponses"]&.map { |v| WebResponse.from_hash(v) } || [],
|
|
85
|
+
properties: h["properties"]
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def ==(other)
|
|
90
|
+
return false unless other.is_a?(ExternalProperties)
|
|
91
|
+
@schema == other.schema && @version == other.version && @guid == other.guid && @run_guid == other.run_guid && @conversion == other.conversion && @graphs == other.graphs && @externalized_properties == other.externalized_properties && @artifacts == other.artifacts && @invocations == other.invocations && @logical_locations == other.logical_locations && @thread_flow_locations == other.thread_flow_locations && @results == other.results && @taxonomies == other.taxonomies && @driver == other.driver && @extensions == other.extensions && @policies == other.policies && @translations == other.translations && @addresses == other.addresses && @web_requests == other.web_requests && @web_responses == other.web_responses && @properties == other.properties
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
alias eql? ==
|
|
95
|
+
|
|
96
|
+
def hash
|
|
97
|
+
[@schema, @version, @guid, @run_guid, @conversion, @graphs, @externalized_properties, @artifacts, @invocations, @logical_locations, @thread_flow_locations, @results, @taxonomies, @driver, @extensions, @policies, @translations, @addresses, @web_requests, @web_responses, @properties].hash
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# 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.
|
|
5
|
+
class ExternalPropertyFileReference
|
|
6
|
+
attr_accessor :location, :guid, :item_count, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(location: nil, guid: nil, item_count: -1, properties: nil)
|
|
9
|
+
@location = location
|
|
10
|
+
@guid = guid
|
|
11
|
+
@item_count = item_count
|
|
12
|
+
@properties = properties
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
h = {}
|
|
17
|
+
h["location"] = @location&.to_h unless @location.nil?
|
|
18
|
+
h["guid"] = @guid unless @guid.nil?
|
|
19
|
+
h["itemCount"] = @item_count if @item_count && @item_count != -1
|
|
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
|
+
location: ArtifactLocation.from_hash(h["location"]),
|
|
32
|
+
guid: h["guid"],
|
|
33
|
+
item_count: h["itemCount"] || -1,
|
|
34
|
+
properties: h["properties"]
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ==(other)
|
|
39
|
+
return false unless other.is_a?(ExternalPropertyFileReference)
|
|
40
|
+
@location == other.location && @guid == other.guid && @item_count == other.item_count && @properties == other.properties
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
alias eql? ==
|
|
44
|
+
|
|
45
|
+
def hash
|
|
46
|
+
[@location, @guid, @item_count, @properties].hash
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# References to external property files that should be inlined with the content of a root log file.
|
|
5
|
+
class ExternalPropertyFileReferences
|
|
6
|
+
attr_accessor :conversion, :graphs, :externalized_properties, :artifacts, :invocations, :logical_locations, :thread_flow_locations, :results, :taxonomies, :addresses, :driver, :extensions, :policies, :translations, :web_requests, :web_responses, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(conversion: nil, graphs: [], externalized_properties: nil, artifacts: [], invocations: [], logical_locations: [], thread_flow_locations: [], results: [], taxonomies: [], addresses: [], driver: nil, extensions: [], policies: [], translations: [], web_requests: [], web_responses: [], properties: nil)
|
|
9
|
+
@conversion = conversion
|
|
10
|
+
@graphs = graphs
|
|
11
|
+
@externalized_properties = externalized_properties
|
|
12
|
+
@artifacts = artifacts
|
|
13
|
+
@invocations = invocations
|
|
14
|
+
@logical_locations = logical_locations
|
|
15
|
+
@thread_flow_locations = thread_flow_locations
|
|
16
|
+
@results = results
|
|
17
|
+
@taxonomies = taxonomies
|
|
18
|
+
@addresses = addresses
|
|
19
|
+
@driver = driver
|
|
20
|
+
@extensions = extensions
|
|
21
|
+
@policies = policies
|
|
22
|
+
@translations = translations
|
|
23
|
+
@web_requests = web_requests
|
|
24
|
+
@web_responses = web_responses
|
|
25
|
+
@properties = properties
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def to_h
|
|
29
|
+
h = {}
|
|
30
|
+
h["conversion"] = @conversion&.to_h unless @conversion.nil?
|
|
31
|
+
h["graphs"] = @graphs&.map(&:to_h) if @graphs&.any?
|
|
32
|
+
h["externalizedProperties"] = @externalized_properties&.to_h unless @externalized_properties.nil?
|
|
33
|
+
h["artifacts"] = @artifacts&.map(&:to_h) if @artifacts&.any?
|
|
34
|
+
h["invocations"] = @invocations&.map(&:to_h) if @invocations&.any?
|
|
35
|
+
h["logicalLocations"] = @logical_locations&.map(&:to_h) if @logical_locations&.any?
|
|
36
|
+
h["threadFlowLocations"] = @thread_flow_locations&.map(&:to_h) if @thread_flow_locations&.any?
|
|
37
|
+
h["results"] = @results&.map(&:to_h) if @results&.any?
|
|
38
|
+
h["taxonomies"] = @taxonomies&.map(&:to_h) if @taxonomies&.any?
|
|
39
|
+
h["addresses"] = @addresses&.map(&:to_h) if @addresses&.any?
|
|
40
|
+
h["driver"] = @driver&.to_h unless @driver.nil?
|
|
41
|
+
h["extensions"] = @extensions&.map(&:to_h) if @extensions&.any?
|
|
42
|
+
h["policies"] = @policies&.map(&:to_h) if @policies&.any?
|
|
43
|
+
h["translations"] = @translations&.map(&:to_h) if @translations&.any?
|
|
44
|
+
h["webRequests"] = @web_requests&.map(&:to_h) if @web_requests&.any?
|
|
45
|
+
h["webResponses"] = @web_responses&.map(&:to_h) if @web_responses&.any?
|
|
46
|
+
h["properties"] = @properties unless @properties.nil?
|
|
47
|
+
h
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def to_json(pretty: false)
|
|
51
|
+
pretty ? JSON.pretty_generate(to_h) : JSON.generate(to_h)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.from_hash(h)
|
|
55
|
+
return nil if h.nil?
|
|
56
|
+
new(
|
|
57
|
+
conversion: ExternalPropertyFileReference.from_hash(h["conversion"]),
|
|
58
|
+
graphs: h["graphs"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
59
|
+
externalized_properties: ExternalPropertyFileReference.from_hash(h["externalizedProperties"]),
|
|
60
|
+
artifacts: h["artifacts"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
61
|
+
invocations: h["invocations"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
62
|
+
logical_locations: h["logicalLocations"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
63
|
+
thread_flow_locations: h["threadFlowLocations"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
64
|
+
results: h["results"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
65
|
+
taxonomies: h["taxonomies"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
66
|
+
addresses: h["addresses"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
67
|
+
driver: ExternalPropertyFileReference.from_hash(h["driver"]),
|
|
68
|
+
extensions: h["extensions"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
69
|
+
policies: h["policies"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
70
|
+
translations: h["translations"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
71
|
+
web_requests: h["webRequests"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
72
|
+
web_responses: h["webResponses"]&.map { |v| ExternalPropertyFileReference.from_hash(v) } || [],
|
|
73
|
+
properties: h["properties"]
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def ==(other)
|
|
78
|
+
return false unless other.is_a?(ExternalPropertyFileReferences)
|
|
79
|
+
@conversion == other.conversion && @graphs == other.graphs && @externalized_properties == other.externalized_properties && @artifacts == other.artifacts && @invocations == other.invocations && @logical_locations == other.logical_locations && @thread_flow_locations == other.thread_flow_locations && @results == other.results && @taxonomies == other.taxonomies && @addresses == other.addresses && @driver == other.driver && @extensions == other.extensions && @policies == other.policies && @translations == other.translations && @web_requests == other.web_requests && @web_responses == other.web_responses && @properties == other.properties
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
alias eql? ==
|
|
83
|
+
|
|
84
|
+
def hash
|
|
85
|
+
[@conversion, @graphs, @externalized_properties, @artifacts, @invocations, @logical_locations, @thread_flow_locations, @results, @taxonomies, @addresses, @driver, @extensions, @policies, @translations, @web_requests, @web_responses, @properties].hash
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
data/lib/sarif/fix.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# 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.
|
|
5
|
+
class Fix
|
|
6
|
+
attr_accessor :description, :artifact_changes, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(description: nil, artifact_changes:, properties: nil)
|
|
9
|
+
@description = description
|
|
10
|
+
@artifact_changes = artifact_changes
|
|
11
|
+
@properties = properties
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def to_h
|
|
15
|
+
h = {}
|
|
16
|
+
h["description"] = @description&.to_h unless @description.nil?
|
|
17
|
+
h["artifactChanges"] = @artifact_changes&.map(&:to_h)
|
|
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
|
+
description: Message.from_hash(h["description"]),
|
|
30
|
+
artifact_changes: h["artifactChanges"]&.map { |v| ArtifactChange.from_hash(v) },
|
|
31
|
+
properties: h["properties"]
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def ==(other)
|
|
36
|
+
return false unless other.is_a?(Fix)
|
|
37
|
+
@description == other.description && @artifact_changes == other.artifact_changes && @properties == other.properties
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
alias eql? ==
|
|
41
|
+
|
|
42
|
+
def hash
|
|
43
|
+
[@description, @artifact_changes, @properties].hash
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/sarif/graph.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# A network of nodes and directed edges that describes some aspect of the structure of the code (for example, a call graph).
|
|
5
|
+
class Graph
|
|
6
|
+
attr_accessor :description, :nodes, :edges, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(description: nil, nodes: [], edges: [], properties: nil)
|
|
9
|
+
@description = description
|
|
10
|
+
@nodes = nodes
|
|
11
|
+
@edges = edges
|
|
12
|
+
@properties = properties
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_h
|
|
16
|
+
h = {}
|
|
17
|
+
h["description"] = @description&.to_h unless @description.nil?
|
|
18
|
+
h["nodes"] = @nodes&.map(&:to_h) if @nodes&.any?
|
|
19
|
+
h["edges"] = @edges&.map(&:to_h) if @edges&.any?
|
|
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
|
+
description: Message.from_hash(h["description"]),
|
|
32
|
+
nodes: h["nodes"]&.map { |v| Node.from_hash(v) } || [],
|
|
33
|
+
edges: h["edges"]&.map { |v| Edge.from_hash(v) } || [],
|
|
34
|
+
properties: h["properties"]
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def ==(other)
|
|
39
|
+
return false unless other.is_a?(Graph)
|
|
40
|
+
@description == other.description && @nodes == other.nodes && @edges == other.edges && @properties == other.properties
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
alias eql? ==
|
|
44
|
+
|
|
45
|
+
def hash
|
|
46
|
+
[@description, @nodes, @edges, @properties].hash
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Sarif
|
|
4
|
+
# Represents a path through a graph.
|
|
5
|
+
class GraphTraversal
|
|
6
|
+
attr_accessor :run_graph_index, :result_graph_index, :description, :initial_state, :immutable_state, :edge_traversals, :properties
|
|
7
|
+
|
|
8
|
+
def initialize(run_graph_index: -1, result_graph_index: -1, description: nil, initial_state: nil, immutable_state: nil, edge_traversals: [], properties: nil)
|
|
9
|
+
@run_graph_index = run_graph_index
|
|
10
|
+
@result_graph_index = result_graph_index
|
|
11
|
+
@description = description
|
|
12
|
+
@initial_state = initial_state
|
|
13
|
+
@immutable_state = immutable_state
|
|
14
|
+
@edge_traversals = edge_traversals
|
|
15
|
+
@properties = properties
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_h
|
|
19
|
+
h = {}
|
|
20
|
+
h["runGraphIndex"] = @run_graph_index if @run_graph_index && @run_graph_index != -1
|
|
21
|
+
h["resultGraphIndex"] = @result_graph_index if @result_graph_index && @result_graph_index != -1
|
|
22
|
+
h["description"] = @description&.to_h unless @description.nil?
|
|
23
|
+
h["initialState"] = @initial_state unless @initial_state.nil?
|
|
24
|
+
h["immutableState"] = @immutable_state unless @immutable_state.nil?
|
|
25
|
+
h["edgeTraversals"] = @edge_traversals&.map(&:to_h) if @edge_traversals&.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
|
+
run_graph_index: h["runGraphIndex"] || -1,
|
|
38
|
+
result_graph_index: h["resultGraphIndex"] || -1,
|
|
39
|
+
description: Message.from_hash(h["description"]),
|
|
40
|
+
initial_state: h["initialState"],
|
|
41
|
+
immutable_state: h["immutableState"],
|
|
42
|
+
edge_traversals: h["edgeTraversals"]&.map { |v| EdgeTraversal.from_hash(v) } || [],
|
|
43
|
+
properties: h["properties"]
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def ==(other)
|
|
48
|
+
return false unless other.is_a?(GraphTraversal)
|
|
49
|
+
@run_graph_index == other.run_graph_index && @result_graph_index == other.result_graph_index && @description == other.description && @initial_state == other.initial_state && @immutable_state == other.immutable_state && @edge_traversals == other.edge_traversals && @properties == other.properties
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
alias eql? ==
|
|
53
|
+
|
|
54
|
+
def hash
|
|
55
|
+
[@run_graph_index, @result_graph_index, @description, @initial_state, @immutable_state, @edge_traversals, @properties].hash
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|