diff --git a/infer/src/checkers/SinkTrace.ml b/infer/src/checkers/SinkTrace.ml index ea9cd1cae..43771283e 100644 --- a/infer/src/checkers/SinkTrace.ml +++ b/infer/src/checkers/SinkTrace.ml @@ -43,6 +43,8 @@ module Make (TraceElem : TraceElem.S) = struct module Sink = MakeSink (TraceElem) let should_report _ _ = true + + let should_report_footprint _ _ = false end) type sink_path = Passthroughs.t * (Sink.t * Passthroughs.t) list diff --git a/infer/src/checkers/Source.ml b/infer/src/checkers/Source.ml index ed5aa08ad..fcc51d5cb 100644 --- a/infer/src/checkers/Source.ml +++ b/infer/src/checkers/Source.ml @@ -17,8 +17,6 @@ let all_formals_untainted pdesc = module type Kind = sig include TraceElem.Kind - val unknown : t - val get : Typ.Procname.t -> HilExp.t list -> Tenv.t -> (t * int option) option val get_tainted_formals : Procdesc.t -> Tenv.t -> (Mangled.t * Typ.t * t option) list diff --git a/infer/src/checkers/Source.mli b/infer/src/checkers/Source.mli index 96a00dbbe..d5cdbb320 100644 --- a/infer/src/checkers/Source.mli +++ b/infer/src/checkers/Source.mli @@ -15,9 +15,6 @@ val all_formals_untainted : Procdesc.t -> (Mangled.t * Typ.t * 'a option) list module type Kind = sig include TraceElem.Kind - val unknown : t - (** kind of an unknown source *) - val get : Typ.Procname.t -> HilExp.t list -> Tenv.t -> (t * int option) option (** return Some (kind) if the procedure with the given actuals is a taint source, None otherwise *) diff --git a/infer/src/checkers/Trace.ml b/infer/src/checkers/Trace.ml index 5c6c60ce8..c21954329 100644 --- a/infer/src/checkers/Trace.ml +++ b/infer/src/checkers/Trace.ml @@ -18,6 +18,8 @@ module type Spec = sig val should_report : Source.t -> Sink.t -> bool (** should a flow originating at source and entering sink be reported? *) + + val should_report_footprint : AccessPath.Abs.t -> Sink.t -> bool end module type S = sig @@ -54,10 +56,12 @@ module type S = sig module Sinks = Sink.Set module Passthroughs = Passthrough.Set - (** path from a source to a sink with passthroughs at each step in the call stack. the first set - of passthroughs are the ones in the "reporting" procedure that calls the first function in - both the source and sink stack *) - type path = Passthroughs.t * (Source.t * Passthroughs.t) list * (Sink.t * Passthroughs.t) list + type path_source = Known of Source.t | Footprint of AccessPath.Abs.t + + type path_sink = Sink.t + + type path = + Passthroughs.t * (path_source * Passthroughs.t) list * (path_sink * Passthroughs.t) list val empty : t @@ -70,7 +74,7 @@ module type S = sig val passthroughs : t -> Passthroughs.t (** get the passthroughs of the trace *) - val get_reports : ?cur_site:CallSite.t -> t -> (Source.t * Sink.t * Passthroughs.t) list + val get_reports : ?cur_site:CallSite.t -> t -> (path_source * path_sink * Passthroughs.t) list (** get the reportable source-sink flows in this trace. specifying [cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *) @@ -80,8 +84,8 @@ module type S = sig [cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *) val to_loc_trace : - ?desc_of_source:(Source.t -> string) -> ?source_should_nest:(Source.t -> bool) - -> ?desc_of_sink:(Sink.t -> string) -> ?sink_should_nest:(Sink.t -> bool) -> path + ?desc_of_source:(path_source -> string) -> ?source_should_nest:(path_source -> bool) + -> ?desc_of_sink:(path_sink -> string) -> ?sink_should_nest:(path_sink -> bool) -> path -> Errlog.loc_trace (** create a loc_trace from a path; [source_should_nest s] should be true when we are going one deeper into a call-chain, ie when lt_level should be bumper in the next loc_trace_elem, and @@ -115,6 +119,8 @@ module type S = sig val pp_path : Typ.Procname.t -> F.formatter -> path -> unit (** pretty-print a path in the context of the given procname *) + + val pp_path_source : F.formatter -> path_source -> unit end (** Expand a trace element (i.e., a source or sink) into a list of trace elements bottoming out in @@ -224,12 +230,23 @@ module Make (Spec : Spec) = struct type astate = t - type path = Passthroughs.t * (Source.t * Passthroughs.t) list * (Sink.t * Passthroughs.t) list + type path_source = Known of Source.t | Footprint of AccessPath.Abs.t + + type path_sink = Sink.t + + type path = + Passthroughs.t * (path_source * Passthroughs.t) list * (path_sink * Passthroughs.t) list let pp fmt t = F.fprintf fmt "%a -> %a via %a" Sources.pp t.sources Sinks.pp t.sinks Passthroughs.pp t.passthroughs + let get_path_source_call_site = function + | Known source + -> Source.call_site source + | Footprint _ + -> CallSite.dummy + let sources t = t.sources let sinks t = t.sinks @@ -258,13 +275,28 @@ module Make (Spec : Spec) = struct let report_source source sinks acc0 = let report_one sink acc = if Spec.should_report source sink && should_report_at_site source sink then - (source, sink, t.passthroughs) :: acc + (Known source, sink, t.passthroughs) :: acc else acc in Sinks.fold report_one sinks acc0 in + let report_footprint acc0 footprint_access_path (is_mem, _) = + let report_one sink acc = + if is_mem && Spec.should_report_footprint footprint_access_path sink then + (Footprint footprint_access_path, sink, t.passthroughs) :: acc + else acc + in + Sinks.fold report_one t.sinks acc0 + in let report_sources source acc = report_source source t.sinks acc in Sources.Known.fold report_sources t.sources.known [] + |> Sources.Footprint.fold report_footprint t.sources.footprint + + let pp_path_source fmt = function + | Known source + -> Source.pp fmt source + | Footprint access_path + -> AccessPath.Abs.pp fmt access_path let pp_path cur_pname fmt (cur_passthroughs, sources_passthroughs, sinks_passthroughs) = let pp_passthroughs fmt passthroughs = @@ -278,11 +310,11 @@ module Make (Spec : Spec) = struct in F.pp_print_list ~pp_sep pp_elem fmt elems_passthroughs in - let pp_sources = pp_elems Source.call_site in + let pp_sources = pp_elems get_path_source_call_site in let pp_sinks = pp_elems Sink.call_site in let original_source = fst (List.hd_exn sources_passthroughs) in let final_sink = fst (List.hd_exn sinks_passthroughs) in - F.fprintf fmt "Error: %a -> %a. Full trace:@.%a@.Current procedure %a %a@.%a" Source.pp + F.fprintf fmt "Error: %a -> %a. Full trace:@.%a@.Current procedure %a %a@.%a" pp_path_source original_source Sink.pp final_sink pp_sources sources_passthroughs Typ.Procname.pp cur_pname pp_passthroughs cur_passthroughs pp_sinks (List.rev sinks_passthroughs) @@ -312,41 +344,57 @@ module Make (Spec : Spec) = struct in Passthrough.Set.filter between_start_and_end passthroughs in - let expand_path source sink = - let sources_of_pname pname = - let trace = trace_of_pname pname in - (Sources.Known.elements (sources trace).known, passthroughs trace) - in - let sinks_of_pname pname = - let trace = trace_of_pname pname in - (Sinks.elements (sinks trace), passthroughs trace) - in - let sources_passthroughs = - let filter_passthroughs = filter_passthroughs_ Source in - SourceExpander.expand source ~elems_passthroughs_of_pname:sources_of_pname - ~filter_passthroughs - in - let sinks_passthroughs = - let filter_passthroughs = filter_passthroughs_ Sink in - SinkExpander.expand sink ~elems_passthroughs_of_pname:sinks_of_pname ~filter_passthroughs - in - (sources_passthroughs, sinks_passthroughs) + let expand_path path_source sink = + match path_source with + | Known source + -> let sources_of_pname pname = + let trace = trace_of_pname pname in + (Sources.Known.elements (sources trace).known, passthroughs trace) + in + let sinks_of_pname pname = + let trace = trace_of_pname pname in + (Sinks.elements (sinks trace), passthroughs trace) + in + let sources_passthroughs = + let filter_passthroughs = filter_passthroughs_ Source in + SourceExpander.expand source ~elems_passthroughs_of_pname:sources_of_pname + ~filter_passthroughs + |> List.map ~f:(fun (source, passthrough) -> (Known source, passthrough)) + in + let sinks_passthroughs = + let filter_passthroughs = filter_passthroughs_ Sink in + SinkExpander.expand sink ~elems_passthroughs_of_pname:sinks_of_pname + ~filter_passthroughs + in + (sources_passthroughs, sinks_passthroughs) + | Footprint _ + -> ([], []) in List.map - ~f:(fun (source, sink, passthroughs) -> - let sources_passthroughs, sinks_passthroughs = expand_path source sink in + ~f:(fun (path_source, sink, passthroughs) -> + let sources_passthroughs, sinks_passthroughs = expand_path path_source sink in let filtered_passthroughs = - filter_passthroughs_ Top_level (Source.call_site source) (Sink.call_site sink) - passthroughs + let source_site = + match path_source with + | Known source + -> Source.call_site source + | Footprint _ + -> Option.value ~default:CallSite.dummy cur_site + in + filter_passthroughs_ Top_level source_site (Sink.call_site sink) passthroughs in (filtered_passthroughs, sources_passthroughs, sinks_passthroughs)) (get_reports ?cur_site t) let to_loc_trace - ?(desc_of_source= fun source -> - let callsite = Source.call_site source in - Format.asprintf "return from %a" Typ.Procname.pp - (CallSite.pname callsite)) ?(source_should_nest= fun _ -> true) + ?(desc_of_source= function + | Known source + -> let callsite = Source.call_site source in + Format.asprintf "return from %a" Typ.Procname.pp + (CallSite.pname callsite) + | Footprint access_path + -> Format.asprintf "read from %a" AccessPath.Abs.pp access_path) + ?(source_should_nest= fun _ -> true) ?(desc_of_sink= fun sink -> let callsite = Sink.call_site sink in Format.asprintf "call to %a" Typ.Procname.pp (CallSite.pname callsite)) @@ -389,7 +437,7 @@ module Make (Spec : Spec) = struct 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 + trace_elems_of_path_elem get_path_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 diff --git a/infer/src/checkers/Trace.mli b/infer/src/checkers/Trace.mli index 08c141847..99d75e59f 100644 --- a/infer/src/checkers/Trace.mli +++ b/infer/src/checkers/Trace.mli @@ -18,6 +18,10 @@ module type Spec = sig val should_report : Source.t -> Sink.t -> bool (** should a flow originating at source and entering sink be reported? *) + + val should_report_footprint : AccessPath.Abs.t -> Sink.t -> bool + (** should a flow read from the environment via the given access path and entering sink be + reported? *) end module type S = sig @@ -56,10 +60,18 @@ module type S = sig module Sinks = Sink.Set module Passthroughs = Passthrough.Set + type path_source = + | Known of Source.t (** source originating from a called procedure *) + | Footprint of AccessPath.Abs.t + (** source read from an access path rooted in a parameter or global *) + + type path_sink = Sink.t + (** path from a source to a sink with passthroughs at each step in the call stack. the first set of passthroughs are the ones in the "reporting" procedure that calls the first function in both the source and sink stack *) - type path = Passthroughs.t * (Source.t * Passthroughs.t) list * (Sink.t * Passthroughs.t) list + type path = + Passthroughs.t * (path_source * Passthroughs.t) list * (path_sink * Passthroughs.t) list val empty : t (** the empty trace *) @@ -73,7 +85,7 @@ module type S = sig val passthroughs : t -> Passthroughs.t (** get the passthroughs of the trace *) - val get_reports : ?cur_site:CallSite.t -> t -> (Source.t * Sink.t * Passthroughs.t) list + val get_reports : ?cur_site:CallSite.t -> t -> (path_source * path_sink * Passthroughs.t) list (** get the reportable source-sink flows in this trace. specifying [cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *) @@ -83,8 +95,8 @@ module type S = sig [cur_site] restricts the reported paths to ones introduced by the call at [cur_site] *) val to_loc_trace : - ?desc_of_source:(Source.t -> string) -> ?source_should_nest:(Source.t -> bool) - -> ?desc_of_sink:(Sink.t -> string) -> ?sink_should_nest:(Sink.t -> bool) -> path + ?desc_of_source:(path_source -> string) -> ?source_should_nest:(path_source -> bool) + -> ?desc_of_sink:(path_sink -> string) -> ?sink_should_nest:(path_sink -> bool) -> path -> Errlog.loc_trace (** create a loc_trace from a path; [source_should_nest s] should be true when we are going one deeper into a call-chain, ie when lt_level should be bumper in the next loc_trace_elem, and @@ -120,6 +132,8 @@ module type S = sig val pp_path : Typ.Procname.t -> F.formatter -> path -> unit (** pretty-print a path in the context of the given procname *) + + val pp_path_source : F.formatter -> path_source -> unit end module Make (Spec : Spec) : S with module Source = Spec.Source and module Sink = Spec.Sink diff --git a/infer/src/quandary/ClangTrace.ml b/infer/src/quandary/ClangTrace.ml index 83e028d5c..8327cf94d 100644 --- a/infer/src/quandary/ClangTrace.ml +++ b/infer/src/quandary/ClangTrace.ml @@ -17,11 +17,8 @@ module SourceKind = struct | EnvironmentVariable (** source that was read from an environment variable *) | File (** source that was read from a file *) | Other (** for testing or uncategorized sources *) - | Unknown [@@deriving compare] - let unknown = Unknown - let of_string = function | "Endpoint" -> Endpoint (Mangled.from_string "NONE", Typ.Tvoid) @@ -111,9 +108,7 @@ module SourceKind = struct | File -> "File" | Other - -> "Other" - | Unknown - -> "Unknown" ) + -> "Other" ) end module CppSource = Source.Make (SourceKind) @@ -257,6 +252,22 @@ include Trace.Make (struct true | _, Other -> true - | Unknown, (Allocation | BufferAccess | ShellExec | SQL) - -> false + + let should_report_footprint footprint_access_path sink = + (* is this var a command line flag created by the popular C++ gflags library for creating + command-line flags (https://github.com/gflags/gflags)? *) + let is_gflag access_path = + let pvar_is_gflag pvar = + String.is_substring ~substring:"FLAGS_" (Pvar.get_simplified_name pvar) + in + match AccessPath.Abs.extract access_path with + | (Var.ProgramVar pvar, _), _ + -> Pvar.is_global pvar && pvar_is_gflag pvar + | _ + -> false + in + match Sink.kind sink + with Allocation | BufferAccess | Other | ShellExec | SQL -> + (* gflags globals come from the environment; treat them as sources for everything *) + is_gflag footprint_access_path end) diff --git a/infer/src/quandary/JavaTrace.ml b/infer/src/quandary/JavaTrace.ml index 4d94a2284..10a225d46 100644 --- a/infer/src/quandary/JavaTrace.ml +++ b/infer/src/quandary/JavaTrace.ml @@ -18,11 +18,8 @@ module SourceKind = struct | Other (** for testing or uncategorized sources *) | PrivateData (** private user or device-specific data *) | UserControlledURI (** resource locator controller by user *) - | Unknown [@@deriving compare] - let unknown = Unknown - let of_string = function | "Clipboard" -> Clipboard @@ -166,9 +163,7 @@ module SourceKind = struct | PrivateData -> "PrivateData" | Other - -> "Other" - | Unknown - -> "Unknown" ) + -> "Other" ) end module JavaSource = Source.Make (SourceKind) @@ -318,26 +313,28 @@ include Trace.Make (struct let should_report source sink = match (Source.kind source, Sink.kind sink) with - | PrivateData, Logging - (* logging private data issue *) - | Intent, StartComponent - (* intent reuse issue *) - | Intent, CreateIntent - (* intent configured with external values issue *) - | Intent, JavaScript - (* external data flows into JS: remote code execution risk *) - | PrivateData, JavaScript - (* leaking private data into JS *) - | UserControlledURI, (CreateIntent | StartComponent) - (* create intent/launch component from user-controlled URI *) - | UserControlledURI, CreateFile - (* create file from user-controller URI; potential path-traversal vulnerability *) - | Clipboard, (StartComponent | CreateIntent | JavaScript | CreateFile | HTML) - -> (* do something sensitive with user-controlled data from the clipboard *) - true - | Other, _ | _, Other - -> (* for testing purposes, Other matches everything *) - true - | _ - -> false + | PrivateData, Logging + (* logging private data issue *) + | Intent, StartComponent + (* intent reuse issue *) + | Intent, CreateIntent + (* intent configured with external values issue *) + | Intent, JavaScript + (* external data flows into JS: remote code execution risk *) + | PrivateData, JavaScript + (* leaking private data into JS *) + | UserControlledURI, (CreateIntent | StartComponent) + (* create intent/launch component from user-controlled URI *) + | UserControlledURI, CreateFile + (* create file from user-controller URI; potential path-traversal vulnerability *) + | Clipboard, (StartComponent | CreateIntent | JavaScript | CreateFile | HTML) + -> (* do something sensitive with user-controlled data from the clipboard *) + true + | Other, _ | _, Other + -> (* for testing purposes, Other matches everything *) + true + | _ + -> false + + let should_report_footprint _ _ = false end) diff --git a/infer/src/quandary/TaintAnalysis.ml b/infer/src/quandary/TaintAnalysis.ml index f83a3b64b..f91650dcf 100644 --- a/infer/src/quandary/TaintAnalysis.ml +++ b/infer/src/quandary/TaintAnalysis.ml @@ -94,11 +94,14 @@ module Make (TaintSpecification : TaintSpec.S) = struct let endpoints = (lazy (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 (Lazy.force endpoints) (Typ.Procname.java_get_class_name java_pname) - | _ + let is_endpoint = function + | TraceDomain.Known source -> ( + match CallSite.pname (TraceDomain.Source.call_site source) with + | Typ.Procname.Java java_pname + -> String.Set.mem (Lazy.force endpoints) (Typ.Procname.java_get_class_name java_pname) + | _ + -> false ) + | TraceDomain.Footprint _ -> false (** log any new reportable source-sink flows in [trace] *) @@ -114,12 +117,12 @@ module Make (TaintSpecification : TaintSpec.S) = struct | None -> TaintDomain.empty in - let get_short_trace_string original_source final_sink = - F.asprintf "%a -> %a%s" TraceDomain.Source.pp original_source TraceDomain.Sink.pp + let get_short_trace_string original_path_source final_sink = + F.asprintf "%a -> %a%s" TraceDomain.pp_path_source original_path_source TraceDomain.Sink.pp final_sink - (if is_endpoint original_source then ". Note: source is an endpoint." else "") + (if is_endpoint original_path_source then ". Note: source is an endpoint." else "") in - let report_one (source, sink, _) = + let report_one (path_source, sink, _) = let open TraceDomain in let rec expand_source source0 (report_acc, seen_acc as acc) = let kind = Source.kind source0 in @@ -190,7 +193,14 @@ module Make (TaintSpecification : TaintSpec.S) = struct | [] -> acc in - let expanded_sources, _ = expand_source source ([(None, source)], CallSite.Set.empty) in + let expanded_sources, _ = + match path_source with + | Known source + -> let sources, calls = expand_source source ([(None, source)], CallSite.Set.empty) in + (List.map ~f:(fun (ap_opt, source) -> (ap_opt, Known source)) sources, calls) + | Footprint _ + -> ([(None, path_source)], CallSite.Set.empty) + in let expanded_sinks, _ = expand_sink sink sink_indexes ([sink], CallSite.Set.empty) in let source_trace = let pp_access_path_opt fmt = function @@ -205,13 +215,18 @@ module Make (TaintSpecification : TaintSpec.S) = struct else access_path ) in List.map - ~f:(fun (access_path_opt, source) -> - let call_site = Source.call_site source in - let desc = - Format.asprintf "Return from %a%a" Typ.Procname.pp (CallSite.pname call_site) - pp_access_path_opt access_path_opt + ~f:(fun (access_path_opt, path_source) -> + let desc, loc = + match path_source with + | Known source + -> let call_site = Source.call_site source in + ( Format.asprintf "Return from %a%a" Typ.Procname.pp (CallSite.pname call_site) + pp_access_path_opt access_path_opt + , CallSite.loc call_site ) + | Footprint access_path + -> (Format.asprintf "Read from %a" AccessPath.Abs.pp access_path, Location.dummy) in - Errlog.make_trace_element 0 (CallSite.loc call_site) desc []) + Errlog.make_trace_element 0 loc desc []) expanded_sources in let sink_trace = @@ -223,9 +238,9 @@ module Make (TaintSpecification : TaintSpec.S) = struct expanded_sinks in let msg = IssueType.quandary_taint_error.unique_id in - let _, original_source = List.hd_exn expanded_sources in + let _, original_path_source = List.hd_exn expanded_sources in let final_sink = List.hd_exn expanded_sinks in - let trace_str = get_short_trace_string original_source final_sink in + let trace_str = get_short_trace_string original_path_source final_sink in let ltr = source_trace @ List.rev sink_trace in let exn = Exceptions.Checkers (msg, Localise.verbatim_desc trace_str) in Reporting.log_error proc_data.extras.summary ~loc:(CallSite.loc cur_site) ~ltr exn diff --git a/infer/src/unit/TaintTests.ml b/infer/src/unit/TaintTests.ml index e4f9850f3..3a814009a 100644 --- a/infer/src/unit/TaintTests.ml +++ b/infer/src/unit/TaintTests.ml @@ -16,8 +16,6 @@ module MockTrace = Trace.Make (struct module Source = Source.Make (struct include MockTraceElem - let unknown = CallSite.dummy - let get pname _ _ = if String.is_prefix ~prefix:"SOURCE" (Typ.Procname.to_string pname) then Some (CallSite.make pname Location.dummy, None) @@ -36,6 +34,8 @@ module MockTrace = Trace.Make (struct end) let should_report _ _ = false + + let should_report_footprint _ _ = false end) module MockTaintAnalysis = TaintAnalysis.Make (struct diff --git a/infer/src/unit/TraceTests.ml b/infer/src/unit/TraceTests.ml index 9a421bc1d..ab761cd34 100644 --- a/infer/src/unit/TraceTests.ml +++ b/infer/src/unit/TraceTests.ml @@ -12,9 +12,7 @@ module L = Logging module F = Format module MockTraceElem = struct - type t = Kind1 | Kind2 | Footprint | Unknown [@@deriving compare] - - let unknown = Unknown + type t = Kind1 | Kind2 | Footprint [@@deriving compare] let call_site _ = CallSite.dummy @@ -29,8 +27,6 @@ module MockTraceElem = struct -> F.fprintf fmt "Kind2" | Footprint -> F.fprintf fmt "Footprint" - | Unknown - -> F.fprintf fmt "Unknown" module Kind = struct type nonrec t = t @@ -81,10 +77,19 @@ module MockTrace = Trace.Make (struct let should_report source sink = [%compare.equal : MockTraceElem.t] (Source.kind source) (Sink.kind sink) + + let should_report_footprint _ _ = false end) let trace_equal t1 t2 = MockTrace.( <= ) ~lhs:t1 ~rhs:t2 && MockTrace.( <= ) ~lhs:t2 ~rhs:t1 +let source_equal path_source source = + match path_source with + | MockTrace.Known s + -> MockSource.equal s source + | MockTrace.Footprint _ + -> false + let tests = let source1 = MockSource.make MockTraceElem.Kind1 CallSite.dummy in let source2 = MockSource.make MockTraceElem.Kind2 CallSite.dummy in @@ -101,13 +106,11 @@ let tests = assert_equal (List.length reports) 2 ; assert_bool "Reports should contain source1 -> sink1" (List.exists - ~f:(fun (source, sink, _) -> - MockSource.equal source source1 && MockSink.equal sink sink1) + ~f:(fun (source, sink, _) -> source_equal source source1 && MockSink.equal sink sink1) reports) ; assert_bool "Reports should contain source2 -> sink2" (List.exists - ~f:(fun (source, sink, _) -> - MockSource.equal source source2 && MockSink.equal sink sink2) + ~f:(fun (source, sink, _) -> source_equal source source2 && MockSink.equal sink sink2) reports) in "get_reports" >:: get_reports_ diff --git a/infer/tests/codetoanalyze/cpp/quandary/execs.cpp b/infer/tests/codetoanalyze/cpp/quandary/execs.cpp index f5cba3a19..90c835b9f 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/execs.cpp +++ b/infer/tests/codetoanalyze/cpp/quandary/execs.cpp @@ -99,7 +99,7 @@ void customGetEnvOk() { return execl(NULL, source); } -void FN_exec_flag_bad() { execl(FLAGS_cli_string, NULL); } +void exec_flag_bad() { execl(FLAGS_cli_string, NULL); } void sql_on_env_var_bad() { std::string source = (std::string)std::getenv("ENV_VAR"); diff --git a/infer/tests/codetoanalyze/cpp/quandary/issues.exp b/infer/tests/codetoanalyze/cpp/quandary/issues.exp index 8a5ef903a..9a8907af6 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/issues.exp +++ b/infer/tests/codetoanalyze/cpp/quandary/issues.exp @@ -54,6 +54,7 @@ codetoanalyze/cpp/quandary/execs.cpp, execs::callExecBad, 29, QUANDARY_TAINT_ERR codetoanalyze/cpp/quandary/execs.cpp, execs::callExecBad, 31, QUANDARY_TAINT_ERROR, [Return from getenv,Call to execve] codetoanalyze/cpp/quandary/execs.cpp, execs::callExecBad, 33, QUANDARY_TAINT_ERROR, [Return from getenv,Call to system] codetoanalyze/cpp/quandary/execs.cpp, execs::callExecBad, 35, QUANDARY_TAINT_ERROR, [Return from getenv,Call to popen] +codetoanalyze/cpp/quandary/execs.cpp, execs::exec_flag_bad, 0, QUANDARY_TAINT_ERROR, [Read from &#GB$execs::FLAGS_cli_string*,Call to execl] codetoanalyze/cpp/quandary/execs.cpp, execs::sql_on_env_var_bad, 2, QUANDARY_TAINT_ERROR, [Return from getenv,Call to __infer_sql_sink] codetoanalyze/cpp/quandary/files.cpp, files::read_file_call_exec_bad1, 5, QUANDARY_TAINT_ERROR, [Return from std::basic_istream>_read,Call to execle] codetoanalyze/cpp/quandary/files.cpp, files::read_file_call_exec_bad2, 5, QUANDARY_TAINT_ERROR, [Return from std::basic_istream>_readsome,Call to execle]