[quandary] add Errlog traces

Summary: Generalizing jvillard's awesome work to include passthroughs in traces, then calling it from Quandary.

Reviewed By: jvillard

Differential Revision: D4172108

fbshipit-source-id: 0296c59
master
Sam Blackshear 8 years ago committed by Facebook Github Bot
parent e3d8482bd4
commit 8d48c108ca

@ -21,6 +21,9 @@ type t =
let make site =
{ site }
let site t =
t.site
let compare pt1 pt2 =
(match pt1, pt2 with
| {site=site1}, {site=site2} -> CallSite.compare site1 site2

@ -13,6 +13,8 @@ type t
val make : CallSite.t -> t
val site : t -> CallSite.t
val compare : t -> t -> int
val pp : F.formatter -> t -> unit

@ -239,23 +239,53 @@ module Make (Spec : Spec) = struct
let callsite = Sink.call_site sink in
Format.asprintf "call to %a" Procname.pp (CallSite.pname callsite))
?(sink_should_nest=(fun _ -> true))
(_, sources, sinks) =
let trace_elem_of_path_elem call_site desc should_nest =
let level = ref 0 in
fun (elem, _) ->
let lt_level = !level in
let desc = desc elem in
let callsite = call_site elem in
if should_nest elem then incr level;
Errlog.make_trace_element lt_level (CallSite.loc callsite) desc [] in
let trace_elem_of_source =
trace_elem_of_path_elem Source.call_site desc_of_source source_should_nest in
let trace_elem_of_sink =
trace_elem_of_path_elem Sink.call_site desc_of_sink sink_should_nest in
(* reverse sinks intentionally, do not reverse sources(?) *)
IList.rev_append
(IList.rev_map trace_elem_of_source sources)
(IList.map trace_elem_of_sink (IList.rev sinks))
(passthroughs, sources, sinks) =
let trace_elems_of_passthroughs lt_level passthroughs acc0 =
let trace_elem_of_passthrough passthrough acc =
let passthrough_site = Passthrough.site passthrough in
let desc = F.asprintf "flow through %a" Procname.pp (CallSite.pname passthrough_site) in
(Errlog.make_trace_element lt_level (CallSite.loc passthrough_site) desc []) :: acc in
(* sort passthroughs by ascending line number to create a coherent trace *)
let sorted_passthroughs =
IList.sort
(fun passthrough1 passthrough2 ->
let loc1 = CallSite.loc (Passthrough.site passthrough1) in
let loc2 = CallSite.loc (Passthrough.site passthrough2) in
Pervasives.compare loc1.Location.line loc2.Location.line)
(Passthroughs.elements passthroughs) in
IList.fold_right trace_elem_of_passthrough sorted_passthroughs acc0 in
let get_nesting should_nest elems start_nesting =
let level = ref start_nesting in
let get_nesting_ ((elem, _) as pair) =
if should_nest elem
then incr level;
pair, !level in
IList.map get_nesting_ (IList.rev elems) in
let trace_elems_of_path_elem call_site desc ~is_source ((elem, passthroughs), lt_level) acc =
let desc = desc elem in
let loc = CallSite.loc (call_site elem) in
if is_source
then
let trace_elem = Errlog.make_trace_element lt_level loc desc [] in
trace_elems_of_passthroughs (lt_level + 1) passthroughs (trace_elem :: acc)
else
let trace_elem = Errlog.make_trace_element (lt_level - 1) loc desc [] in
trace_elem :: (trace_elems_of_passthroughs lt_level passthroughs acc) in
let trace_elems_of_source =
trace_elems_of_path_elem Source.call_site desc_of_source ~is_source:true in
let trace_elems_of_sink =
trace_elems_of_path_elem Sink.call_site desc_of_sink ~is_source:false in
let sources_with_level = get_nesting source_should_nest sources (-1) in
let sinks_with_level = get_nesting sink_should_nest sinks 0 in
let trace_prefix =
IList.fold_right trace_elems_of_sink sinks_with_level []
|> trace_elems_of_passthroughs 0 passthroughs in
IList.fold_left
(fun acc source -> trace_elems_of_source source acc) trace_prefix sources_with_level
let of_source source =
let sources = Sources.singleton source in

@ -176,8 +176,9 @@ module Make (TaintSpec : TaintSpec.S) = struct
let caller_pname = Procdesc.get_proc_name proc_data.pdesc in
let msg = Localise.to_string Localise.quandary_taint_error in
let trace_str = F.asprintf "%a" pp_path_short path in
let ltr = TraceDomain.to_loc_trace path in
let exn = Exceptions.Checkers (msg, Localise.verbatim_desc trace_str) in
Reporting.log_error caller_pname ~loc:(CallSite.loc callee_site) exn in
Reporting.log_error caller_pname ~loc:(CallSite.loc callee_site) ~ltr exn in
let reported_sinks =
IList.map

Loading…
Cancel
Save