diff --git a/infer/src/base/Config.ml b/infer/src/base/Config.ml index e35f61631..937a1d345 100644 --- a/infer/src/base/Config.ml +++ b/infer/src/base/Config.ml @@ -1157,6 +1157,11 @@ and project_root = ~parse_mode:CLOpt.(Infer [Analysis;Clang;Driver;Print]) ~meta:"dir" "Specify the root directory of the project" +and quandary_endpoints = + CLOpt.mk_json ~long:"quandary-endpoints" + ~parse_mode:CLOpt.(Infer [Quandary]) + "Specify endpoint classes for Quandary" + and quandary_sources = CLOpt.mk_json ~long:"quandary-sources" ~parse_mode:CLOpt.(Infer [Quandary]) @@ -1725,6 +1730,7 @@ and procs_csv = !procs_csv and procs_xml = !procs_xml and project_root = !project_root and quandary = !quandary +and quandary_endpoints = !quandary_endpoints and quandary_sources = !quandary_sources and quandary_sinks = !quandary_sinks and quiet = !quiet diff --git a/infer/src/base/Config.mli b/infer/src/base/Config.mli index 293ddad71..65edd927b 100644 --- a/infer/src/base/Config.mli +++ b/infer/src/base/Config.mli @@ -299,6 +299,7 @@ val procs_csv : string option val procs_xml : string option val project_root : string val quandary : bool +val quandary_endpoints : Yojson.Basic.json val quandary_sources : Yojson.Basic.json val quandary_sinks : Yojson.Basic.json val quiet : bool diff --git a/infer/src/quandary/QuandaryConfig.ml b/infer/src/quandary/QuandaryConfig.ml index e85a5e7e5..157e74697 100644 --- a/infer/src/quandary/QuandaryConfig.ml +++ b/infer/src/quandary/QuandaryConfig.ml @@ -44,3 +44,14 @@ module Sink = struct | _ -> [] end + +module Endpoint = struct + type t = string + + let of_json = function + | `List endpoints -> + let parse_endpoint = Yojson.Basic.Util.to_string in + List.map ~f:parse_endpoint endpoints + | _ -> + [] +end diff --git a/infer/src/quandary/QuandaryConfig.mli b/infer/src/quandary/QuandaryConfig.mli index 77b8127a9..d84411a5d 100644 --- a/infer/src/quandary/QuandaryConfig.mli +++ b/infer/src/quandary/QuandaryConfig.mli @@ -22,3 +22,9 @@ module Sink : sig val of_json : [> `List of Yojson.Basic.json list ] -> t list end + +module Endpoint : sig + type t = string (** name of endpoint class *) + + val of_json : [> `List of Yojson.Basic.json list ] -> t list +end diff --git a/infer/src/quandary/TaintAnalysis.ml b/infer/src/quandary/TaintAnalysis.ml index a733ca3a7..7d4e3f962 100644 --- a/infer/src/quandary/TaintAnalysis.ml +++ b/infer/src/quandary/TaintAnalysis.ml @@ -159,6 +159,15 @@ module Make (TaintSpecification : TaintSpec.S) = struct let id_ap = AccessPath.Exact (AccessPath.of_id ret_id ret_typ) in TaintDomain.add_trace id_ap trace access_tree + let endpoints = String.Set.of_list (QuandaryConfig.Endpoint.of_json Config.quandary_endpoints) + + let is_endpoint source = + match CallSite.pname (TraceDomain.Source.call_site source) with + | Typ.Procname.Java java_pname -> + String.Set.mem endpoints (Typ.Procname.java_get_class_name java_pname) + | _ -> + false + (** log any new reportable source-sink flows in [trace] *) let report_trace trace cur_site (proc_data : FormalMap.t ProcData.t) = let trace_of_pname pname = @@ -181,9 +190,10 @@ module Make (TaintSpecification : TaintSpec.S) = struct let final_sink = fst (List.hd_exn sinks_passthroughs) in F.fprintf fmt - "%a -> %a" + "%a -> %a%s" TraceDomain.Source.pp original_source - TraceDomain.Sink.pp final_sink in + TraceDomain.Sink.pp final_sink + (if is_endpoint original_source then ". Note: source is an endpoint." else "") in let report_error path = let caller_pname = Procdesc.get_proc_name proc_data.pdesc in diff --git a/infer/tests/codetoanalyze/java/quandary/.inferconfig b/infer/tests/codetoanalyze/java/quandary/.inferconfig index ed7360631..0ce166ecf 100644 --- a/infer/tests/codetoanalyze/java/quandary/.inferconfig +++ b/infer/tests/codetoanalyze/java/quandary/.inferconfig @@ -15,5 +15,8 @@ "procedure": "codetoanalyze.java.quandary.ExternalSpecs.loggingSink2", "kind": "Logging" } + ], + "quandary-endpoints": [ + "codetoanalyze.java.quandary.MyService" ] }