[quandary] Allow sinks to have multiple taints

Reviewed By: jvillard

Differential Revision: D13163848

fbshipit-source-id: 929e4d0ea
master
Mehdi Bouaziz 6 years ago committed by Facebook Github Bot
parent 8de2b93cab
commit 8443cd73f6

@ -11,13 +11,13 @@ module F = Format
module type Kind = sig
include TraceElem.Kind
val get : Typ.Procname.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> (t * IntSet.t) option
val get : Typ.Procname.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> (t * IntSet.t) list
end
module type S = sig
include TraceElem.S
val get : CallSite.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> t option
val get : CallSite.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> t list
val indexes : t -> IntSet.t
@ -38,11 +38,8 @@ module Make (Kind : Kind) = struct
let make ?(indexes = IntSet.empty) kind site = {kind; site; indexes}
let get site actuals call_flags tenv =
match Kind.get (CallSite.pname site) actuals call_flags tenv with
| Some (kind, indexes) ->
Some {kind; site; indexes}
| None ->
None
Kind.get (CallSite.pname site) actuals call_flags tenv
|> List.rev_map ~f:(fun (kind, indexes) -> {kind; site; indexes})
let with_callsite t callee_site = {t with site= callee_site}

@ -10,14 +10,14 @@ open! IStd
module type Kind = sig
include TraceElem.Kind
val get : Typ.Procname.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> (t * IntSet.t) option
val get : Typ.Procname.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> (t * IntSet.t) list
(** return Some kind if the given procname/actuals are a sink, None otherwise *)
end
module type S = sig
include TraceElem.S
val get : CallSite.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> t option
val get : CallSite.t -> HilExp.t list -> CallFlags.t -> Tenv.t -> t list
(** return Some sink if the given call site/actuals are a sink, None otherwise *)
val indexes : t -> IntSet.t

@ -32,7 +32,7 @@ end
module MakeSink (TraceElem : TraceElem.S) = struct
include TraceElem
let get _ _ _ _ = None
let get _ _ _ _ = []
let indexes _ = IntSet.empty

@ -239,7 +239,7 @@ module SinkKind = struct
(* taint the nth parameter (0-indexed) *)
let taint_nth n kind actuals =
if n < List.length actuals then Some (kind, IntSet.singleton n) else None
if n < List.length actuals then [(kind, IntSet.singleton n)] else []
(* taint all parameters after the nth (exclusive) *)
@ -248,13 +248,13 @@ module SinkKind = struct
List.filter_mapi ~f:(fun actual_num _ -> Option.some_if (actual_num > n) actual_num) actuals
with
| [] ->
None
[]
| to_taint ->
Some (kind, IntSet.of_list to_taint)
[(kind, IntSet.of_list to_taint)]
let taint_all kind actuals =
Some (kind, IntSet.of_list (List.mapi ~f:(fun actual_num _ -> actual_num) actuals))
[(kind, IntSet.of_list (List.mapi ~f:(fun actual_num _ -> actual_num) actuals))]
(* return Some(sink kind) if [procedure_name] is in the list of externally specified sinks *)
@ -266,12 +266,14 @@ module SinkKind = struct
let kind = of_string kind in
try
let n = int_of_string index in
taint_nth n kind actuals
let taint = taint_nth n kind actuals in
Option.some_if (not (List.is_empty taint)) taint
with Failure _ ->
(* couldn't parse the index, just taint everything *)
taint_all kind actuals
Some (taint_all kind actuals)
else None )
external_sinks
|> Option.value ~default:[]
let get pname actuals _ _ =
@ -326,13 +328,13 @@ module SinkKind = struct
| Some (Const.Cint i) ->
(* check if the data kind might be CURLOPT_URL *)
IntLit.to_int i
|> Option.bind ~f:(fun n ->
if controls_request n then taint_after_nth 1 URL actuals else None )
|> Option.value_map ~default:[] ~f:(fun n ->
if controls_request n then taint_after_nth 1 URL actuals else [] )
| _ ->
(* can't statically resolve data kind; taint it just in case *)
taint_after_nth 1 URL actuals )
| None ->
None )
[] )
| "execl" | "execlp" | "execle" | "execv" | "execve" | "execvp" | "system" ->
taint_all ShellExec actuals
| "openat" ->
@ -353,7 +355,7 @@ module SinkKind = struct
| _ ->
get_external_sink pname actuals )
| Typ.Procname.Block _ ->
None
[]
| pname ->
L.(die InternalError) "Non-C++ procname %a in C++ analysis" Typ.Procname.pp pname

@ -331,12 +331,12 @@ module SinkKind = struct
let indexes =
IntSet.of_list (List.mapi ~f:(fun param_num _ -> param_num + offset) actuals_to_taint)
in
Some (kind, indexes)
Some [(kind, indexes)]
in
(* taint the nth non-"this" parameter (0-indexed) *)
let taint_nth n kind =
let first_index = if Typ.Procname.Java.is_static java_pname then n else n + 1 in
if first_index < List.length actuals then Some (kind, IntSet.singleton first_index)
if first_index < List.length actuals then Some [(kind, IntSet.singleton first_index)]
else None
in
let get_external_sink class_name method_name =
@ -444,8 +444,9 @@ module SinkKind = struct
in
PatternMatch.supertype_find_map_opt tenv taint_matching_supertype
(Typ.Name.Java.from_string (Typ.Procname.Java.get_class_name java_pname))
|> Option.value ~default:[]
| pname when BuiltinDecl.is_declared pname ->
None
[]
| pname ->
L.(die InternalError) "Non-Java procname %a in Java analysis" Typ.Procname.pp pname

@ -468,11 +468,8 @@ module Make (TaintSpecification : TaintSpec.S) = struct
proc_data.ProcData.tenv
in
let astate_acc_result =
match sinks with
| None ->
astate_acc
| Some sink ->
add_sink sink dummy_actuals astate proc_data dummy_call_site
List.fold sinks ~init:astate_acc ~f:(fun astate sink ->
add_sink sink dummy_actuals astate proc_data dummy_call_site )
in
add_sinks_for_access astate_acc_result ae
in
@ -671,13 +668,11 @@ module Make (TaintSpecification : TaintSpec.S) = struct
let astate_with_sink =
if List.is_empty actuals then astate
else
match
let sinks =
TraceDomain.Sink.get call_site actuals call_flags proc_data.ProcData.tenv
with
| Some sink ->
add_sink sink actuals astate proc_data call_site
| None ->
astate
in
List.fold sinks ~init:astate ~f:(fun astate sink ->
add_sink sink actuals astate proc_data call_site )
in
let astate_with_summary =
let sources = TraceDomain.Source.get call_site actuals proc_data.tenv in

@ -32,8 +32,8 @@ module MockTrace = Trace.Make (struct
let get pname _ _ _ =
if String.is_prefix ~prefix:"SINK" (Typ.Procname.to_string pname) then
Some (CallSite.make pname Location.dummy, IntSet.singleton 0)
else None
[(CallSite.make pname Location.dummy, IntSet.singleton 0)]
else []
end)
module Sanitizer = Sanitizer.Dummy

Loading…
Cancel
Save