You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.2 KiB

(*
* 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! IStd
module F = Format
module L = Logging
module Kind = struct
type t =
| EnvironmentVariable (** source that was read from an environment variable *)
| Other (** for testing or uncategorized sources *)
| Unknown
[@@deriving compare]
let unknown = Unknown
let get pname _ = match pname with
| (Typ.Procname.ObjC_Cpp cpp_pname) as pname ->
begin
match Typ.Procname.objc_cpp_get_class_name cpp_pname, Typ.Procname.get_method pname with
| "InferTaint", "source" -> Some Other
| _ -> None
end
| (Typ.Procname.C _) as pname ->
begin
match Typ.Procname.to_string pname with
| "getenv" -> Some EnvironmentVariable
| "__infer_taint_source" -> Some Other
| _ -> None
end
| Typ.Procname.Block _ ->
None
| pname when BuiltinDecl.is_declared pname ->
None
| pname ->
failwithf "Non-C++ procname %a in C++ analysis@." Typ.Procname.pp pname
let get_tainted_formals pdesc _ =
Source.all_formals_untainted pdesc
let pp fmt = function
| EnvironmentVariable -> F.fprintf fmt "EnvironmentVariable"
| Other -> F.fprintf fmt "Other"
| Unknown -> F.fprintf fmt "Unknown"
end
module CppSource = Source.Make(Kind)
module SinkKind = struct
type t =
| ShellExec (** shell exec function *)
| Other (** for testing or uncategorized sinks *)
[@@deriving compare]
let get pname actuals _ =
let taint_all actuals kind ~report_reachable =
List.mapi
~f:(fun actual_num _ -> kind, actual_num, report_reachable)
actuals in
match pname with
| (Typ.Procname.ObjC_Cpp cpp_pname) as pname ->
begin
match Typ.Procname.objc_cpp_get_class_name cpp_pname, Typ.Procname.get_method pname with
| "InferTaint", "sink:" -> taint_all actuals Other ~report_reachable:true
| _ -> []
end
| Typ.Procname.C _ ->
begin
match Typ.Procname.to_string pname with
| "execl" | "execlp" | "execle" | "execv" | "execvp" ->
taint_all actuals ShellExec ~report_reachable:false
| "__infer_taint_sink" ->
[Other, 0, false]
| _ ->
[]
end
| Typ.Procname.Block _ ->
[]
| pname when BuiltinDecl.is_declared pname ->
[]
| pname ->
failwithf "Non-C++ procname %a in C++ analysis@." Typ.Procname.pp pname
let pp fmt = function
| ShellExec -> F.fprintf fmt "ShellExec"
| Other -> F.fprintf fmt "Other"
end
module CppSink = Sink.Make(SinkKind)
include
Trace.Make(struct
module Source = CppSource
module Sink = CppSink
let should_report source sink =
match Source.kind source, Sink.kind sink with
| EnvironmentVariable, ShellExec ->
true
| Other, Other ->
true
| _ ->
false
end)