diff --git a/infer/src/checkers/Sanitizer.ml b/infer/src/checkers/Sanitizer.ml new file mode 100644 index 000000000..1f2ec01dd --- /dev/null +++ b/infer/src/checkers/Sanitizer.ml @@ -0,0 +1,27 @@ +(* + * Copyright (c) 2017 - 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! IStd +module F = Format + +module type S = sig + type t [@@deriving compare] + + val get : Typ.Procname.t -> t option + + val pp : F.formatter -> t -> unit +end + +module Dummy = struct + type t = unit [@@deriving compare] + + let get _ = None + + let pp _ _ = () +end diff --git a/infer/src/checkers/Sanitizer.mli b/infer/src/checkers/Sanitizer.mli new file mode 100644 index 000000000..4bbd78b2f --- /dev/null +++ b/infer/src/checkers/Sanitizer.mli @@ -0,0 +1,23 @@ +(* + * Copyright (c) 2017 - 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! IStd +module F = Format + +(** Sanitizers for filtering traces in taint analysis *) +module type S = sig + type t [@@deriving compare] + + val get : Typ.Procname.t -> t option + (** Get the sanitizer that should be applied to the return value of given procedure, if any *) + + val pp : F.formatter -> t -> unit +end + +module Dummy : S diff --git a/infer/src/checkers/SinkTrace.ml b/infer/src/checkers/SinkTrace.ml index a3cd535ab..20d139cb7 100644 --- a/infer/src/checkers/SinkTrace.ml +++ b/infer/src/checkers/SinkTrace.ml @@ -40,6 +40,7 @@ end module Make (TraceElem : TraceElem.S) = struct include Trace.Make (struct module Source = Source.Dummy + module Sanitizer = Sanitizer.Dummy module Sink = MakeSink (TraceElem) let get_report _ _ = Some IssueType.do_not_report diff --git a/infer/src/checkers/Trace.ml b/infer/src/checkers/Trace.ml index c8b175d0f..9b269e4e5 100644 --- a/infer/src/checkers/Trace.ml +++ b/infer/src/checkers/Trace.ml @@ -16,6 +16,8 @@ module type Spec = sig module Sink : Sink.S + module Sanitizer : Sanitizer.S + val get_report : Source.t -> Sink.t -> IssueType.t option end diff --git a/infer/src/checkers/Trace.mli b/infer/src/checkers/Trace.mli index 1fc3439d4..d44cbd407 100644 --- a/infer/src/checkers/Trace.mli +++ b/infer/src/checkers/Trace.mli @@ -16,6 +16,8 @@ module type Spec = sig module Sink : Sink.S + module Sanitizer : Sanitizer.S + val get_report : Source.t -> Sink.t -> IssueType.t option (** return Some(issue) if the source and sink match, None otherwise *) end diff --git a/infer/src/quandary/ClangTaintAnalysis.ml b/infer/src/quandary/ClangTaintAnalysis.ml index 76e92422d..53906d5dc 100644 --- a/infer/src/quandary/ClangTaintAnalysis.ml +++ b/infer/src/quandary/ClangTaintAnalysis.ml @@ -98,23 +98,5 @@ include TaintAnalysis.Make (struct | _ -> None - - let external_sanitizers = - List.map - ~f:(fun {QuandaryConfig.Sanitizer.procedure} -> - QualifiedCppName.Match.of_fuzzy_qual_names [procedure]) - (QuandaryConfig.Sanitizer.of_json Config.quandary_sanitizers) - - - let get_sanitizer pname = - let qualified_pname = Typ.Procname.get_qualifiers pname in - List.find_map - ~f:(fun qualifiers -> - if QualifiedCppName.Match.match_qualifiers qualifiers qualified_pname then - Some TaintSpec.Return - else None) - external_sanitizers - - let is_taintable_type _ = true end) diff --git a/infer/src/quandary/ClangTrace.ml b/infer/src/quandary/ClangTrace.ml index 07c410324..72fa3797b 100644 --- a/infer/src/quandary/ClangTrace.ml +++ b/infer/src/quandary/ClangTrace.ml @@ -297,9 +297,32 @@ end module CppSink = Sink.Make (SinkKind) +module CppSanitizer = struct + type t = All [@@deriving compare] + + let external_sanitizers = + List.map + ~f:(fun {QuandaryConfig.Sanitizer.procedure} -> + QualifiedCppName.Match.of_fuzzy_qual_names [procedure]) + (QuandaryConfig.Sanitizer.of_json Config.quandary_sanitizers) + + + let get pname = + let qualified_pname = Typ.Procname.get_qualifiers pname in + List.find_map + ~f:(fun qualifiers -> + if QualifiedCppName.Match.match_qualifiers qualifiers qualified_pname then Some All + else None) + external_sanitizers + + + let pp fmt = function All -> F.fprintf fmt "All" +end + include Trace.Make (struct module Source = CppSource module Sink = CppSink + module Sanitizer = CppSanitizer let get_report source sink = (* TODO: make this accept structs/objects too, but not primitive types or enumes *) diff --git a/infer/src/quandary/JavaTaintAnalysis.ml b/infer/src/quandary/JavaTaintAnalysis.ml index ba7ff4d28..5069f7adc 100644 --- a/infer/src/quandary/JavaTaintAnalysis.ml +++ b/infer/src/quandary/JavaTaintAnalysis.ml @@ -79,28 +79,6 @@ include TaintAnalysis.Make (struct let get_model _ _ _ _ _ = None - let external_sanitizers = - List.map - ~f:(fun {QuandaryConfig.Sanitizer.procedure} -> Str.regexp procedure) - (QuandaryConfig.Sanitizer.of_json Config.quandary_sanitizers) - - - let get_sanitizer = function - | Typ.Procname.Java java_pname -> - let procedure_string = - Printf.sprintf "%s.%s" - (Typ.Procname.java_get_class_name java_pname) - (Typ.Procname.java_get_method java_pname) - in - List.find_map - ~f:(fun procedure_regex -> - if Str.string_match procedure_regex procedure_string 0 then Some TaintSpec.Return - else None) - external_sanitizers - | _ -> - None - - let is_taintable_type typ = match typ.Typ.desc with | Typ.Tptr ({desc= Tstruct JavaClass typename}, _) | Tstruct JavaClass typename -> ( diff --git a/infer/src/quandary/JavaTrace.ml b/infer/src/quandary/JavaTrace.ml index 037cf9887..9672bfaa5 100644 --- a/infer/src/quandary/JavaTrace.ml +++ b/infer/src/quandary/JavaTrace.ml @@ -349,9 +349,37 @@ end module JavaSink = Sink.Make (SinkKind) +module JavaSanitizer = struct + type t = All [@@deriving compare] + + let external_sanitizers = + List.map + ~f:(fun {QuandaryConfig.Sanitizer.procedure} -> Str.regexp procedure) + (QuandaryConfig.Sanitizer.of_json Config.quandary_sanitizers) + + + let get = function + | Typ.Procname.Java java_pname -> + let procedure_string = + Printf.sprintf "%s.%s" + (Typ.Procname.java_get_class_name java_pname) + (Typ.Procname.java_get_method java_pname) + in + List.find_map + ~f:(fun procedure_regex -> + if Str.string_match procedure_regex procedure_string 0 then Some All else None) + external_sanitizers + | _ -> + None + + + let pp fmt = function All -> F.fprintf fmt "All" +end + include Trace.Make (struct module Source = JavaSource module Sink = JavaSink + module Sanitizer = JavaSanitizer let get_report source sink = match (Source.kind source, Sink.kind sink) with diff --git a/infer/src/quandary/TaintAnalysis.ml b/infer/src/quandary/TaintAnalysis.ml index bcd35eeee..b73516494 100644 --- a/infer/src/quandary/TaintAnalysis.ml +++ b/infer/src/quandary/TaintAnalysis.ml @@ -627,13 +627,8 @@ module Make (TaintSpecification : TaintSpec.S) = struct | None -> astate_with_summary | Some ret_base -> - match TaintSpecification.get_sanitizer callee_pname with - | Some Return -> - (* clear the trace associated with the return value. ideally, we would - associate a kind with the sanitizer and only clear the trace when its - kind matches the source. but this gets complicated to do properly with - footprint sources, since we don't know their kind. so do the simple - thing for now. *) + match TraceDomain.Sanitizer.get callee_pname with + | Some _ -> TaintDomain.BaseMap.remove ret_base astate_with_summary | None -> astate_with_summary diff --git a/infer/src/quandary/TaintSpec.ml b/infer/src/quandary/TaintSpec.ml index 00a6e8884..3e54d5035 100644 --- a/infer/src/quandary/TaintSpec.ml +++ b/infer/src/quandary/TaintSpec.ml @@ -19,8 +19,6 @@ type action = (** Propagate taint from all non-receiver actuals to the receiver actual *) | Propagate_to_return (** Propagate taint from all actuals to the return value *) -type sanitizer = Return (** a sanitizer that removes taint from its return value *) - module type S = sig module Trace : Trace.S @@ -39,9 +37,6 @@ module type S = sig val is_taintable_type : Typ.t -> bool (** return true if the given typ can be tainted *) - val get_sanitizer : Typ.Procname.t -> sanitizer option - (** get the sanitizer associated with the given type, if any *) - val to_summary_access_tree : AccessTree.t -> QuandarySummary.AccessTree.t val of_summary_access_tree : QuandarySummary.AccessTree.t -> AccessTree.t diff --git a/infer/src/unit/TaintTests.ml b/infer/src/unit/TaintTests.ml index 36447ec4b..ae49fcfab 100644 --- a/infer/src/unit/TaintTests.ml +++ b/infer/src/unit/TaintTests.ml @@ -39,6 +39,8 @@ module MockTrace = Trace.Make (struct end) + module Sanitizer = Sanitizer.Dummy + let get_report _ _ = None end) @@ -55,8 +57,6 @@ module MockTaintAnalysis = TaintAnalysis.Make (struct let is_taintable_type _ = true let get_model _ _ _ _ _ = None - - let get_sanitizer _ = None end) module TestInterpreter = diff --git a/infer/src/unit/TraceTests.ml b/infer/src/unit/TraceTests.ml index 23a855447..4ae7caddc 100644 --- a/infer/src/unit/TraceTests.ml +++ b/infer/src/unit/TraceTests.ml @@ -79,6 +79,7 @@ end module MockTrace = Trace.Make (struct module Source = MockSource module Sink = MockSink + module Sanitizer = Sanitizer.Dummy let get_report source sink = if [%compare.equal : MockTraceElem.t] (Source.kind source) (Sink.kind sink) then @@ -139,4 +140,3 @@ let tests = "append" >:: append_ in "trace_domain_suite" >::: [get_reports; append] -