Commit 02f4ea7e authored by Virgile Prevosto's avatar Virgile Prevosto
Browse files

Merge branch 'feature/andre/mdr-sarif-pretty' into 'master'

Feature/andre/mdr sarif pretty

See merge request frama-c/frama-c!2846
parents b876bf4e 37dc88a3
...@@ -277,13 +277,19 @@ module Normalized = struct ...@@ -277,13 +277,19 @@ module Normalized = struct
with _ -> false with _ -> false
let to_base_uri name = let to_base_uri name =
if is_relative name then None, skip_dot name let p = insert cwd name in
else begin let buf = Buffer.create 80 in
let p = insert cwd name in let res = add_uri_path buf p in
let buf = Buffer.create 80 in let uri =
let res = add_uri_path buf p in Buffer.contents buf in
res, Buffer.contents buf let uri =
end try
if String.get uri 0 = '/' then
String.sub uri 1 (String.length uri - 1)
else uri
with Invalid_argument _ -> uri
in
res, uri
end end
type position = type position =
......
...@@ -39,7 +39,7 @@ PLUGIN_CMO:=\ ...@@ -39,7 +39,7 @@ PLUGIN_CMO:=\
PLUGIN_DISTRIBUTED:=$(PLUGIN_ENABLE) PLUGIN_DISTRIBUTED:=$(PLUGIN_ENABLE)
PLUGIN_REQUIRES:=ppx_deriving ppx_deriving_yojson yojson PLUGIN_REQUIRES:=ppx_deriving ppx_deriving_yojson yojson
PLUGIN_DISTRIB_EXTERNAL:= Makefile.in configure.ac configure share/acsl.xml PLUGIN_DISTRIB_EXTERNAL:= Makefile.in configure.ac configure share/acsl.xml
PLUGIN_TESTS_DIRS:= eva PLUGIN_TESTS_DIRS:= eva sarif
include $(FRAMAC_SHARE)/Makefile.dynamic include $(FRAMAC_SHARE)/Makefile.dynamic
......
...@@ -112,3 +112,17 @@ module Stubs = String_list( ...@@ -112,3 +112,17 @@ module Stubs = String_list(
let arg_name = "f1,...,fn" let arg_name = "f1,...,fn"
let help = "list of C files containing stub functions" let help = "list of C files containing stub functions"
end) end)
module PrintLibc = True(
struct
let option_name = "-mdr-print-libc"
let help =
"when set (default), reports include information about libc elements."
end)
module SarifDeterministic = False(
struct
let option_name = "-mdr-sarif-deterministic"
let help = "omits non-deterministic data from SARIF reports, such as \
absolute file URIs and timestamps."
end)
...@@ -45,3 +45,9 @@ module Date: Parameter_sig.String ...@@ -45,3 +45,9 @@ module Date: Parameter_sig.String
(** Value of [-mdr-stubs]. *) (** Value of [-mdr-stubs]. *)
module Stubs: Parameter_sig.String_list module Stubs: Parameter_sig.String_list
(** Value of [-mdr-print-libc]. *)
module PrintLibc: Parameter_sig.Bool
(** Value of [-mdr-sarif-deterministic]. *)
module SarifDeterministic: Parameter_sig.Bool
...@@ -98,10 +98,8 @@ module ArtifactLocation = struct ...@@ -98,10 +98,8 @@ module ArtifactLocation = struct
let default = create ~uri:"" () let default = create ~uri:"" ()
let of_loc loc = let of_loc loc =
let open Filepath in let uriBaseId, uri = Filepath.(Normalized.to_base_uri (fst loc).pos_path) in
(* by construction, we have an absolute path here, no need for uriBase *) create ~uri ?uriBaseId ()
let uri = ((fst loc).pos_path :> string) in
create ~uri ()
end end
module ArtifactLocationDictionary = Json_dictionary(ArtifactLocation) module ArtifactLocationDictionary = Json_dictionary(ArtifactLocation)
...@@ -462,6 +460,7 @@ module Driver = struct ...@@ -462,6 +460,7 @@ module Driver = struct
semanticVersion: (string [@default ""]); semanticVersion: (string [@default ""]);
fileVersion: (string [@default ""]); fileVersion: (string [@default ""]);
downloadUri: (string [@default ""]); downloadUri: (string [@default ""]);
informationUri: (string [@default ""]);
sarifLoggerVersion: (string [@default ""]); sarifLoggerVersion: (string [@default ""]);
language: (string [@default "en-US"]); language: (string [@default "en-US"]);
properties: (Properties.t [@default Properties.default]); properties: (Properties.t [@default Properties.default]);
...@@ -474,13 +473,14 @@ module Driver = struct ...@@ -474,13 +473,14 @@ module Driver = struct
?(semanticVersion="") ?(semanticVersion="")
?(fileVersion="") ?(fileVersion="")
?(downloadUri="") ?(downloadUri="")
?(informationUri="")
?(sarifLoggerVersion="") ?(sarifLoggerVersion="")
?(language="en-US") ?(language="en-US")
?(properties=Properties.default) ?(properties=Properties.default)
() ()
= =
{ name; fullName; version; semanticVersion; fileVersion; { name; fullName; version; semanticVersion; fileVersion;
downloadUri; sarifLoggerVersion; language; properties } downloadUri; informationUri; sarifLoggerVersion; language; properties }
let default = create ~name:"" () let default = create ~name:"" ()
end end
......
...@@ -22,14 +22,20 @@ ...@@ -22,14 +22,20 @@
open Sarif open Sarif
let frama_c_sarif = let frama_c_sarif () =
let name = "frama-c" in let name = "frama-c" in
let version = Fc_config.version_and_codename in let version, semanticVersion =
let semanticVersion = Fc_config.version in if Mdr_params.SarifDeterministic.get () then
"0+omitted-for-deterministic-output", ""
else
Fc_config.version_and_codename, Fc_config.version
in
let fullName = name ^ "-" ^ version in let fullName = name ^ "-" ^ version in
let downloadUri = "https://frama-c.com/download.html" in let downloadUri = "https://frama-c.com/download.html" in
let informationUri = "https://frama-c.com" in
Tool.create Tool.create
(Driver.create ~name ~version ~semanticVersion ~fullName ~downloadUri ()) (Driver.create ~name ~version ~semanticVersion ~fullName ~downloadUri
~informationUri ())
let get_remarks () = let get_remarks () =
let f = Mdr_params.Remarks.get () in let f = Mdr_params.Remarks.get () in
...@@ -53,6 +59,9 @@ module Analysis_cmdline = ...@@ -53,6 +59,9 @@ module Analysis_cmdline =
let gen_invocation () = let gen_invocation () =
let cl = Analysis_cmdline.get () in let cl = Analysis_cmdline.get () in
(* The first argument is _always_ the binary name, but to avoid printing it
as an absolute path to binlevel.opt, we replace it with 'frama-c' *)
let cl = "frama-c" :: List.tl cl in
let commandLine = String.concat " " cl in let commandLine = String.concat " " cl in
let arguments = List.tl cl in let arguments = List.tl cl in
Invocation.create ~commandLine ~arguments () Invocation.create ~commandLine ~arguments ()
...@@ -107,27 +116,51 @@ let make_message alarm annot remark = ...@@ -107,27 +116,51 @@ let make_message alarm annot remark =
in in
Message.create ~text ~markdown () Message.create ~text ~markdown ()
let kf_is_in_libc kf =
let g = Kernel_function.get_global kf in
Cil.hasAttribute "fc_stdlib" (Cil_datatype.Global.attr g)
let ip_is_in_libc ip =
match Property.get_kf ip with
| None ->
(* possibly an identified lemma; check its attributes *)
begin
match ip with
| IPAxiomatic {iax_attrs=attrs}
| IPLemma {il_attrs=attrs}
| IPAxiom {il_attrs=attrs} ->
Cil.hasAttribute "fc_stdlib" attrs
| _ ->
false
end
| Some kf ->
kf_is_in_libc kf
let opt_physical_location_of_loc loc = let opt_physical_location_of_loc loc =
if loc = Cil_datatype.Location.unknown then [] if loc = Cil_datatype.Location.unknown then []
else [ Location.of_loc loc ] else [ Location.of_loc loc ]
(* Cil_types *)
let gen_results remarks = let gen_results remarks =
let treat_alarm _e kf s ~rank:_ alarm annot (i, rules, content) = let treat_alarm _e kf s ~rank:_ alarm annot (i, rules, content) =
let prop = Property.ip_of_code_annot_single kf s annot in if not (Mdr_params.PrintLibc.get ()) && kf_is_in_libc kf then
let ruleId = Alarms.get_name alarm in (* skip alarm in libc *)
let rules = (i, rules, content)
Datatype.String.Map.add ruleId (Alarms.get_description alarm) rules else
in let prop = Property.ip_of_code_annot_single kf s annot in
let label = "Alarm-" ^ string_of_int i in let ruleId = Alarms.get_name alarm in
let kind = kind_of_status (Property_status.Feedback.get prop) in let rules =
let level = level_of_status (Property_status.Feedback.get prop) in Datatype.String.Map.add ruleId (Alarms.get_description alarm) rules
let remark = get_remark remarks label in in
let message = make_message alarm annot remark in let label = "Alarm-" ^ string_of_int i in
let locations = opt_physical_location_of_loc (Cil_datatype.Stmt.loc s) in let kind = kind_of_status (Property_status.Feedback.get prop) in
let res = let level = level_of_status (Property_status.Feedback.get prop) in
Sarif_result.create ~kind ~level ~ruleId ~message ~locations () let remark = get_remark remarks label in
in let message = make_message alarm annot remark in
(i+1, rules, res :: content) let locations = opt_physical_location_of_loc (Cil_datatype.Stmt.loc s) in
let res =
Sarif_result.create ~kind ~level ~ruleId ~message ~locations ()
in
(i+1, rules, res :: content)
in in
let _, rules, content = let _, rules, content =
Alarms.fold treat_alarm (0, Datatype.String.Map.empty,[]) Alarms.fold treat_alarm (0, Datatype.String.Map.empty,[])
...@@ -153,14 +186,18 @@ let gen_status ip = ...@@ -153,14 +186,18 @@ let gen_status ip =
let gen_statuses () = let gen_statuses () =
let f ip content = let f ip content =
if is_alarm ip then content else (gen_status ip) :: content let exclude =
is_alarm ip ||
(not (Mdr_params.PrintLibc.get ()) && ip_is_in_libc ip)
in
if exclude then content else (gen_status ip) :: content
in in
List.rev (Property_status.fold f []) List.rev (Property_status.fold f [])
let gen_artifacts () = let gen_artifacts () =
let add_src_file f = let add_src_file f =
let uri = (f:Filepath.Normalized.t :> string) in let uriBaseId, uri = Filepath.Normalized.to_base_uri f in
let location = ArtifactLocation.create ~uri () in let location = ArtifactLocation.create ~uri ?uriBaseId () in
let roles = [ Role.analysisTarget ] in let roles = [ Role.analysisTarget ] in
let mimeType = "text/x-csrc" in let mimeType = "text/x-csrc" in
Artifact.create ~location ~roles ~mimeType () Artifact.create ~location ~roles ~mimeType ()
...@@ -176,7 +213,7 @@ let add_rule id desc l = ...@@ -176,7 +213,7 @@ let add_rule id desc l =
let make_taxonomies rules = Datatype.String.Map.fold add_rule rules [] let make_taxonomies rules = Datatype.String.Map.fold add_rule rules []
let gen_run remarks = let gen_run remarks =
let tool = frama_c_sarif in let tool = frama_c_sarif () in
let name = "frama-c" in let name = "frama-c" in
let invocations = [gen_invocation ()] in let invocations = [gen_invocation ()] in
let rules, results = gen_results remarks in let rules, results = gen_results remarks in
...@@ -192,7 +229,24 @@ let gen_run remarks = ...@@ -192,7 +229,24 @@ let gen_run remarks =
let taxonomies = [ToolComponent.create ~name ~rules ()] in let taxonomies = [ToolComponent.create ~name ~rules ()] in
let results = results @ user_annot_results in let results = results @ user_annot_results in
let artifacts = gen_artifacts () in let artifacts = gen_artifacts () in
Run.create ~tool ~invocations ~results ~taxonomies ~artifacts () let uriBases = ("PWD", Sys.getcwd ()) :: Filepath.all_symbolic_dirs () in
let uriBasesJson =
List.fold_left (fun acc (name, dir) ->
let baseUri =
if Mdr_params.SarifDeterministic.get () then
"file:///omitted-for-deterministic-output/"
else "file://" ^ dir ^ "/"
in
(name, `Assoc [("uri", `String baseUri)]) :: acc
) [] uriBases
in
let originalUriBaseIds =
match ArtifactLocationDictionary.of_yojson (`Assoc uriBasesJson) with
| Ok x -> x
| Error s -> failwith s
in
Run.create ~tool ~invocations ~results ~taxonomies ~artifacts
~originalUriBaseIds ()
let generate () = let generate () =
let remarks = get_remarks () in let remarks = get_remarks () in
......
/* run.config
CMD: @frama-c@ @PTEST_FILE@ -no-autoload-plugins -load-module eva,from,scope,markdown_report -eva -eva-no-results -mdr-gen sarif -mdr-sarif-deterministic
LOG: with-libc.sarif
OPT: -mdr-out @PTEST_DIR@/result/with-libc.sarif
LOG: without-libc.sarif
OPT: -mdr-no-print-libc -mdr-out @PTEST_DIR@/result/without-libc.sarif
*/
#include <string.h>
int main() {
char *s = "hello world";
int n = strlen(s);
return n;
}
[kernel] Parsing tests/sarif/libc.c (with preprocessing)
[eva] Analyzing a complete application starting at main
[eva] Computing initial state
[eva] Initial state computed
[eva:initial-state] Values of globals at initialization
[eva] done for function main
[eva] ====== VALUES COMPUTED ======
[eva:summary] ====== ANALYSIS SUMMARY ======
----------------------------------------------------------------------------
1 function analyzed (out of 1): 100% coverage.
In this function, 4 statements reached (out of 4): 100% coverage.
----------------------------------------------------------------------------
No errors or warnings raised during the analysis.
----------------------------------------------------------------------------
0 alarms generated by the analysis.
----------------------------------------------------------------------------
Evaluation of the logical properties reached by the analysis:
Assertions 0 valid 0 unknown 0 invalid 0 total
Preconditions 1 valid 0 unknown 0 invalid 1 total
100% of the logical properties reached have been proven.
----------------------------------------------------------------------------
[mdr] Report tests/sarif/result/with-libc.sarif generated
[kernel] Parsing tests/sarif/libc.c (with preprocessing)
[eva] Analyzing a complete application starting at main
[eva] Computing initial state
[eva] Initial state computed
[eva:initial-state] Values of globals at initialization
[eva] done for function main
[eva] ====== VALUES COMPUTED ======
[eva:summary] ====== ANALYSIS SUMMARY ======
----------------------------------------------------------------------------
1 function analyzed (out of 1): 100% coverage.
In this function, 4 statements reached (out of 4): 100% coverage.
----------------------------------------------------------------------------
No errors or warnings raised during the analysis.
----------------------------------------------------------------------------
0 alarms generated by the analysis.
----------------------------------------------------------------------------
Evaluation of the logical properties reached by the analysis:
Assertions 0 valid 0 unknown 0 invalid 0 total
Preconditions 1 valid 0 unknown 0 invalid 1 total
100% of the logical properties reached have been proven.
----------------------------------------------------------------------------
[mdr] Report tests/sarif/result/without-libc.sarif generated
This diff is collapsed.
{
"$schema":
"https://github.com/oasis-tcs/sarif-spec/blob/master/Documents/CommitteeSpecificationDrafts/v2.1.0-CSD.1/sarif-schema-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "frama-c",
"fullName": "frama-c-0+omitted-for-deterministic-output",
"version": "0+omitted-for-deterministic-output",
"downloadUri": "https://frama-c.com/download.html",
"informationUri": "https://frama-c.com"
}
},
"invocations": [
{
"commandLine":
"frama-c -check tests/sarif/libc.c -no-autoload-plugins -load-module eva,from,scope,markdown_report -eva -eva-no-results -mdr-gen sarif -mdr-sarif-deterministic -mdr-no-print-libc -mdr-out tests/sarif/result/without-libc.sarif",
"arguments": [
"-check", "tests/sarif/libc.c", "-no-autoload-plugins",
"-load-module", "eva,from,scope,markdown_report", "-eva",
"-eva-no-results", "-mdr-gen", "sarif",
"-mdr-sarif-deterministic", "-mdr-no-print-libc", "-mdr-out",
"tests/sarif/result/without-libc.sarif"
],
"exitCode": 0,
"executionSuccessful": true
}
],
"originalUriBaseIds": {
"FRAMAC_SHARE": {
"uri": "file:///omitted-for-deterministic-output/"
},
"FRAMAC_LIB": { "uri": "file:///omitted-for-deterministic-output/" },
"FRAMAC_PLUGIN": {
"uri": "file:///omitted-for-deterministic-output/"
},
"PWD": { "uri": "file:///omitted-for-deterministic-output/" }
},
"artifacts": [
{
"location": { "uri": "tests/sarif/libc.c", "uriBaseId": "PWD" },
"roles": [ "analysisTarget" ],
"mimeType": "text/x-csrc"
}
],
"results": [
{
"ruleId": "user-spec",
"kind": "pass",
"level": "none",
"message": {
"text": "specialization of valid_string_s at stmt 2."
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "tests/sarif/libc.c",
"uriBaseId": "PWD"
},
"region": {
"startLine": 13,
"startColumn": 10,
"endLine": 13,
"endColumn": 19,
"byteLength": 9
}
}
}
]
}
],
"defaultSourceLanguage": "C",
"taxonomies": [
{
"name": "frama-c",
"rules": [
{
"id": "user-spec",
"shortDescription": {
"text": "User-written ACSL specification."
}
}
],
"contents": [ "nonLocalizedData" ]
}
]
}
]
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment