Differential Revision: D3684879 fbshipit-source-id: 1b101aemaster
parent
36e2175293
commit
8f5542ed2f
@ -0,0 +1,93 @@
|
|||||||
|
(*
|
||||||
|
* Copyright (c) 2016 - present Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*)
|
||||||
|
|
||||||
|
open! Utils
|
||||||
|
|
||||||
|
module F = Format
|
||||||
|
module L = Logging
|
||||||
|
|
||||||
|
module type Spec = sig
|
||||||
|
module Source : Source.S
|
||||||
|
module Sink : Sink.S
|
||||||
|
|
||||||
|
(** should a flow originating at source and entering sink be reported? *)
|
||||||
|
val should_report : Source.t -> Sink.t -> bool
|
||||||
|
end
|
||||||
|
|
||||||
|
module type S = sig
|
||||||
|
include Spec
|
||||||
|
type t
|
||||||
|
|
||||||
|
(** get the source of the trace *)
|
||||||
|
val source : t -> Source.t
|
||||||
|
|
||||||
|
(** get the sink of the trace, if any *)
|
||||||
|
val sink : t -> Sink.t option
|
||||||
|
|
||||||
|
(** return true if this trace represent a dangerous flow *)
|
||||||
|
val should_report : t -> bool
|
||||||
|
|
||||||
|
(** create a trace from a source *)
|
||||||
|
val of_source : Source.t -> t
|
||||||
|
|
||||||
|
(** add a sink to the current trace. *)
|
||||||
|
val add_sink : t -> Sink.t -> t
|
||||||
|
|
||||||
|
val compare : t -> t -> int
|
||||||
|
val pp : F.formatter -> t -> unit
|
||||||
|
end
|
||||||
|
|
||||||
|
module Make (Spec : Spec) = struct
|
||||||
|
include Spec
|
||||||
|
|
||||||
|
type t =
|
||||||
|
{
|
||||||
|
source : Source.t; (** last function in the trace that returned tainted data *)
|
||||||
|
sink : Sink.t option;
|
||||||
|
(** last callee in the trace that transitively called a tainted function (if any) *)
|
||||||
|
passthroughs : Passthrough.Set.t; (** calls that occurred between source and sink *)
|
||||||
|
}
|
||||||
|
|
||||||
|
let compare t1 t2 =
|
||||||
|
let compare_sink_opts sink1_opt sink2_opt = match sink1_opt, sink2_opt with
|
||||||
|
| Some sink1, Some sink2 -> Sink.compare sink1 sink2
|
||||||
|
| None, None -> 0
|
||||||
|
| Some _, None -> (-1)
|
||||||
|
| None, Some _ -> 1 in
|
||||||
|
Source.compare t1.source t2.source
|
||||||
|
|> next compare_sink_opts t1.sink t2.sink
|
||||||
|
|> next Passthrough.Set.compare t1.passthroughs t2.passthroughs
|
||||||
|
|
||||||
|
let pp fmt t =
|
||||||
|
let pp_sink_opt fmt = function
|
||||||
|
| None -> F.fprintf fmt "?"
|
||||||
|
| Some sink -> Sink.pp fmt sink in
|
||||||
|
F.fprintf
|
||||||
|
fmt
|
||||||
|
"%a -> %a via %a"
|
||||||
|
Source.pp t.source pp_sink_opt t.sink Passthrough.Set.pp t.passthroughs
|
||||||
|
|
||||||
|
let source t =
|
||||||
|
t.source
|
||||||
|
|
||||||
|
let sink t =
|
||||||
|
t.sink
|
||||||
|
|
||||||
|
let should_report t = match t.sink with
|
||||||
|
| Some sink -> Spec.should_report t.source sink
|
||||||
|
| None -> false
|
||||||
|
|
||||||
|
let of_source source =
|
||||||
|
let passthroughs = Passthrough.Set.empty in
|
||||||
|
let sink = None in
|
||||||
|
{ source; passthroughs; sink; }
|
||||||
|
|
||||||
|
let add_sink t sink =
|
||||||
|
{ t with sink = Some sink; }
|
||||||
|
end
|
Loading…
Reference in new issue