From 6c4cc7db8d26cfb281083c5e51ccafd29ba5aebf Mon Sep 17 00:00:00 2001 From: Geoffrey Borough <105998328+gborough@users.noreply.github.com> Date: Mon, 29 Jan 2024 08:29:32 +1100 Subject: [PATCH] release 0.3.0 --- .ocamlformat | 2 + CHANGES | 13 +- lib/dune | 29 +- lib/sarif_v_2_1_0_util.ml | 537 ++++++++++++++++++++++---------------- test/dune | 14 +- test/malformed.ml | 55 +++- test/test_sarif.ml | 183 +++++++++---- 7 files changed, 536 insertions(+), 297 deletions(-) create mode 100644 .ocamlformat diff --git a/.ocamlformat b/.ocamlformat new file mode 100644 index 0000000..aa5495a --- /dev/null +++ b/.ocamlformat @@ -0,0 +1,2 @@ +profile = janestreet +version = 0.26.1 \ No newline at end of file diff --git a/CHANGES b/CHANGES index 1e93c42..6ae4662 100644 --- a/CHANGES +++ b/CHANGES @@ -13,4 +13,15 @@ ## 0.2.1 (2024-01-24) ### Removed -* Removed core and re2 dependencies \ No newline at end of file +* Removed core and re2 dependencies + +## 0.2.1 (2024-01-29) + +### Added +* Added ocamlformat rules + +### Removed +* Removed unnecessary ord derive on all types + +### Fixed +* Fixed PropertyBag signature from (string * string) list -> (string * abstract) list to cover JSON value cases \ No newline at end of file diff --git a/lib/dune b/lib/dune index bc5151f..8e63b26 100644 --- a/lib/dune +++ b/lib/dune @@ -2,25 +2,32 @@ (public_name sarif) (name sarif) (libraries timedesc atdgen-runtime re uri) - (preprocess (pps ppx_deriving.show ppx_deriving.ord ppx_deriving.eq)) - (flags :standard -w -30)) + (preprocess + (pps ppx_deriving.show ppx_deriving.ord ppx_deriving.eq)) + (flags :standard -w -30)) (include_subdirs unqualified) (rule (targets sarif_v_2_1_0_t.ml sarif_v_2_1_0_t.mli) - (deps sarif_v_2_1_0.atd) - (mode (promote (until-clean))) - (action (run atdgen -t %{deps}))) + (deps sarif_v_2_1_0.atd) + (mode + (promote (until-clean))) + (action + (run atdgen -t %{deps}))) (rule (targets sarif_v_2_1_0_j.ml sarif_v_2_1_0_j.mli) - (deps sarif_v_2_1_0.atd) - (mode (promote (until-clean))) - (action (run atdgen -j -j-std %{deps}))) + (deps sarif_v_2_1_0.atd) + (mode + (promote (until-clean))) + (action + (run atdgen -j -j-std %{deps}))) (rule (targets sarif_v_2_1_0_v.ml sarif_v_2_1_0_v.mli) - (deps sarif_v_2_1_0.atd) - (mode (promote (until-clean))) - (action (run atdgen -v %{deps}))) + (deps sarif_v_2_1_0.atd) + (mode + (promote (until-clean))) + (action + (run atdgen -v %{deps}))) diff --git a/lib/sarif_v_2_1_0_util.ml b/lib/sarif_v_2_1_0_util.ml index 9156bb0..84884e1 100644 --- a/lib/sarif_v_2_1_0_util.ml +++ b/lib/sarif_v_2_1_0_util.ml @@ -1,454 +1,537 @@ (** Validation functions used by atdgen validator *) open Timedesc - open Sarif_v_2_1_0_t let validate_iso8601_opt = function | None -> true - | Some v -> match of_iso8601 v with - | Ok _ -> true - | Error _ -> false - -let re_mime_type = - Re.Str.regexp "^[^/]+/.+$" - -let validate_mime_type x = - Re.Str.string_match re_mime_type x 0 - -let validate_mime_type_opt x = - Option.fold ~none:true ~some:validate_mime_type x + | Some v -> + (match of_iso8601 v with + | Ok _ -> true + | Error _ -> false) +;; -let validate_int64_minimum_zero x = if (Int64.compare x (-1L)) > 0 then true else false +let re_mime_type = Re.Str.regexp "^[^/]+/.+$" +let validate_mime_type x = Re.Str.string_match re_mime_type x 0 +let validate_mime_type_opt x = Option.fold ~none:true ~some:validate_mime_type x +let validate_int64_minimum_zero x = if Int64.compare x (-1L) > 0 then true else false let validate_int64_minimum_zero_opt = function | None -> true - | Some v -> if (Int64.compare v (-1L)) > 0 then true else false + | Some v -> if Int64.compare v (-1L) > 0 then true else false +;; -let validate_int64_minimum_one x = if (Int64.compare x (0L)) > 0 then true else false +let validate_int64_minimum_one x = if Int64.compare x 0L > 0 then true else false let validate_int64_minimum_one_opt = function | None -> true - | Some v -> if (Int64.compare v (0L)) > 0 then true else false + | Some v -> if Int64.compare v 0L > 0 then true else false +;; -let validate_int64_minimum_minus_one x = - if (Int64.compare x (-2L)) > 0 then true else false +let validate_int64_minimum_minus_one x = if Int64.compare x (-2L) > 0 then true else false let re_guid = - Re.Str.regexp "^[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}$" - -let validate_guid x = - Re.Str.string_match re_guid x 0 - -let validate_guid_opt o = - Option.fold o ~none:true ~some:validate_guid - -let re_dotted_quad_file = - Re.Str.regexp "^[0-9]+(\\\\.[0-9]+){3}$" + Re.Str.regexp + "^[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}$" +;; -let validate_dotted_quad_file_v x = - Re.Str.string_match re_dotted_quad_file x 0 +let validate_guid x = Re.Str.string_match re_guid x 0 +let validate_guid_opt o = Option.fold o ~none:true ~some:validate_guid +let re_dotted_quad_file = Re.Str.regexp "^[0-9]+(\\\\.[0-9]+){3}$" +let validate_dotted_quad_file_v x = Re.Str.string_match re_dotted_quad_file x 0 let validate_dotted_quad_file_v_opt o = Option.fold o ~none:true ~some:validate_dotted_quad_file_v +;; -let re_language = - Re.Str.regexp "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$" - -let validate_language x = - Re.Str.string_match re_language x 0 - -let validate_language_opt x = - Option.fold x ~none:true ~some:validate_language +let re_language = Re.Str.regexp "^[a-zA-Z]{2}(-[a-zA-Z]{2})?$" +let validate_language x = Re.Str.string_match re_language x 0 +let validate_language_opt x = Option.fold x ~none:true ~some:validate_language let validate_unique = function | [] -> true | cur :: rem -> let rec loop cur rem = - not (List.mem cur rem) && + (not (List.mem cur rem)) + && match rem with | [] -> true | cur :: rem -> loop cur rem in loop cur rem +;; -let validate_unique_opt xs_opt = - Option.fold ~none:true ~some:validate_unique xs_opt +let validate_unique_opt xs_opt = Option.fold ~none:true ~some:validate_unique xs_opt let validate_rank x = - if (Int64.compare x (-2L)) > 0 && (Int64.compare x (101L)) < 0 then true else false + if Int64.compare x (-2L) > 0 && Int64.compare x 101L < 0 then true else false +;; let validate_uri x = match Uri.of_string x |> Uri.Absolute_http.of_uri with | Ok _ -> true | Error _ -> false +;; let validate_uri_opt = function | None -> true - | Some v -> match Uri.of_string v |> Uri.Absolute_http.of_uri with - | Ok _ -> true - | Error _ -> false + | Some v -> + (match Uri.of_string v |> Uri.Absolute_http.of_uri with + | Ok _ -> true + | Error _ -> false) +;; -let validate_list_min_size_one x = if (Int.compare (List.length x) 1) > 0 then true else false +let validate_list_min_size_one x = + if Int.compare (List.length x) 1 > 0 then true else false +;; let validate_list_all_str_list (lst : string list option) pred = match lst with | None -> true | Some v -> List.for_all pred v +;; -let validate_list_all_deprecated_guid_list (lst : reporting_descriptor_deprecated_guids_item list option) pred = - match lst with - | None -> true - | Some v -> List.for_all pred v +let validate_list_all_deprecated_guid_list + (lst : reporting_descriptor_deprecated_guids_item list option) + pred + = + match lst with + | None -> true + | Some v -> List.for_all pred v +;; (** Validator for type address *) let validate_address (address : address) = - validate_int64_minimum_minus_one address.absolute_address && - validate_int64_minimum_minus_one address.index && - validate_int64_minimum_minus_one address.parent_index + validate_int64_minimum_minus_one address.absolute_address + && validate_int64_minimum_minus_one address.index + && validate_int64_minimum_minus_one address.parent_index +;; (** Validator for type artifact *) let validate_artifact (artifact : artifact) = - validate_iso8601_opt artifact.last_modified_time_utc && - validate_int64_minimum_minus_one artifact.length && - validate_mime_type_opt artifact.mime_type && - validate_int64_minimum_zero_opt artifact.offset && - validate_int64_minimum_minus_one artifact.parent_index && - validate_unique_opt artifact.roles + validate_iso8601_opt artifact.last_modified_time_utc + && validate_int64_minimum_minus_one artifact.length + && validate_mime_type_opt artifact.mime_type + && validate_int64_minimum_zero_opt artifact.offset + && validate_int64_minimum_minus_one artifact.parent_index + && validate_unique_opt artifact.roles +;; (** Validator for type artifact_location *) let validate_artifact_location (artifact_location : artifact_location) = - validate_int64_minimum_minus_one artifact_location.index && - validate_uri_opt artifact_location.uri + validate_int64_minimum_minus_one artifact_location.index + && validate_uri_opt artifact_location.uri +;; (** Validator for type artifact_mimetype *) let validate_artifact_mimetype (artifact_mimetype : artifact_mimetype) = validate_mime_type artifact_mimetype +;; (** Validator for type attachment *) let validate_attachment (attachment : attachment) = - validate_unique_opt attachment.rectangles && - validate_unique_opt attachment.regions + validate_unique_opt attachment.rectangles && validate_unique_opt attachment.regions +;; (** Validator for type conversion *) let validate_conversion (conversion : conversion) = validate_unique_opt conversion.analysis_tool_log_files +;; (** Validator for type external_properties *) -let validate_external_properties (external_properties : external_properties ) = - validate_unique_opt external_properties.artifacts && - validate_unique_opt external_properties.extensions && - validate_unique_opt external_properties.graph && - validate_guid_opt external_properties.guid && - validate_unique_opt external_properties.logical_locations && - validate_unique_opt external_properties.policies && - validate_guid_opt external_properties.run_guid && - validate_unique_opt external_properties.taxonomies && - validate_unique_opt external_properties.thread_flow_locations && - validate_unique_opt external_properties.translations && - validate_unique_opt external_properties.web_requests && - validate_unique_opt external_properties.web_responses +let validate_external_properties (external_properties : external_properties) = + validate_unique_opt external_properties.artifacts + && validate_unique_opt external_properties.extensions + && validate_unique_opt external_properties.graph + && validate_guid_opt external_properties.guid + && validate_unique_opt external_properties.logical_locations + && validate_unique_opt external_properties.policies + && validate_guid_opt external_properties.run_guid + && validate_unique_opt external_properties.taxonomies + && validate_unique_opt external_properties.thread_flow_locations + && validate_unique_opt external_properties.translations + && validate_unique_opt external_properties.web_requests + && validate_unique_opt external_properties.web_responses +;; (** Validator for type external_properties_guid *) -let validate_external_properties_guid (external_properties_guid : external_properties_guid) = +let validate_external_properties_guid + (external_properties_guid : external_properties_guid) + = validate_guid external_properties_guid +;; (** Validator for type edge_traversal *) let validate_edge_traversal (edge_traversal : edge_traversal) = validate_int64_minimum_zero_opt edge_traversal.step_over_edge_count +;; (** Validator for type external_properties_run_guid *) -let validate_external_properties_run_guid (external_properties_run_guid : external_properties_run_guid) = +let validate_external_properties_run_guid + (external_properties_run_guid : external_properties_run_guid) + = validate_guid external_properties_run_guid +;; (** Validator for type external_property_file_references *) -let validate_external_property_file_references (external_property_file_references : external_property_file_references) = - validate_unique_opt external_property_file_references.addresses && - validate_unique_opt external_property_file_references.artifacts && - validate_unique_opt external_property_file_references.extensions && - validate_unique_opt external_property_file_references.graphs && - validate_unique_opt external_property_file_references.invocations && - validate_unique_opt external_property_file_references.logical_locations && - validate_unique_opt external_property_file_references.policies && - validate_unique_opt external_property_file_references.results && - validate_unique_opt external_property_file_references.taxonomies && - validate_unique_opt external_property_file_references.thread_flow_locations && - validate_unique_opt external_property_file_references.translations && - validate_unique_opt external_property_file_references.web_requests && - validate_unique_opt external_property_file_references.web_responses +let validate_external_property_file_references + (external_property_file_references : external_property_file_references) + = + validate_unique_opt external_property_file_references.addresses + && validate_unique_opt external_property_file_references.artifacts + && validate_unique_opt external_property_file_references.extensions + && validate_unique_opt external_property_file_references.graphs + && validate_unique_opt external_property_file_references.invocations + && validate_unique_opt external_property_file_references.logical_locations + && validate_unique_opt external_property_file_references.policies + && validate_unique_opt external_property_file_references.results + && validate_unique_opt external_property_file_references.taxonomies + && validate_unique_opt external_property_file_references.thread_flow_locations + && validate_unique_opt external_property_file_references.translations + && validate_unique_opt external_property_file_references.web_requests + && validate_unique_opt external_property_file_references.web_responses +;; (** Validator for type external_property_file_reference *) -let validate_external_property_file_reference (external_property_file_reference : external_property_file_reference) = - validate_guid_opt external_property_file_reference.guid && - validate_int64_minimum_minus_one external_property_file_reference.item_count +let validate_external_property_file_reference + (external_property_file_reference : external_property_file_reference) + = + validate_guid_opt external_property_file_reference.guid + && validate_int64_minimum_minus_one external_property_file_reference.item_count +;; (** Validator for type external_property_file_reference_guid *) -let validate_external_property_file_reference_guid (external_property_file_reference_guid : external_property_file_reference_guid) = +let validate_external_property_file_reference_guid + (external_property_file_reference_guid : external_property_file_reference_guid) + = validate_guid external_property_file_reference_guid +;; (** Validator for type fix *) let validate_fix (fix : fix) = - validate_list_min_size_one fix.artifact_changes && - validate_unique fix.artifact_changes + validate_list_min_size_one fix.artifact_changes && validate_unique fix.artifact_changes +;; (** Validator for type graph *) let validate_graph (graph : graph) = - validate_unique_opt graph.edges && - validate_unique_opt graph.nodes + validate_unique_opt graph.edges && validate_unique_opt graph.nodes +;; (** Validator for type graph_traversal_variant0 *) -let validate_graph_traversal_variant0 (graph_traversal_variant0 : graph_traversal_variant0) = - validate_unique_opt graph_traversal_variant0.edge_traversals && - validate_int64_minimum_minus_one graph_traversal_variant0.result_graph_index&& - validate_int64_minimum_minus_one graph_traversal_variant0.run_graph_index +let validate_graph_traversal_variant0 + (graph_traversal_variant0 : graph_traversal_variant0) + = + validate_unique_opt graph_traversal_variant0.edge_traversals + && validate_int64_minimum_minus_one graph_traversal_variant0.result_graph_index + && validate_int64_minimum_minus_one graph_traversal_variant0.run_graph_index +;; (** Validator for type graph_traversal_variant1 *) -let validate_graph_traversal_variant1 (graph_traversal_variant1 : graph_traversal_variant1) = - validate_unique_opt graph_traversal_variant1.edge_traversals && - validate_int64_minimum_minus_one graph_traversal_variant1.result_graph_index && - validate_int64_minimum_minus_one graph_traversal_variant1.run_graph_index +let validate_graph_traversal_variant1 + (graph_traversal_variant1 : graph_traversal_variant1) + = + validate_unique_opt graph_traversal_variant1.edge_traversals + && validate_int64_minimum_minus_one graph_traversal_variant1.result_graph_index + && validate_int64_minimum_minus_one graph_traversal_variant1.run_graph_index +;; (** Validator for type invocation *) let validate_invocation (invocation : invocation) = - validate_iso8601_opt invocation.end_time_utc && - validate_unique_opt invocation.notification_configuration_overrides && - validate_unique_opt invocation.response_files && - validate_unique_opt invocation.rule_configuration_overrides && - validate_iso8601_opt invocation.start_time_utc + validate_iso8601_opt invocation.end_time_utc + && validate_unique_opt invocation.notification_configuration_overrides + && validate_unique_opt invocation.response_files + && validate_unique_opt invocation.rule_configuration_overrides + && validate_iso8601_opt invocation.start_time_utc +;; (** Validator for type location *) let validate_location (location : location) = - validate_unique_opt location.annotations && - validate_int64_minimum_minus_one location.id && - validate_unique_opt location.logical_locations && - validate_unique_opt location.relationships + validate_unique_opt location.annotations + && validate_int64_minimum_minus_one location.id + && validate_unique_opt location.logical_locations + && validate_unique_opt location.relationships +;; (** Validator for type location_relationship *) let validate_location_relationship (location_relationship : location_relationship) = - validate_unique_opt location_relationship.kinds && - validate_int64_minimum_zero location_relationship.target + validate_unique_opt location_relationship.kinds + && validate_int64_minimum_zero location_relationship.target +;; (** Validator for type logical_location *) let validate_logical_location (logical_location : logical_location) = - validate_int64_minimum_minus_one logical_location.index && - validate_int64_minimum_minus_one logical_location.parent_index + validate_int64_minimum_minus_one logical_location.index + && validate_int64_minimum_minus_one logical_location.parent_index +;; (** Validator for type node *) -let validate_node (node : node) = - validate_unique_opt node.children +let validate_node (node : node) = validate_unique_opt node.children (** Validator for type notification *) let validate_notification (notification : notification) = - validate_unique_opt notification.locations && - validate_iso8601_opt notification.time_utc + validate_unique_opt notification.locations && validate_iso8601_opt notification.time_utc +;; (** Validator for type property_bag *) -let validate_property_bag (property_bag : property_bag) = - validate_unique property_bag +let validate_property_bag (property_bag : property_bag) = validate_unique property_bag (** Validator for type reporting_descriptor *) let validate_reporting_descriptor (reporting_descriptor : reporting_descriptor) = - validate_unique_opt reporting_descriptor.deprecated_guids && - validate_list_all_deprecated_guid_list reporting_descriptor.deprecated_guids validate_guid && - validate_unique_opt reporting_descriptor.deprecated_ids && - validate_unique_opt reporting_descriptor.deprecated_names && - validate_guid_opt reporting_descriptor.guid && - validate_uri_opt reporting_descriptor.help_uri && - validate_unique_opt reporting_descriptor.relationships + validate_unique_opt reporting_descriptor.deprecated_guids + && validate_list_all_deprecated_guid_list + reporting_descriptor.deprecated_guids + validate_guid + && validate_unique_opt reporting_descriptor.deprecated_ids + && validate_unique_opt reporting_descriptor.deprecated_names + && validate_guid_opt reporting_descriptor.guid + && validate_uri_opt reporting_descriptor.help_uri + && validate_unique_opt reporting_descriptor.relationships +;; (** Validator for type reporting_configuration *) let validate_reporting_configuration (reporting_configuration : reporting_configuration) = validate_rank reporting_configuration.rank +;; (** Validator for type reporting_descriptor_deprecated_guids_item *) -let validate_reporting_descriptor_deprecated_guids_item (reporting_descriptor_deprecated_guids_item : reporting_descriptor_deprecated_guids_item) = +let validate_reporting_descriptor_deprecated_guids_item + (reporting_descriptor_deprecated_guids_item : + reporting_descriptor_deprecated_guids_item) + = validate_guid reporting_descriptor_deprecated_guids_item +;; (** Validator for type reporting_descriptor_guid *) -let validate_reporting_descriptor_guid (reporting_descriptor_guid : reporting_descriptor_guid) = +let validate_reporting_descriptor_guid + (reporting_descriptor_guid : reporting_descriptor_guid) + = validate_guid reporting_descriptor_guid +;; (** Validator for type reporting_descriptor_relationship *) -let validate_reporting_descriptor_relationship (reporting_descriptor_relationship : reporting_descriptor_relationship) = +let validate_reporting_descriptor_relationship + (reporting_descriptor_relationship : reporting_descriptor_relationship) + = validate_unique_opt reporting_descriptor_relationship.kinds +;; (** Validator for type reporting_descriptor_reference *) -let validate_reporting_descriptor_reference (reporting_descriptor_reference : reporting_descriptor_reference) = - validate_guid_opt reporting_descriptor_reference.guid && - validate_int64_minimum_minus_one reporting_descriptor_reference.index +let validate_reporting_descriptor_reference + (reporting_descriptor_reference : reporting_descriptor_reference) + = + validate_guid_opt reporting_descriptor_reference.guid + && validate_int64_minimum_minus_one reporting_descriptor_reference.index +;; (** Validator for type reporting_descriptor_reference_guid *) -let validate_reporting_descriptor_reference_guid (reporting_descriptor_reference_guid : reporting_descriptor_reference_guid) = +let validate_reporting_descriptor_reference_guid + (reporting_descriptor_reference_guid : reporting_descriptor_reference_guid) + = validate_guid reporting_descriptor_reference_guid +;; (** Validator for type region *) let validate_region (region : region) = - validate_int64_minimum_zero_opt region.byte_length && - validate_int64_minimum_minus_one region.byte_offset && - validate_int64_minimum_zero_opt region.char_length && - validate_int64_minimum_minus_one region.char_offset && - validate_int64_minimum_one_opt region.end_line && - validate_int64_minimum_one_opt region.start_column && - validate_int64_minimum_one_opt region.start_line + validate_int64_minimum_zero_opt region.byte_length + && validate_int64_minimum_minus_one region.byte_offset + && validate_int64_minimum_zero_opt region.char_length + && validate_int64_minimum_minus_one region.char_offset + && validate_int64_minimum_one_opt region.end_line + && validate_int64_minimum_one_opt region.start_column + && validate_int64_minimum_one_opt region.start_line +;; (** Validator for type result *) let validate_result (result : result) = - validate_unique_opt result.attachments && - validate_guid_opt result.correlation_guid && - validate_unique_opt result.fixes && - validate_unique_opt result.graph_traversals && - validate_unique_opt result.graphs && - validate_guid_opt result.guid && - validate_uri_opt result.hosted_viewer_uri && - validate_int64_minimum_one_opt result.occurrence_count && - validate_rank result.rank && - validate_unique_opt result.related_locations && - validate_int64_minimum_minus_one result.rule_index && - validate_unique_opt result.stacks && - validate_unique_opt result.suppressions && - validate_unique_opt result.taxa && - validate_unique_opt result.work_item_uris && - validate_list_all_str_list result.work_item_uris validate_uri + validate_unique_opt result.attachments + && validate_guid_opt result.correlation_guid + && validate_unique_opt result.fixes + && validate_unique_opt result.graph_traversals + && validate_unique_opt result.graphs + && validate_guid_opt result.guid + && validate_uri_opt result.hosted_viewer_uri + && validate_int64_minimum_one_opt result.occurrence_count + && validate_rank result.rank + && validate_unique_opt result.related_locations + && validate_int64_minimum_minus_one result.rule_index + && validate_unique_opt result.stacks + && validate_unique_opt result.suppressions + && validate_unique_opt result.taxa + && validate_unique_opt result.work_item_uris + && validate_list_all_str_list result.work_item_uris validate_uri +;; (** Validator for type result_correlation_guid *) let validate_result_correlation_guid (result_correlation_guid : result_correlation_guid) = validate_guid result_correlation_guid +;; (** Validator for type result_guid *) -let validate_result_guid (result_guid : result_guid) = - validate_guid result_guid +let validate_result_guid (result_guid : result_guid) = validate_guid result_guid (** Validator for type result_provenance *) let validate_result_provenance (result_provenance : result_provenance) = - validate_unique_opt result_provenance.conversion_sources && - validate_guid_opt result_provenance.first_detection_run_guid && - validate_iso8601_opt result_provenance.first_detection_time_utc && - validate_int64_minimum_minus_one result_provenance.invocation_index && - validate_guid_opt result_provenance.last_detection_run_guid && - validate_iso8601_opt result_provenance.last_detection_time_utc + validate_unique_opt result_provenance.conversion_sources + && validate_guid_opt result_provenance.first_detection_run_guid + && validate_iso8601_opt result_provenance.first_detection_time_utc + && validate_int64_minimum_minus_one result_provenance.invocation_index + && validate_guid_opt result_provenance.last_detection_run_guid + && validate_iso8601_opt result_provenance.last_detection_time_utc +;; (** Validator for type result_provenance_first_detection_run_guid *) -let validate_result_provenance_first_detection_run_guid (result_provenance_first_detection_run_guid : result_provenance_first_detection_run_guid) = +let validate_result_provenance_first_detection_run_guid + (result_provenance_first_detection_run_guid : + result_provenance_first_detection_run_guid) + = validate_guid result_provenance_first_detection_run_guid +;; (** Validator for type result_provenance_last_detection_run_guid *) -let validate_result_provenance_last_detection_run_guid (result_provenance_last_detection_run_guid : result_provenance_last_detection_run_guid) = +let validate_result_provenance_last_detection_run_guid + (result_provenance_last_detection_run_guid : result_provenance_last_detection_run_guid) + = validate_guid result_provenance_last_detection_run_guid +;; (** Validator for type run *) let validate_run (run : run) = - validate_unique_opt run.artifacts && - validate_guid_opt run.baseline_guid && - validate_unique_opt run.graphs && - validate_language_opt run.language && - validate_unique_opt run.logical_locations && - validate_list_min_size_one run.newline_sequences && - validate_unique run.newline_sequences && - validate_unique_opt run.policies && - validate_unique_opt run.redaction_tokens && - validate_unique_opt run.run_aggregates && - validate_unique_opt run.taxonomies && - validate_unique_opt run.thread_flow_locations && - validate_unique_opt run.translations && - validate_unique_opt run.version_control_provenance && - validate_unique_opt run.web_requests && - validate_unique_opt run.web_responses + validate_unique_opt run.artifacts + && validate_guid_opt run.baseline_guid + && validate_unique_opt run.graphs + && validate_language_opt run.language + && validate_unique_opt run.logical_locations + && validate_list_min_size_one run.newline_sequences + && validate_unique run.newline_sequences + && validate_unique_opt run.policies + && validate_unique_opt run.redaction_tokens + && validate_unique_opt run.run_aggregates + && validate_unique_opt run.taxonomies + && validate_unique_opt run.thread_flow_locations + && validate_unique_opt run.translations + && validate_unique_opt run.version_control_provenance + && validate_unique_opt run.web_requests + && validate_unique_opt run.web_responses +;; (** Validator for type run_automation_details *) let validate_run_automation_details (run_automation_details : run_automation_details) = - validate_guid_opt run_automation_details.correlation_guid && - validate_guid_opt run_automation_details.guid + validate_guid_opt run_automation_details.correlation_guid + && validate_guid_opt run_automation_details.guid +;; (** Validator for type run_language *) -let validate_run_language (run_language : run_language) = - validate_language run_language +let validate_run_language (run_language : run_language) = validate_language run_language (** Validator for type run_automation_details_correlation_guid *) -let validate_run_automation_details_correlation_guid (run_automation_details_correlation_guid : run_automation_details_correlation_guid) = +let validate_run_automation_details_correlation_guid + (run_automation_details_correlation_guid : run_automation_details_correlation_guid) + = validate_guid run_automation_details_correlation_guid +;; (** Validator for type run_automation_details_guid *) -let validate_run_automation_details_guid (run_automation_details_guid : run_automation_details_guid) = +let validate_run_automation_details_guid + (run_automation_details_guid : run_automation_details_guid) + = validate_guid run_automation_details_guid +;; (** Validator for type run_baseline_guid *) let validate_run_baseline_guid (run_baseline_guid : run_baseline_guid) = validate_guid run_baseline_guid +;; (** Validator for type suppression *) -let validate_suppression (suppression : suppression) = - validate_guid_opt suppression.guid +let validate_suppression (suppression : suppression) = validate_guid_opt suppression.guid (** Validator for type suppression_guid *) let validate_suppression_guid (suppression_guid : suppression_guid) = validate_guid suppression_guid +;; (** Validator for type sarif_json_schema *) let validate_sarif_json_schema (sarif_json_schema : sarif_json_schema) = validate_unique_opt sarif_json_schema.inline_external_properties +;; (** Validator for type tool *) -let validate_tool (tool : tool) = - validate_unique_opt tool.extensions +let validate_tool (tool : tool) = validate_unique_opt tool.extensions (** Validator for type tool_component *) let validate_tool_component (tool_component : tool_component) = - validate_unique_opt tool_component.contents && - validate_dotted_quad_file_v_opt tool_component.dotted_quad_file_version && - validate_uri_opt tool_component.download_uri && - validate_guid_opt tool_component.guid && - validate_uri_opt tool_component.information_uri && - validate_language_opt tool_component.language && - validate_unique_opt tool_component.notifications && - validate_unique_opt tool_component.rules && - validate_unique_opt tool_component.supported_taxonomies && - validate_unique_opt tool_component.taxa + validate_unique_opt tool_component.contents + && validate_dotted_quad_file_v_opt tool_component.dotted_quad_file_version + && validate_uri_opt tool_component.download_uri + && validate_guid_opt tool_component.guid + && validate_uri_opt tool_component.information_uri + && validate_language_opt tool_component.language + && validate_unique_opt tool_component.notifications + && validate_unique_opt tool_component.rules + && validate_unique_opt tool_component.supported_taxonomies + && validate_unique_opt tool_component.taxa +;; (** Validator for type thread_flow_location *) let validate_thread_flow_location (thread_flow_location : thread_flow_location) = - validate_int64_minimum_minus_one thread_flow_location.execution_order && - validate_iso8601_opt thread_flow_location.execution_time_utc && - validate_int64_minimum_minus_one thread_flow_location.index && - validate_unique_opt thread_flow_location.kinds && - validate_int64_minimum_zero_opt thread_flow_location.nesting_level && - validate_unique_opt thread_flow_location.taxa + validate_int64_minimum_minus_one thread_flow_location.execution_order + && validate_iso8601_opt thread_flow_location.execution_time_utc + && validate_int64_minimum_minus_one thread_flow_location.index + && validate_unique_opt thread_flow_location.kinds + && validate_int64_minimum_zero_opt thread_flow_location.nesting_level + && validate_unique_opt thread_flow_location.taxa +;; (** Validator for type translation_metadata *) let validate_translation_metadata (translation_metadata : translation_metadata) = - validate_uri_opt translation_metadata.download_uri && - validate_uri_opt translation_metadata.information_uri + validate_uri_opt translation_metadata.download_uri + && validate_uri_opt translation_metadata.information_uri +;; (** Validator for type tool_component_reference *) -let validate_tool_component_reference (tool_component_reference : tool_component_reference) = - validate_guid_opt tool_component_reference.guid && - validate_int64_minimum_minus_one tool_component_reference.index +let validate_tool_component_reference + (tool_component_reference : tool_component_reference) + = + validate_guid_opt tool_component_reference.guid + && validate_int64_minimum_minus_one tool_component_reference.index +;; (** Validator for type tool_component_reference_guid *) -let validate_tool_component_reference_guid (tool_component_reference_guid : tool_component_reference_guid) = +let validate_tool_component_reference_guid + (tool_component_reference_guid : tool_component_reference_guid) + = validate_guid tool_component_reference_guid +;; (** Validator for type tool_component_dotted_quad_file_version *) -let validate_tool_component_dotted_quad_file_version (tool_component_dotted_quad_file_version : tool_component_dotted_quad_file_version) = +let validate_tool_component_dotted_quad_file_version + (tool_component_dotted_quad_file_version : tool_component_dotted_quad_file_version) + = validate_dotted_quad_file_v tool_component_dotted_quad_file_version +;; (** Validator for type tool_component_guid *) let validate_tool_component_guid (tool_component_guid : tool_component_guid) = validate_guid tool_component_guid +;; (** Validator for type tool_component_language *) let validate_tool_component_language (tool_component_language : tool_component_language) = validate_language tool_component_language +;; (** Validator for type version_control_details *) let validate_version_control_details (version_control_details : version_control_details) = - validate_iso8601_opt version_control_details.as_of_time_utc && - validate_uri version_control_details.repository_uri + validate_iso8601_opt version_control_details.as_of_time_utc + && validate_uri version_control_details.repository_uri +;; (** Validator for type web_request *) let validate_web_request (web_request : web_request) = validate_int64_minimum_minus_one web_request.index +;; (** Validator for type web_response *) let validate_web_response (web_response : web_response) = validate_int64_minimum_minus_one web_response.index - +;; diff --git a/test/dune b/test/dune index dde0132..c67a8d2 100644 --- a/test/dune +++ b/test/dune @@ -1,7 +1,15 @@ (library (name test_sarif) - (libraries sarif ppx_expect.common ppx_expect.config ppx_expect.config_types) - (inline_tests (deps (glob_files data/*) (glob_files_rec data/semgrep/*.sarif))) - (preprocess (pps ppx_expect))) + (libraries + sarif + ppx_expect.common + ppx_expect.config + ppx_expect.config_types) + (inline_tests + (deps + (glob_files data/*) + (glob_files_rec data/semgrep/*.sarif))) + (preprocess + (pps ppx_expect))) (include_subdirs unqualified) diff --git a/test/malformed.ml b/test/malformed.ml index 4261228..b1806a0 100644 --- a/test/malformed.ml +++ b/test/malformed.ml @@ -5,83 +5,107 @@ let read_all file = let s = really_input_string ic (in_channel_length ic) in close_in ic; s +;; let%expect_test "malformed_iso8601_date" = let json = read_all "data/malformed.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let artifact = Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 0 in + let artifact = + Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 0 + in let parsed_artifact = Sarif_v_2_1_0_j.artifact_of_string artifact in let res = Sarif_v_2_1_0_util.validate_artifact parsed_artifact in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_mime_type" = let json = read_all "data/malformed.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let artifact = Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 1 in + let artifact = + Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 1 + in let parsed_artifact = Sarif_v_2_1_0_j.artifact_of_string artifact in let res = Sarif_v_2_1_0_util.validate_artifact parsed_artifact in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_minimum_zero" = let json = read_all "data/malformed.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let artifact = Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 2 in + let artifact = + Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 2 + in let parsed_artifact = Sarif_v_2_1_0_j.artifact_of_string artifact in let res = Sarif_v_2_1_0_util.validate_artifact parsed_artifact in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_minimum_one" = let json = read_all "data/malformed.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.nth (Option.get parsed_run.results) 0 in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.nth (Option.get parsed_run.results) 0 + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in let res = Sarif_v_2_1_0_util.validate_result parsed_result in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_minimum_minus_one" = let json = read_all "data/malformed.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let artifact = Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 3 in + let artifact = + Sarif_v_2_1_0_j.string_of_artifact @@ List.nth (Option.get parsed_run.artifacts) 3 + in let parsed_artifact = Sarif_v_2_1_0_j.artifact_of_string artifact in let res = Sarif_v_2_1_0_util.validate_artifact parsed_artifact in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_guid" = let json = read_all "data/malformed.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.nth (Option.get parsed_run.results) 1 in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.nth (Option.get parsed_run.results) 1 + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in let res = Sarif_v_2_1_0_util.validate_result parsed_result in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_dotted_quad_file" = let json = read_all "data/malformed.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let taxonomies = Sarif_v_2_1_0_j.string_of_tool_component @@ List.hd @@ Option.get parsed_run.taxonomies in + let taxonomies = + Sarif_v_2_1_0_j.string_of_tool_component + @@ List.hd + @@ Option.get parsed_run.taxonomies + in let parsed_taxonomies = Sarif_v_2_1_0_j.tool_component_of_string taxonomies in let res = Sarif_v_2_1_0_util.validate_tool_component parsed_taxonomies in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_language" = let json = read_all "data/malformed1.json" in @@ -91,39 +115,49 @@ let%expect_test "malformed_language" = let res = Sarif_v_2_1_0_util.validate_run parsed_run in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_none_unique" = let json = read_all "data/malformed1.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in let res = Sarif_v_2_1_0_util.validate_result parsed_result in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_rank" = let json = read_all "data/malformed2.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in let res = Sarif_v_2_1_0_util.validate_result parsed_result in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_uri" = let json = read_all "data/malformed3.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in let res = Sarif_v_2_1_0_util.validate_result parsed_result in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; let%expect_test "malformed_list_min_size_one" = let json = read_all "data/malformed4.json" in @@ -133,3 +167,4 @@ let%expect_test "malformed_list_min_size_one" = let res = Sarif_v_2_1_0_util.validate_run parsed_run in if res then print_endline "true" else print_endline "false"; [%expect {|false|}] +;; diff --git a/test/test_sarif.ml b/test/test_sarif.ml index af02f9e..56a3732 100644 --- a/test/test_sarif.ml +++ b/test/test_sarif.ml @@ -5,32 +5,52 @@ let read_all file = let s = really_input_string ic (in_channel_length ic) in close_in ic; s +;; let%expect_test "code_flows" = let json = read_all "data/code_flows.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in - let code_flows = Sarif_v_2_1_0_j.string_of_code_flow @@ List.hd @@ Option.get parsed_result.code_flows in + let code_flows = + Sarif_v_2_1_0_j.string_of_code_flow @@ List.hd @@ Option.get parsed_result.code_flows + in print_endline code_flows; - [%expect {| {"message":{"text":"Path from declaration to usage."},"threadFlows":[{"locations":[{"importance":"essential","location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"message":{"text":"Variable 'ptr' declared."},"physicalLocation":{"artifactLocation":{"uri":"collections/list.h"},"region":{"snippet":{"text":"int* ptr;"},"startColumn":8,"startLine":15}}}},{"importance":"unimportant","location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"physicalLocation":{"artifactLocation":{"uri":"collections/list.h"},"region":{"snippet":{"text":"offset = 0;"},"startColumn":8,"startLine":18}}}},{"importance":"essential","location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"message":{"text":"Uninitialized variable 'ptr' passed to method 'add_core'."},"physicalLocation":{"artifactLocation":{"uri":"collections/list.h"},"region":{"snippet":{"text":"add_core(ptr, offset, val)"},"startColumn":8,"startLine":25}}}}]}]} |}] + [%expect + {| {"message":{"text":"Path from declaration to usage."},"threadFlows":[{"locations":[{"importance":"essential","location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"message":{"text":"Variable 'ptr' declared."},"physicalLocation":{"artifactLocation":{"uri":"collections/list.h"},"region":{"snippet":{"text":"int* ptr;"},"startColumn":8,"startLine":15}}}},{"importance":"unimportant","location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"physicalLocation":{"artifactLocation":{"uri":"collections/list.h"},"region":{"snippet":{"text":"offset = 0;"},"startColumn":8,"startLine":18}}}},{"importance":"essential","location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"message":{"text":"Uninitialized variable 'ptr' passed to method 'add_core'."},"physicalLocation":{"artifactLocation":{"uri":"collections/list.h"},"region":{"snippet":{"text":"add_core(ptr, offset, val)"},"startColumn":8,"startLine":25}}}}]}]} |}] +;; let%expect_test "context_region" = let json = read_all "data/context_region.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in - let location = Sarif_v_2_1_0_j.string_of_location @@ List.hd @@ Option.get parsed_result.locations in + let location = + Sarif_v_2_1_0_j.string_of_location @@ List.hd @@ Option.get parsed_result.locations + in let parsed_location = Sarif_v_2_1_0_j.location_of_string location in - let physical_location = Sarif_v_2_1_0_j.string_of_physical_location @@ Option.get parsed_location.physical_location in - let parsed_physical_location = Sarif_v_2_1_0_j.physical_location_of_string physical_location in - let context_region = Sarif_v_2_1_0_j.string_of_region @@ Option.get parsed_physical_location.context_region in + let physical_location = + Sarif_v_2_1_0_j.string_of_physical_location + @@ Option.get parsed_location.physical_location + in + let parsed_physical_location = + Sarif_v_2_1_0_j.physical_location_of_string physical_location + in + let context_region = + Sarif_v_2_1_0_j.string_of_region @@ Option.get parsed_physical_location.context_region + in print_endline context_region; - [%expect {| {"endColumn":28,"snippet":{"text":"/// This is a BAD word."},"startColumn":5,"startLine":4} |}] + [%expect + {| {"endColumn":28,"snippet":{"text":"/// This is a BAD word."},"startColumn":5,"startLine":4} |}] +;; let%expect_test "default_rule_configuration" = let json = read_all "data/default_rule_configuration.json" in @@ -41,29 +61,44 @@ let%expect_test "default_rule_configuration" = let parsed_tool = Sarif_v_2_1_0_j.tool_of_string tool in let driver = Sarif_v_2_1_0_j.string_of_tool_component parsed_tool.driver in let parsed_driver = Sarif_v_2_1_0_j.tool_component_of_string driver in - let rules = Sarif_v_2_1_0_j.string_of_reporting_descriptor @@ List.hd @@ Option.get parsed_driver.rules in + let rules = + Sarif_v_2_1_0_j.string_of_reporting_descriptor + @@ List.hd + @@ Option.get parsed_driver.rules + in print_endline rules; [%expect {| {"defaultConfiguration":{"level":"error"},"id":"TUT0001"} |}] +;; let%expect_test "embedded_binary_content" = let json = read_all "data/embedded_binary_content.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in - let location = Sarif_v_2_1_0_j.string_of_location @@ List.hd @@ Option.get parsed_result.locations in + let location = + Sarif_v_2_1_0_j.string_of_location @@ List.hd @@ Option.get parsed_result.locations + in print_endline location; - [%expect {| {"physicalLocation":{"artifactLocation":{"index":0,"uri":"data.bin"},"region":{"byteLength":2,"byteOffset":2}}} |}] + [%expect + {| {"physicalLocation":{"artifactLocation":{"index":0,"uri":"data.bin"},"region":{"byteLength":2,"byteOffset":2}}} |}] +;; let%expect_test "embedded_text_content" = let json = read_all "data/embedded_text_content.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let artifacts = Sarif_v_2_1_0_j.string_of_artifact @@ List.hd @@ Option.get parsed_run.artifacts in + let artifacts = + Sarif_v_2_1_0_j.string_of_artifact @@ List.hd @@ Option.get parsed_run.artifacts + in print_endline artifacts; - [%expect {| {"contents":{"text":"Hello,\r\nworld"},"encoding":"UTF-8","location":{"uri":"explicit.txt"}} |}] + [%expect + {| {"contents":{"text":"Hello,\r\nworld"},"encoding":"UTF-8","location":{"uri":"explicit.txt"}} |}] +;; let%expect_test "notifications" = let json = read_all "data/notifications.json" in @@ -74,40 +109,62 @@ let%expect_test "notifications" = let parsed_tool = Sarif_v_2_1_0_j.tool_of_string tool in let driver = Sarif_v_2_1_0_j.string_of_tool_component parsed_tool.driver in let parsed_driver = Sarif_v_2_1_0_j.tool_component_of_string driver in - let notifications = Sarif_v_2_1_0_j.string_of_reporting_descriptor @@ List.hd @@ Option.get parsed_driver.notifications in + let notifications = + Sarif_v_2_1_0_j.string_of_reporting_descriptor + @@ List.hd + @@ Option.get parsed_driver.notifications + in print_endline notifications; - [%expect {| {"defaultConfiguration":{"level":"warning"},"id":"TUTN9001","messageStrings":{"disabled":{"text":"'{0}' cannot be disabled because this rule does not exist."},"enabled":{"text":"'{0}' cannot be enabled because this rule does not exist."}},"name":"unknown-rule","shortDescription":{"text":"This notification is triggered when the user supplies a command line argument to enable or disable a rule that does not exist."}} |}] + [%expect + {| {"defaultConfiguration":{"level":"warning"},"id":"TUTN9001","messageStrings":{"disabled":{"text":"'{0}' cannot be disabled because this rule does not exist."},"enabled":{"text":"'{0}' cannot be enabled because this rule does not exist."}},"name":"unknown-rule","shortDescription":{"text":"This notification is triggered when the user supplies a command line argument to enable or disable a rule that does not exist."}} |}] +;; let%expect_test "original_uri_base_ids" = let json = read_all "data/original_uri_base_ids.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let original_uri_base_ids = Sarif_v_2_1_0_j.string_of_hm_str_al @@ Option.get parsed_run.original_uri_base_ids in + let original_uri_base_ids = + Sarif_v_2_1_0_j.string_of_hm_str_al @@ Option.get parsed_run.original_uri_base_ids + in print_endline original_uri_base_ids; - [%expect {| {"REPOROOT":{"description":{"text":"The directory into which the repo was cloned."},"properties":{"comment":"The SARIF producer has chosen not to specify a URI for REPOROOT. See §3.14.14, NOTE 1, for an explanation."}},"SRCROOT":{"description":{"text":"The r."},"properties":{"comment":"SRCROOT is expressed relative to REPOROOT."},"uri":"src/","uriBaseId":"REPOROOT"},"LOGSROOT":{"description":{"text":"Destination for tool logs."},"properties":{"comment":"An originalUriBaseId that resolves directly to an absolute URI."},"uri":"file:///C:/logs/"}} |}] + [%expect + {| {"REPOROOT":{"description":{"text":"The directory into which the repo was cloned."},"properties":{"comment":"The SARIF producer has chosen not to specify a URI for REPOROOT. See §3.14.14, NOTE 1, for an explanation."}},"SRCROOT":{"description":{"text":"The r."},"properties":{"comment":"SRCROOT is expressed relative to REPOROOT."},"uri":"src/","uriBaseId":"REPOROOT"},"LOGSROOT":{"description":{"text":"Destination for tool logs."},"properties":{"comment":"An originalUriBaseId that resolves directly to an absolute URI."},"uri":"file:///C:/logs/"}} |}] +;; let%expect_test "regional_variants" = let json = read_all "data/regional_variants.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in - let location = Sarif_v_2_1_0_j.string_of_location @@ List.hd @@ Option.get parsed_result.locations in + let location = + Sarif_v_2_1_0_j.string_of_location @@ List.hd @@ Option.get parsed_result.locations + in print_endline location; - [%expect {| {"physicalLocation":{"artifactLocation":{"index":0,"uri":"TextFile.txt"},"region":{"endColumn":4,"endLine":1,"startColumn":2,"startLine":1}}} |}] + [%expect + {| {"physicalLocation":{"artifactLocation":{"index":0,"uri":"TextFile.txt"},"region":{"endColumn":4,"endLine":1,"startColumn":2,"startLine":1}}} |}] +;; let%expect_test "result_stacks" = let json = read_all "data/result_stacks.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.hd @@ Option.get parsed_run.results + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in - let stacks = Sarif_v_2_1_0_j.string_of_stack @@ List.hd @@ Option.get parsed_result.stacks in + let stacks = + Sarif_v_2_1_0_j.string_of_stack @@ List.hd @@ Option.get parsed_result.stacks + in print_endline stacks; - [%expect {| {"frames":[{"location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add_core"}],"message":{"text":"Exception thrown."},"physicalLocation":{"artifactLocation":{"uri":"collections/list.h","uriBaseId":"SRCROOT"},"region":{"startColumn":15,"startLine":110}}},"module":"platform","parameters":["null","0","14"],"threadId":52},{"location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"physicalLocation":{"artifactLocation":{"uri":"collections/list.h","uriBaseId":"SRCROOT"},"region":{"startColumn":15,"startLine":43}}},"module":"platform","parameters":["14"],"threadId":52},{"location":{"logicalLocations":[{"fullyQualifiedName":"main"}],"physicalLocation":{"artifactLocation":{"uri":"application/main.cpp","uriBaseId":"SRCROOT"},"region":{"startColumn":9,"startLine":28}}},"module":"application","threadId":52}],"message":{"text":"Call stack resulting from usage of uninitialized variable."}} |}] + [%expect + {| {"frames":[{"location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add_core"}],"message":{"text":"Exception thrown."},"physicalLocation":{"artifactLocation":{"uri":"collections/list.h","uriBaseId":"SRCROOT"},"region":{"startColumn":15,"startLine":110}}},"module":"platform","parameters":["null","0","14"],"threadId":52},{"location":{"logicalLocations":[{"fullyQualifiedName":"collections::list::add"}],"physicalLocation":{"artifactLocation":{"uri":"collections/list.h","uriBaseId":"SRCROOT"},"region":{"startColumn":15,"startLine":43}}},"module":"platform","parameters":["14"],"threadId":52},{"location":{"logicalLocations":[{"fullyQualifiedName":"main"}],"physicalLocation":{"artifactLocation":{"uri":"application/main.cpp","uriBaseId":"SRCROOT"},"region":{"startColumn":9,"startLine":28}}},"module":"application","threadId":52}],"message":{"text":"Call stack resulting from usage of uninitialized variable."}} |}] +;; let%expect_test "rule_metadata" = let json = read_all "data/rule_metadata.json" in @@ -118,91 +175,127 @@ let%expect_test "rule_metadata" = let parsed_tool = Sarif_v_2_1_0_j.tool_of_string tool in let driver = Sarif_v_2_1_0_j.string_of_tool_component parsed_tool.driver in let parsed_driver = Sarif_v_2_1_0_j.tool_component_of_string driver in - let rules = Sarif_v_2_1_0_j.string_of_reporting_descriptor @@ List.hd @@ Option.get parsed_driver.rules in + let rules = + Sarif_v_2_1_0_j.string_of_reporting_descriptor + @@ List.hd + @@ Option.get parsed_driver.rules + in print_endline rules; - [%expect {| {"defaultConfiguration":{"level":"error"},"fullDescription":{"markdown":"Every JSON property whose value is defined by the schema to be a URI (with `\"format\": \"uri\"` or `\"format\": \"uri-reference\"`) must contain a valid URI.","text":"Every JSON property whose value is defined by the schema to be a URI (with \"format\": \"uri\" or \"format\": \"uri-reference\") must contain a valid URI."},"id":"TUT1001","messageStrings":{"default":{"markdown":"The URI `{0}` is invalid.","text":"The URI '{0}' is invalid."}},"name":"InvalidUri","shortDescription":{"markdown":"Properties defined with the `uri` or `uri-reference` format must contain valid URIs.","text":"Properties defined with the 'uri' or 'uri-reference' format must contain valid URIs."}} |}] + [%expect + {| {"defaultConfiguration":{"level":"error"},"fullDescription":{"markdown":"Every JSON property whose value is defined by the schema to be a URI (with `\"format\": \"uri\"` or `\"format\": \"uri-reference\"`) must contain a valid URI.","text":"Every JSON property whose value is defined by the schema to be a URI (with \"format\": \"uri\" or \"format\": \"uri-reference\") must contain a valid URI."},"id":"TUT1001","messageStrings":{"default":{"markdown":"The URI `{0}` is invalid.","text":"The URI '{0}' is invalid."}},"name":"InvalidUri","shortDescription":{"markdown":"Properties defined with the `uri` or `uri-reference` format must contain valid URIs.","text":"Properties defined with the 'uri' or 'uri-reference' format must contain valid URIs."}} |}] +;; let%expect_test "suppresions" = let json = read_all "data/suppresions.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let result = Sarif_v_2_1_0_j.string_of_result @@ List.nth (Option.get parsed_run.results) 1 in + let result = + Sarif_v_2_1_0_j.string_of_result @@ List.nth (Option.get parsed_run.results) 1 + in let parsed_result = Sarif_v_2_1_0_j.result_of_string result in - let suppressions = Sarif_v_2_1_0_j.string_of_suppression @@ List.hd @@ Option.get parsed_result.suppressions in + let suppressions = + Sarif_v_2_1_0_j.string_of_suppression + @@ List.hd + @@ Option.get parsed_result.suppressions + in print_endline suppressions; [%expect {| {"kind":"inSource"} |}] +;; let%expect_test "taxonomies" = let json = read_all "data/taxonomies.json" in let parsed_all = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let run = Sarif_v_2_1_0_j.string_of_run @@ List.hd @@ parsed_all.runs in let parsed_run = Sarif_v_2_1_0_j.run_of_string run in - let taxonomies = Sarif_v_2_1_0_j.string_of_tool_component @@ List.hd @@ Option.get parsed_run.taxonomies in + let taxonomies = + Sarif_v_2_1_0_j.string_of_tool_component + @@ List.hd + @@ Option.get parsed_run.taxonomies + in print_endline taxonomies; - [%expect {| {"guid":"1A567403-868F-405E-92CF-771A9ECB03A1","name":"Requirement levels","shortDescription":{"text":"This taxonomy classifies rules according to whether their use is required or recommended by company policy."},"taxa":[{"id":"RQL1001","name":"Required","shortDescription":{"text":"Rules in this category are required by company policy. All violations must be fixed unless an exemption is granted."}},{"id":"RQL1002","name":"Recommended","shortDescription":{"text":"Rules in this category are recommended but not required by company policy. Violations should be fixed but an exemption is not required to suppress a result."}}]} |}] + [%expect + {| {"guid":"1A567403-868F-405E-92CF-771A9ECB03A1","name":"Requirement levels","shortDescription":{"text":"This taxonomy classifies rules according to whether their use is required or recommended by company policy."},"taxa":[{"id":"RQL1001","name":"Required","shortDescription":{"text":"Rules in this category are required by company policy. All violations must be fixed unless an exemption is granted."}},{"id":"RQL1002","name":"Recommended","shortDescription":{"text":"Rules in this category are recommended but not required by company policy. Violations should be fixed but an exemption is not required to suppress a result."}}]} |}] +;; let%expect_test "sarif_json_schema.version" = let sarif_json_schema = - Sarif_v_2_1_0_v.create_sarif_json_schema - ~version:`TwoDotOneDotZero - ~runs:[] - () + Sarif_v_2_1_0_v.create_sarif_json_schema ~version:`TwoDotOneDotZero ~runs:[] () in let s = Sarif_v_2_1_0_j.string_of_sarif_json_schema sarif_json_schema in print_endline s; [%expect {| {"version":"2.1.0","runs":[]} |}] +;; let parse_print_roundtrip file = let json = read_all file in let parsed = Sarif_v_2_1_0_j.sarif_json_schema_of_string json in let s = Sarif_v_2_1_0_j.string_of_sarif_json_schema parsed in print_endline s +;; let%expect_test "data/semgrep/test_sarif_output_rule_board/" = parse_print_roundtrip "data/semgrep/test_sarif_output_rule_board/results.sarif"; - [%expect {| + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[{"fingerprints":{"matchBasedId/v1":"1fa894f43c4fd60b1b0c5e2e9a50311b67b77a7b09f7c45001277b41e41accd87cd8e2931d57e0bf41a0e5086501be1fea611473dd02e1625c49204145464dba_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/stupid.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":26,"endLine":3,"snippet":{"text":" return a + b == a + b"},"startColumn":12,"startLine":3}}}],"message":{"text":"this rule comes from the rule board!"},"properties":{},"ruleId":"rules.rule-board-eqeq-five"},{"fingerprints":{"matchBasedId/v1":"79990521677dc96cec634491f9134e8528b49257440a27b8df47582e37668aaf5cb3343fe53b19476b12071b84f58db799c9f7f3d75b09dd3547f283b7036d38_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/stupid.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":11,"endLine":8,"snippet":{"text":" x == x"},"startColumn":5,"startLine":8}}}],"message":{"text":"this rule comes from the rule board!"},"properties":{},"ruleId":"rules.rule-board-eqeq-five"},{"fingerprints":{"matchBasedId/v1":"79990521677dc96cec634491f9134e8528b49257440a27b8df47582e37668aaf5cb3343fe53b19476b12071b84f58db799c9f7f3d75b09dd3547f283b7036d38_1"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/stupid.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":18,"endLine":12,"snippet":{"text":"assertTrue(x == x)"},"startColumn":12,"startLine":12}}}],"message":{"text":"this rule comes from the rule board!"},"properties":{},"ruleId":"rules.rule-board-eqeq-five"}],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"this rule comes from the rule board!"},"help":{"markdown":"this rule comes from the rule board!","text":"this rule comes from the rule board!"},"id":"rules.rule-board-eqeq-five","name":"rules.rule-board-eqeq-five","properties":{"precision":"very-high","tags":["rule-board-block"]},"shortDescription":{"text":"Semgrep Finding: rules.rule-board-eqeq-five"}}],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;; let%expect_test "data/semgrep/test_sarif_output_include_nosemgrep/results.sarif" = parse_print_roundtrip "data/semgrep/test_sarif_output_include_nosemgrep/results.sarif"; - [%expect {| + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[{"fingerprints":{"matchBasedId/v1":"1ccfdeae9247f2f32c35443f3bf87d4fd67e4d58b25adfcdb7dd5fc74079c09713a2e45e39f1f46e12361f98aa492bfba2a4983d4e9f409c02dfcff1ba254f20_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/regex-nosemgrep.txt","uriBaseId":"%SRCROOT%"},"region":{"endColumn":30,"endLine":1,"snippet":{"text":"aws_account_id = 123456789012 # nosemgrep"},"startColumn":1,"startLine":1}}}],"message":{"text":"AWS Account ID detected"},"properties":{},"ruleId":"rules.detected-aws-account-id","suppressions":[{"kind":"inSource"}]},{"fingerprints":{"matchBasedId/v1":"1ccfdeae9247f2f32c35443f3bf87d4fd67e4d58b25adfcdb7dd5fc74079c09713a2e45e39f1f46e12361f98aa492bfba2a4983d4e9f409c02dfcff1ba254f20_1"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/regex-nosemgrep.txt","uriBaseId":"%SRCROOT%"},"region":{"endColumn":28,"endLine":3,"snippet":{"text":"aws_account_id:123456789012"},"startColumn":1,"startLine":3}}}],"message":{"text":"AWS Account ID detected"},"properties":{},"ruleId":"rules.detected-aws-account-id"}],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"AWS Account ID detected"},"help":{"markdown":"AWS Account ID detected","text":"AWS Account ID detected"},"id":"rules.detected-aws-account-id","name":"rules.detected-aws-account-id","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.detected-aws-account-id"}}],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;; let%expect_test "data/semgrep/test_sarif_output_when_errors/results.sarif" = parse_print_roundtrip "data/semgrep/test_sarif_output_when_errors/results.sarif"; - [%expect {| + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[{"descriptor":{"id":"SemgrepError"},"level":"error","message":{"text":"File not found: targets/basic/inexistent.py"}}]}],"results":[],"tool":{"driver":{"name":"Semgrep OSS","rules":[],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;; let%expect_test "data/semgrep/test_sarif_output_with_autofix/results.sarif" = parse_print_roundtrip "data/semgrep/test_sarif_output_with_autofix/results.sarif"; - [%expect {| + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[{"fingerprints":{"matchBasedId/v1":"4a33397409b7b2d0e677e2e515c526be5568d00a2bf740196e13536ad2b2dfa554167db90394ec8e9779a89eb3ca6e98d86d690f9cc9625fca1fc18be633b1ac_0"},"fixes":[{"artifactChanges":[{"artifactLocation":{"uri":"targets/autofix/autofix.py"},"replacements":[{"deletedRegion":{"endColumn":12,"endLine":5,"startColumn":3,"startLine":5},"insertedContent":{"text":" inputs.get(x) = 1"}}]}],"description":{"text":"Use `.get()` method to avoid a KeyNotFound error\n Autofix: Semgrep rule suggested fix"}}],"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/autofix/autofix.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":12,"endLine":5,"snippet":{"text":" inputs[x] = 1"},"startColumn":3,"startLine":5}}}],"message":{"text":"Use `.get()` method to avoid a KeyNotFound error"},"properties":{},"ruleId":"rules.autofix.use-dict-get"},{"fingerprints":{"matchBasedId/v1":"592b33f0145ca2899616e587fca10aed02dc2cb1261f5e39597f7b66464e2c89cacb4a318c010006c6126e6a0de0a764a2b281dbad87315460dbbbd9a44cd412_0"},"fixes":[{"artifactChanges":[{"artifactLocation":{"uri":"targets/autofix/autofix.py"},"replacements":[{"deletedRegion":{"endColumn":19,"endLine":6,"startColumn":6,"startLine":6},"insertedContent":{"text":" if inputs.get((x + 1)) == True:"}}]}],"description":{"text":"Use `.get()` method to avoid a KeyNotFound error\n Autofix: Semgrep rule suggested fix"}}],"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/autofix/autofix.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":19,"endLine":6,"snippet":{"text":" if inputs[x + 1] == True:"},"startColumn":6,"startLine":6}}}],"message":{"text":"Use `.get()` method to avoid a KeyNotFound error"},"properties":{},"ruleId":"rules.autofix.use-dict-get"}],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"Use `.get()` method to avoid a KeyNotFound error"},"help":{"markdown":"Use `.get()` method to avoid a KeyNotFound error","text":"Use `.get()` method to avoid a KeyNotFound error"},"id":"rules.autofix.use-dict-get","name":"rules.autofix.use-dict-get","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.autofix.use-dict-get"}}],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;; let%expect_test "data/semgrep/test_sarif_output_with_dataflow_traces/results.sarif" = - parse_print_roundtrip "data/semgrep/test_sarif_output_with_dataflow_traces/results.sarif"; - [%expect {| + parse_print_roundtrip + "data/semgrep/test_sarif_output_with_dataflow_traces/results.sarif"; + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[{"codeFlows":[{"message":{"text":"Untrusted dataflow from targets/taint/taint.py:3 to targets/taint/taint.py:9"},"threadFlows":[{"locations":[{"location":{"message":{"text":"Source: 'source1()' @ 'targets/taint/taint.py:3'"},"physicalLocation":{"artifactLocation":{"uri":"targets/taint/taint.py"},"region":{"endColumn":18,"endLine":3,"message":{"text":"Source: 'source1()' @ 'targets/taint/taint.py:3'"},"snippet":{"text":"source1()"},"startColumn":9,"startLine":3}}},"nestingLevel":0},{"location":{"message":{"text":"Propagator : 'a' @ 'targets/taint/taint.py:3'"},"physicalLocation":{"artifactLocation":{"uri":"targets/taint/taint.py"},"region":{"endColumn":6,"endLine":3,"message":{"text":"Propagator : 'a' @ 'targets/taint/taint.py:3'"},"snippet":{"text":"a"},"startColumn":5,"startLine":3}}},"nestingLevel":0},{"location":{"message":{"text":"Propagator : 'b' @ 'targets/taint/taint.py:8'"},"physicalLocation":{"artifactLocation":{"uri":"targets/taint/taint.py"},"region":{"endColumn":10,"endLine":8,"message":{"text":"Propagator : 'b' @ 'targets/taint/taint.py:8'"},"snippet":{"text":"b"},"startColumn":9,"startLine":8}}},"nestingLevel":0},{"location":{"message":{"text":"Sink: 'sink1(b)' @ 'targets/taint/taint.py:9'"},"physicalLocation":{"artifactLocation":{"uri":"targets/taint/taint.py"},"region":{"endColumn":13,"endLine":9,"message":{"text":"Sink: 'sink1(b)' @ 'targets/taint/taint.py:9'"},"snippet":{"text":" sink1(b)"},"startColumn":5,"startLine":9}}},"nestingLevel":1}]}]}],"fingerprints":{"matchBasedId/v1":"b7d9e6f63610bc461ccd05b612b609b516a1ba6c6fb63268160f62de8bb894cd8c2ef9e389681db5d538050af75010b0219f21d41f67488da439ca426798dbde_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/taint/taint.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":13,"endLine":9,"snippet":{"text":" sink1(b)"},"startColumn":5,"startLine":9}}}],"message":{"text":"A user input source() went into a dangerous sink()"},"properties":{},"ruleId":"rules.classic"}],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"warning"},"fullDescription":{"text":"A user input source() went into a dangerous sink()"},"help":{"markdown":"A user input source() went into a dangerous sink()","text":"A user input source() went into a dangerous sink()"},"id":"rules.classic","name":"rules.classic","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.classic"}}],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;; let%expect_test "data/semgrep/test_sarif_output_with_nosemgrep_and_error/results.sarif" = - parse_print_roundtrip "data/semgrep/test_sarif_output_with_nosemgrep_and_error/results.sarif"; - [%expect {| + parse_print_roundtrip + "data/semgrep/test_sarif_output_with_nosemgrep_and_error/results.sarif"; + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[{"fingerprints":{"matchBasedId/v1":"4a1a7f92c1f9d4d48ea96c4353e75c3b1e0bcb51e3c5a84d9edbaa810f7a1814f5fbf4a4cd1f88de224f007c4c3fb666a9fa61d669d739c2d78215ec73d02e7c_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/nosemgrep/eqeq-nosemgrep.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":26,"endLine":2,"snippet":{"text":" return a + b == a + b # nosemgrep: rules.eqeq-is-bad"},"startColumn":12,"startLine":2}}}],"message":{"text":"useless comparison operation `a + b == a + b` or `a + b != a + b`"},"properties":{},"ruleId":"rules.eqeq-is-bad","suppressions":[{"kind":"inSource"}]}],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"possibly useless comparison but in eq function"},"help":{"markdown":"possibly useless comparison but in eq function","text":"possibly useless comparison but in eq function"},"id":"rules.assert-eqeq-is-ok","name":"rules.assert-eqeq-is-ok","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.assert-eqeq-is-ok"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"useless comparison operation `$X == $X` or `$X != $X`"},"help":{"markdown":"useless comparison operation `$X == $X` or `$X != $X`\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/r/eqeq-bad)\n","text":"useless comparison operation `$X == $X` or `$X != $X`"},"helpUri":"https://semgrep.dev/r/eqeq-bad","id":"rules.eqeq-is-bad","name":"rules.eqeq-is-bad","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.eqeq-is-bad"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"useless comparison"},"help":{"markdown":"useless comparison","text":"useless comparison"},"id":"rules.javascript-basic-eqeq-bad","name":"rules.javascript-basic-eqeq-bad","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.javascript-basic-eqeq-bad"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"this function is only available on Python 3.7+"},"help":{"markdown":"this function is only available on Python 3.7+","text":"this function is only available on Python 3.7+"},"id":"rules.python37-compatability-os-module","name":"rules.python37-compatability-os-module","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.python37-compatability-os-module"}}],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;; let%expect_test "data/semgrep/test_sarif_output_with_source/results.sarif" = parse_print_roundtrip "data/semgrep/test_sarif_output_with_source/results.sarif"; - [%expect {| + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[{"fingerprints":{"matchBasedId/v1":"62b4a09c4569768898c43c09fa0a5b95b7e93257ef3a0911a5c379b6265b4d49fa4aecd5782461632e9aef4779af02d7cad4405b9a5318a0e5ffe9a5bd8daeae_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/stupid.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":26,"endLine":3,"snippet":{"text":" return a + b == a + b"},"startColumn":12,"startLine":3}}}],"message":{"text":"useless comparison operation `a + b == a + b` or `a + b != a + b`; possible bug?"},"properties":{},"ruleId":"rules.eqeq-is-bad"},{"fingerprints":{"matchBasedId/v1":"33c7ad418bcb7f83d9dcec68b2a8aa78ace93efbc20a12297ea7e15594ce23f5bca80b0958952b14dad3e874370c9ca7f991d2e1414adc33d243f133b1ff2811_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/stupid.js","uriBaseId":"%SRCROOT%"},"region":{"endColumn":19,"endLine":3,"snippet":{"text":"console.log(x == x)"},"startColumn":13,"startLine":3}}}],"message":{"text":"useless comparison"},"properties":{},"ruleId":"rules.javascript-basic-eqeq-bad"}],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"possibly useless comparison but in eq function"},"help":{"markdown":"possibly useless comparison but in eq function\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/foo/bar/assert)\n","text":"possibly useless comparison but in eq function"},"helpUri":"https://semgrep.dev/foo/bar/assert","id":"rules.assert-eqeq-is-ok","name":"rules.assert-eqeq-is-ok","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.assert-eqeq-is-ok"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"useless comparison operation `$X == $X` or `$X != $X`; possible bug?"},"help":{"markdown":"useless comparison operation `$X == $X` or `$X != $X`; possible bug?\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/foo/bar/bad)\n","text":"useless comparison operation `$X == $X` or `$X != $X`; possible bug?"},"helpUri":"https://semgrep.dev/foo/bar/bad","id":"rules.eqeq-is-bad","name":"rules.eqeq-is-bad","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.eqeq-is-bad"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"useless comparison"},"help":{"markdown":"useless comparison\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/foo/bar/js)\n - [https://google.com](https://google.com)\n","text":"useless comparison"},"helpUri":"https://semgrep.dev/foo/bar/js","id":"rules.javascript-basic-eqeq-bad","name":"rules.javascript-basic-eqeq-bad","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.javascript-basic-eqeq-bad"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"this function is only available on Python 3.7+"},"help":{"markdown":"this function is only available on Python 3.7+\n\nReferences:\n - [Semgrep Rule](https://semgrep.dev/foo/bar/compat)\n","text":"this function is only available on Python 3.7+"},"helpUri":"https://semgrep.dev/foo/bar/compat","id":"rules.python37-compatability-os-module","name":"rules.python37-compatability-os-module","properties":{"precision":"very-high","tags":[]},"shortDescription":{"text":"Semgrep Finding: rules.python37-compatability-os-module"}}],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;; let%expect_test "data/semgrep/test_sarif_output_with_source_edit/results.sarif" = parse_print_roundtrip "data/semgrep/test_sarif_output_with_source_edit/results.sarif"; - [%expect {| + [%expect + {| {"version":"2.1.0","runs":[{"invocations":[{"executionSuccessful":true,"toolExecutionNotifications":[]}],"results":[{"fingerprints":{"matchBasedId/v1":"62b4a09c4569768898c43c09fa0a5b95b7e93257ef3a0911a5c379b6265b4d49fa4aecd5782461632e9aef4779af02d7cad4405b9a5318a0e5ffe9a5bd8daeae_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/stupid.py","uriBaseId":"%SRCROOT%"},"region":{"endColumn":26,"endLine":3,"snippet":{"text":" return a + b == a + b"},"startColumn":12,"startLine":3}}}],"message":{"text":"useless comparison operation `a + b == a + b` or `a + b != a + b`; possible bug?"},"properties":{},"ruleId":"rules.eqeq-is-bad"},{"fingerprints":{"matchBasedId/v1":"33c7ad418bcb7f83d9dcec68b2a8aa78ace93efbc20a12297ea7e15594ce23f5bca80b0958952b14dad3e874370c9ca7f991d2e1414adc33d243f133b1ff2811_0"},"locations":[{"physicalLocation":{"artifactLocation":{"uri":"targets/basic/stupid.js","uriBaseId":"%SRCROOT%"},"region":{"endColumn":19,"endLine":3,"snippet":{"text":"console.log(x == x)"},"startColumn":13,"startLine":3}}}],"message":{"text":"useless comparison"},"properties":{},"ruleId":"rules.javascript-basic-eqeq-bad"}],"tool":{"driver":{"name":"Semgrep OSS","rules":[{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"possibly useless comparison but in eq function"},"help":{"markdown":"some help text","text":"some help text"},"id":"rules.assert-eqeq-is-ok","name":"rules.assert-eqeq-is-ok","properties":{"precision":"very-high","tags":["security","sometag"]},"shortDescription":{"text":"some short description"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"useless comparison operation `$X == $X` or `$X != $X`; possible bug?"},"help":{"markdown":"some help text","text":"some help text"},"id":"rules.eqeq-is-bad","name":"rules.eqeq-is-bad","properties":{"precision":"very-high","tags":["security","sometag"]},"shortDescription":{"text":"some short description"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"useless comparison"},"help":{"markdown":"some help text","text":"some help text"},"id":"rules.javascript-basic-eqeq-bad","name":"rules.javascript-basic-eqeq-bad","properties":{"precision":"very-high","tags":["cwe te","security","sometag"]},"shortDescription":{"text":"some short description"}},{"defaultConfiguration":{"level":"error"},"fullDescription":{"text":"this function is only available on Python 3.7+"},"help":{"markdown":"some help text","text":"some help text"},"id":"rules.python37-compatability-os-module","name":"rules.python37-compatability-os-module","properties":{"precision":"very-high","tags":["security","sometag"]},"shortDescription":{"text":"some short description"}}],"semanticVersion":"placeholder"}}}],"$schema":"https://docs.oasis-open.org/sarif/sarif/v2.1.0/os/schemas/sarif-schema-2.1.0.json"} |}] +;;