diff --git a/infer/src/quandary/ClangTrace.ml b/infer/src/quandary/ClangTrace.ml index 7513e99a8..6adf99547 100644 --- a/infer/src/quandary/ClangTrace.ml +++ b/infer/src/quandary/ClangTrace.ml @@ -29,17 +29,21 @@ module SourceKind = struct let external_sources = List.map - ~f:(fun { QuandaryConfig.Source.procedure; kind; } -> - QualifiedCppName.Match.of_fuzzy_qual_names [procedure], kind) + ~f:(fun { QuandaryConfig.Source.procedure; kind; index; } -> + QualifiedCppName.Match.of_fuzzy_qual_names [procedure], kind, index) (QuandaryConfig.Source.of_json Config.quandary_sources) (* return Some(source kind) if [procedure_name] is in the list of externally specified sources *) let get_external_source qualified_pname = let return = None in List.find_map - ~f:(fun (qualifiers, kind) -> + ~f:(fun (qualifiers, kind, index) -> if QualifiedCppName.Match.match_qualifiers qualifiers qualified_pname - then Some (of_string kind, return) + then + let source_index = + try Some (int_of_string index) + with Failure _ -> return in + Some (of_string kind, source_index) else None) external_sources diff --git a/infer/src/quandary/QuandaryConfig.ml b/infer/src/quandary/QuandaryConfig.ml index bd0e5e3da..978fc25c9 100644 --- a/infer/src/quandary/QuandaryConfig.ml +++ b/infer/src/quandary/QuandaryConfig.ml @@ -14,7 +14,7 @@ module F = Format (** utilities for importing JSON specifications of sources/sinks into Quandary *) module Source = struct - type t = { procedure : string; kind : string; } + type t = { procedure : string; kind : string; index : string; } let of_json = function | `List sources -> @@ -22,7 +22,9 @@ module Source = struct let open Yojson.Basic in let procedure = Util.member "procedure" json |> Util.to_string in let kind = Util.member "kind" json |> Util.to_string in - { procedure; kind; } in + let index = + Util.member "index" json |> Util.to_string_option |> Option.value ~default:"return" in + { procedure; kind; index; } in List.map ~f:parse_source sources | _ -> [] diff --git a/infer/src/quandary/QuandaryConfig.mli b/infer/src/quandary/QuandaryConfig.mli index 4b2cf2f29..949a68e8c 100644 --- a/infer/src/quandary/QuandaryConfig.mli +++ b/infer/src/quandary/QuandaryConfig.mli @@ -12,7 +12,7 @@ open! IStd (** utilities for importing JSON specifications of sources/sinks into Quandary*) module Source : sig - type t = { procedure : string; kind : string; } + type t = { procedure : string; kind : string; index : string; } val of_json : [> `List of Yojson.Basic.json list ] -> t list end diff --git a/infer/tests/codetoanalyze/cpp/quandary/.inferconfig b/infer/tests/codetoanalyze/cpp/quandary/.inferconfig index a8c925212..8be6e13ae 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/.inferconfig +++ b/infer/tests/codetoanalyze/cpp/quandary/.inferconfig @@ -20,6 +20,11 @@ "procedure": "basics::Obj::string_source", "kind": "Other" }, + { + "procedure": "basics::Obj::taint_arg_source", + "kind": "Other", + "index": "0" + }, { "procedure": "allocs::allocation_source", "kind": "EnvironmentVariable" diff --git a/infer/tests/codetoanalyze/cpp/quandary/basics.cpp b/infer/tests/codetoanalyze/cpp/quandary/basics.cpp index 79b148ea4..3069ffb1e 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/basics.cpp +++ b/infer/tests/codetoanalyze/cpp/quandary/basics.cpp @@ -21,6 +21,7 @@ class Obj { static void* static_source() { return (void*)0; } static void static_sink(void*) {} std::string string_source(int i) { return ""; } + static int taint_arg_source(int* arg) { return 1; } void string_sink(std::string) {} std::string field1; std::string field2; @@ -130,4 +131,16 @@ void FN_via_passthrough_bad2(Obj* obj) { std::string laundered_source = id2(source); obj->string_sink(laundered_source); } + +void taint_arg_source_bad() { + int source; + Obj::taint_arg_source(&source); + __infer_taint_sink((void*)source); +} + +void taint_arg_source_ok() { + int source; + int ret = Obj::taint_arg_source(&source); + __infer_taint_sink((void*)ret); // return value is not a source +} } diff --git a/infer/tests/codetoanalyze/cpp/quandary/issues.exp b/infer/tests/codetoanalyze/cpp/quandary/issues.exp index 941d5c9cb..c70d7065c 100644 --- a/infer/tests/codetoanalyze/cpp/quandary/issues.exp +++ b/infer/tests/codetoanalyze/cpp/quandary/issues.exp @@ -1,10 +1,10 @@ -codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_brk_bad, 1, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to brk] -codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_calloc_bad1, 1, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to calloc] -codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_calloc_bad2, 1, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to calloc] -codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_malloc_bad, 1, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to malloc] -codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_reaalloc_bad1, 1, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to realloc] -codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_reaalloc_bad2, 1, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to realloc] -codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_sbrk_bad, 1, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to sbrk] +codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_brk_bad, 0, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to brk] +codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_calloc_bad1, 0, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to calloc] +codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_calloc_bad2, 0, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to calloc] +codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_malloc_bad, 0, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to malloc] +codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_reaalloc_bad1, 0, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to realloc] +codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_reaalloc_bad2, 0, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to realloc] +codetoanalyze/cpp/quandary/allocs.cpp, allocs::untrusted_sbrk_bad, 0, QUANDARY_TAINT_ERROR, [return from allocs::allocation_source,call to sbrk] codetoanalyze/cpp/quandary/basics.cpp, basics::object_source_sink_bad, 2, QUANDARY_TAINT_ERROR, [return from basics::Obj_method_source,call to basics::Obj_method_sink] codetoanalyze/cpp/quandary/basics.cpp, basics::propagateBad, 3, QUANDARY_TAINT_ERROR, [return from __infer_taint_source,flow through basics::id,call to basics::callSink,call to __infer_taint_sink] codetoanalyze/cpp/quandary/basics.cpp, basics::returnSourceToSinkBad, 2, QUANDARY_TAINT_ERROR, [return from __infer_taint_source,return from basics::returnSource,call to __infer_taint_sink] @@ -12,6 +12,7 @@ codetoanalyze/cpp/quandary/basics.cpp, basics::sourceThenCallSinkBad, 2, QUANDAR codetoanalyze/cpp/quandary/basics.cpp, basics::sourceToSinkDirectBad, 2, QUANDARY_TAINT_ERROR, [return from __infer_taint_source,call to __infer_taint_sink] codetoanalyze/cpp/quandary/basics.cpp, basics::static_source_sink_bad, 2, QUANDARY_TAINT_ERROR, [return from basics::Obj_static_source,call to basics::Obj_static_sink] codetoanalyze/cpp/quandary/basics.cpp, basics::string_source_bad, 2, QUANDARY_TAINT_ERROR, [return from basics::Obj_string_source,call to basics::Obj_string_sink] +codetoanalyze/cpp/quandary/basics.cpp, basics::taint_arg_source_bad, 3, QUANDARY_TAINT_ERROR, [return from basics::Obj_taint_arg_source,call to __infer_taint_sink] codetoanalyze/cpp/quandary/basics.cpp, basics::template_source_bad, 2, QUANDARY_TAINT_ERROR, [return from basics::template_source,call to __infer_taint_sink] codetoanalyze/cpp/quandary/basics.cpp, basics::via_field_bad1, 3, QUANDARY_TAINT_ERROR, [return from basics::template_source_>,call to basics::template_sink_>] codetoanalyze/cpp/quandary/basics.cpp, basics::via_field_bad2, 2, QUANDARY_TAINT_ERROR, [return from basics::template_source_>,call to basics::template_sink_>]