diff --git a/infer/src/quandary/JavaTrace.ml b/infer/src/quandary/JavaTrace.ml index 64256171d..191dd2df9 100644 --- a/infer/src/quandary/JavaTrace.ml +++ b/infer/src/quandary/JavaTrace.ml @@ -63,6 +63,15 @@ module SourceKind = struct let get pname actuals tenv = let return = None in + let get_external_source class_name method_name = + (* check the list of externally specified sources *) + let procedure = class_name ^ "." ^ method_name in + List.find_map + ~f:(fun (procedure_regex, kind) -> + if Str.string_match procedure_regex procedure 0 then Some (of_string kind, return) + else None ) + external_sources + in match pname with | Typ.Procname.Java pname -> ( match (Typ.Procname.Java.get_class_name pname, Typ.Procname.Java.get_method pname) with @@ -102,24 +111,11 @@ module SourceKind = struct Some (UserControlledString, return) | "android.widget.EditText", "getText" -> Some (UserControlledString, return) - | _ -> - None - in - let kind_opt = - PatternMatch.supertype_find_map_opt tenv taint_matching_supertype - (Typ.Name.Java.from_string class_name) + | class_name, method_name -> + get_external_source class_name method_name in - match kind_opt with - | Some _ -> - kind_opt - | None -> - (* check the list of externally specified sources *) - let procedure = class_name ^ "." ^ method_name in - List.find_map - ~f:(fun (procedure_regex, kind) -> - if Str.string_match procedure_regex procedure 0 then Some (of_string kind, return) - else None ) - external_sources ) + PatternMatch.supertype_find_map_opt tenv taint_matching_supertype + (Typ.Name.Java.from_string class_name) ) | Typ.Procname.C _ when Typ.Procname.equal pname BuiltinDecl.__global_access -> ( match (* accessed global will be passed to us as the only parameter *) actuals with @@ -335,6 +331,22 @@ module SinkKind = struct if first_index < List.length actuals then Some (kind, IntSet.singleton first_index) else None in + let get_external_sink class_name method_name = + (* check the list of externally specified sinks *) + let procedure = class_name ^ "." ^ method_name in + List.find_map + ~f:(fun (procedure_regex, kind, index) -> + if Str.string_match procedure_regex procedure 0 then + let kind = of_string kind in + try + let n = int_of_string index in + taint_nth n kind + with Failure _ -> + (* couldn't parse the index, just taint everything *) + taint_all kind + else None ) + external_sinks + in match (Typ.Procname.Java.get_class_name java_pname, Typ.Procname.Java.get_method java_pname) with @@ -407,20 +419,7 @@ module SinkKind = struct | "java.lang.Runtime", "exec" -> taint_nth 0 ShellExec | class_name, method_name -> - (* check the list of externally specified sinks *) - let procedure = class_name ^ "." ^ method_name in - List.find_map - ~f:(fun (procedure_regex, kind, index) -> - if Str.string_match procedure_regex procedure 0 then - let kind = of_string kind in - try - let n = int_of_string index in - taint_nth n kind - with Failure _ -> - (* couldn't parse the index, just taint everything *) - taint_all kind - else None ) - external_sinks + get_external_sink class_name method_name in PatternMatch.supertype_find_map_opt tenv taint_matching_supertype (Typ.Name.Java.from_string class_name) ) diff --git a/infer/tests/codetoanalyze/java/quandary/.inferconfig b/infer/tests/codetoanalyze/java/quandary/.inferconfig index 927113ef2..3bd7dec6a 100644 --- a/infer/tests/codetoanalyze/java/quandary/.inferconfig +++ b/infer/tests/codetoanalyze/java/quandary/.inferconfig @@ -4,6 +4,10 @@ { "procedure": "codetoanalyze.java.quandary.ExternalSpecs.privateData*", "kind": "PrivateData" + }, + { + "procedure": "codetoanalyze.java.quandary.InterfaceSpec.source", + "kind": "PrivateData" } ], "quandary-sinks": [ @@ -19,6 +23,10 @@ { "procedure": "codetoanalyze.java.quandary.ExternalSpecs.sinkThatPropagates", "kind": "Logging" + }, + { + "procedure": "codetoanalyze.java.quandary.InterfaceSpec.sink", + "kind": "Logging" } ], "quandary-sanitizers": [ diff --git a/infer/tests/codetoanalyze/java/quandary/ExternalSpecs.java b/infer/tests/codetoanalyze/java/quandary/ExternalSpecs.java index 70fb6498c..5b5f8d10d 100644 --- a/infer/tests/codetoanalyze/java/quandary/ExternalSpecs.java +++ b/infer/tests/codetoanalyze/java/quandary/ExternalSpecs.java @@ -125,3 +125,28 @@ public class ExternalSpecs { } } + +interface InterfaceSpec { + + // marked as source in .inferconfig + public Object source(); + + // marked as sink in .inferconfig + public void sink(Object o); +} + +class InterfaceSpecImpl implements InterfaceSpec { + + @Override + public Object source() { + return null; + } + + @Override + public void sink(Object o) {} + + public void externalSpecBad() { + sink(source()); + } + +} diff --git a/infer/tests/codetoanalyze/java/quandary/issues.exp b/infer/tests/codetoanalyze/java/quandary/issues.exp index a9f6593d9..9eb532f6e 100644 --- a/infer/tests/codetoanalyze/java/quandary/issues.exp +++ b/infer/tests/codetoanalyze/java/quandary/issues.exp @@ -50,6 +50,7 @@ codetoanalyze/java/quandary/ExternalSpecs.java, void ExternalSpecs.callExternalS codetoanalyze/java/quandary/ExternalSpecs.java, void ExternalSpecs.callSinkThatPropagatesBad(), 2, QUANDARY_TAINT_ERROR, ERROR, [Return from Object InferTaint.inferSecretSource(),Call to Object ExternalSpecs.sinkThatPropagates(Object) with tainted index 0] codetoanalyze/java/quandary/ExternalSpecs.java, void ExternalSpecs.callSinkThatPropagatesBad(), 3, QUANDARY_TAINT_ERROR, ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void ExternalSpecs.loggingSink1(Object,Object) with tainted index 1] codetoanalyze/java/quandary/ExternalSpecs.java, void ExternalSpecs.logExternalSourceBad(), 1, LOGGING_PRIVATE_DATA, ERROR, [Return from Object ExternalSpecs.privateDataSource(),Call to int Log.e(String,String) with tainted index 1] +codetoanalyze/java/quandary/ExternalSpecs.java, void InterfaceSpecImpl.externalSpecBad(), 1, LOGGING_PRIVATE_DATA, ERROR, [Return from Object InterfaceSpecImpl.source(),Call to void InterfaceSpecImpl.sink(Object) with tainted index 1] codetoanalyze/java/quandary/Fields.java, void Fields.instanceFieldBad(), 2, QUANDARY_TAINT_ERROR, ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void InferTaint.inferSensitiveSink(Object) with tainted index 0] codetoanalyze/java/quandary/Fields.java, void Fields.staticFieldBad(), 2, QUANDARY_TAINT_ERROR, ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void InferTaint.inferSensitiveSink(Object) with tainted index 0] codetoanalyze/java/quandary/Fields.java, void Fields.viaFieldBad1(Fields$Obj), 2, QUANDARY_TAINT_ERROR, ERROR, [Return from Object InferTaint.inferSecretSource(),Call to void InferTaint.inferSensitiveSink(Object) with tainted index 0]