From bc4b1882dc56282217d05aefb64959c3e57ecdc0 Mon Sep 17 00:00:00 2001 From: Mitya Lyubarskiy Date: Thu, 17 Sep 2020 05:08:23 -0700 Subject: [PATCH] [nullsafe] Add a field to jsonbug_t: unvetted third party methods Summary: If the issue is related to the use of an unvetted third party method that can not be trusted, we record this fact. Reviewed By: ngorogiannis Differential Revision: D23705626 fbshipit-source-id: 851328fe5 --- infer/src/atd/jsonbug.atd | 1 + infer/src/integration/IssuesTest.ml | 5 +- infer/src/nullsafe/AnnotatedSignature.ml | 4 ++ infer/src/nullsafe/AnnotatedSignature.mli | 4 ++ infer/src/nullsafe/ClassLevelAnalysis.ml | 7 ++- infer/src/nullsafe/EradicateReporting.ml | 10 +--- infer/src/nullsafe/ErrorRenderingUtils.ml | 14 +++-- infer/src/nullsafe/NullsafeIssue.ml | 59 ++++++++++++++++++- infer/src/nullsafe/NullsafeIssue.mli | 4 ++ infer/src/nullsafe/ThirdPartyMethod.mli | 3 +- .../nullsafe/StrictModeForThirdParty.java | 37 ++++++++++++ .../codetoanalyze/java/nullsafe/issues.exp | 23 +++++--- .../some/test/pckg/ThirdPartyTestClass.java | 26 ++++++++ 13 files changed, 169 insertions(+), 28 deletions(-) diff --git a/infer/src/atd/jsonbug.atd b/infer/src/atd/jsonbug.atd index 4395831cb..3afac55d3 100644 --- a/infer/src/atd/jsonbug.atd +++ b/infer/src/atd/jsonbug.atd @@ -31,6 +31,7 @@ type nullsafe_meta_issue_info = { type nullsafe_extra = { class_name: string; package: string nullable; + ?unvetted_3rd_party: string list option; (* If the issue is related to the use of a not yet registered third-party methods, here's the list of their signatures *) ?meta_issue_info: nullsafe_meta_issue_info option (* Should be present if the issue is "nullsafe meta issue" *) } diff --git a/infer/src/integration/IssuesTest.ml b/infer/src/integration/IssuesTest.ml index e241cda31..73c1a82d7 100644 --- a/infer/src/integration/IssuesTest.ml +++ b/infer/src/integration/IssuesTest.ml @@ -8,8 +8,11 @@ open! IStd module F = Format -let pp_nullsafe_extra fmt Jsonbug_t.{class_name; package; meta_issue_info} = +let pp_nullsafe_extra fmt Jsonbug_t.{class_name; package; meta_issue_info; unvetted_3rd_party} = F.fprintf fmt "%s, %s" class_name (Option.value package ~default:"") ; + Option.iter unvetted_3rd_party ~f:(fun unvetted_3rd_party -> + let third_party_str = String.concat unvetted_3rd_party ~sep:"," in + F.fprintf fmt ", unvetted_3rd_party:[%s]" third_party_str ) ; Option.iter meta_issue_info ~f:(fun Jsonbug_t.{num_issues; curr_nullsafe_mode; can_be_promoted_to} -> let can_be_promoted_to_str = diff --git a/infer/src/nullsafe/AnnotatedSignature.ml b/infer/src/nullsafe/AnnotatedSignature.ml index c11c3e103..52717d1ba 100644 --- a/infer/src/nullsafe/AnnotatedSignature.ml +++ b/infer/src/nullsafe/AnnotatedSignature.ml @@ -36,6 +36,10 @@ and third_party_model_source = | InThirdPartyRepo of {filename: string; line_number: int} [@@deriving compare] +let get_non_virtual_params {params} = + match params with x :: tail when Mangled.is_this x.mangled -> tail | _ -> params + + (* get nullability of method's return type given its annotations and information about its params *) let nullability_for_return ~is_callee_in_trust_list ~nullsafe_mode ~is_third_party ret_type ret_annotations ~has_propagates_nullable_in_param = diff --git a/infer/src/nullsafe/AnnotatedSignature.mli b/infer/src/nullsafe/AnnotatedSignature.mli index 0e1253458..63dc3e21a 100644 --- a/infer/src/nullsafe/AnnotatedSignature.mli +++ b/infer/src/nullsafe/AnnotatedSignature.mli @@ -34,6 +34,10 @@ and third_party_model_source = | InThirdPartyRepo of {filename: string; line_number: int} [@@deriving compare] +val get_non_virtual_params : t -> param_signature list +(** List of params, not counting the optional first ("this") param used to represent non-static + methods. *) + val set_modelled_nullability : Procname.t -> t -> third_party_model_source -> bool * bool list -> t (** Override nullability for a function signature given its modelled nullability (for ret value and params) *) diff --git a/infer/src/nullsafe/ClassLevelAnalysis.ml b/infer/src/nullsafe/ClassLevelAnalysis.ml index 2f8d7ee96..372fea98a 100644 --- a/infer/src/nullsafe/ClassLevelAnalysis.ml +++ b/infer/src/nullsafe/ClassLevelAnalysis.ml @@ -182,7 +182,10 @@ let report_meta_issue_for_top_level_class tenv source_file class_name class_stru in let package = JavaClassName.package class_name in let class_name = JavaClassName.classname class_name in - let nullsafe_extra = Jsonbug_t.{class_name; package; meta_issue_info= Some meta_issue_info} in + let nullsafe_extra = + Jsonbug_t. + {class_name; package; meta_issue_info= Some meta_issue_info; unvetted_3rd_party= None} + in log_issue ~issue_log ~loc:class_loc ~severity ~nullsafe_extra issue_type description @@ -206,7 +209,7 @@ let analyze_nullsafe_annotations tenv source_file class_name class_struct issue_ let nullsafe_extra = let package = JavaClassName.package class_name in let class_name = JavaClassName.classname class_name in - Jsonbug_t.{class_name; package; meta_issue_info= None} + Jsonbug_t.{class_name; package; meta_issue_info= None; unvetted_3rd_party= None} in match NullsafeMode.check_problematic_class_annotation tenv class_name with | Ok () -> diff --git a/infer/src/nullsafe/EradicateReporting.ml b/infer/src/nullsafe/EradicateReporting.ml index 6d3cf7eef..ae4b2c894 100644 --- a/infer/src/nullsafe/EradicateReporting.ml +++ b/infer/src/nullsafe/EradicateReporting.ml @@ -15,13 +15,6 @@ let get_proc_name proc_attrs = Logging.die InternalError "Unexpected attempt to report a nullsafe error on a non-java method" -let get_nullsafe_extra proc_attrs = - let proc_name = get_proc_name proc_attrs in - let class_name = Procname.Java.get_simple_class_name proc_name in - let package = Procname.Java.get_package proc_name in - Some Jsonbug_t.{class_name; package; meta_issue_info= None} - - let report_error {IntraproceduralAnalysis.proc_desc; tenv; err_log} checker ?(field_name = None) nullsafe_issue = let proc_attrs = Procdesc.get_attributes proc_desc in @@ -29,7 +22,8 @@ let report_error {IntraproceduralAnalysis.proc_desc; tenv; err_log} checker ?(fi let description = NullsafeIssue.get_description nullsafe_issue in let severity = NullsafeIssue.get_severity nullsafe_issue in let loc = NullsafeIssue.get_loc nullsafe_issue in - let nullsafe_extra = get_nullsafe_extra proc_attrs in + let proc_name = get_proc_name proc_attrs in + let nullsafe_extra = Some (NullsafeIssue.get_nullsafe_extra nullsafe_issue proc_name) in let extras = Jsonbug_t.{nullsafe_extra; cost_degree= None; cost_polynomial= None} in let suppressed = Reporting.is_suppressed tenv proc_attrs issue_type ~field_name in if suppressed then Logging.debug Analysis Medium "Reporting is suppressed!@\n" diff --git a/infer/src/nullsafe/ErrorRenderingUtils.ml b/infer/src/nullsafe/ErrorRenderingUtils.ml index 8bcdcc1d9..8c7a78e5b 100644 --- a/infer/src/nullsafe/ErrorRenderingUtils.ml +++ b/infer/src/nullsafe/ErrorRenderingUtils.ml @@ -94,6 +94,7 @@ type message_info = ; coming_from_explanation: string ; what_is_used: string ; recommendation: string + ; third_party_dependent_methods: (Procname.Java.t * AnnotatedSignature.t) list ; issue_type: IssueType.t } let get_field_class_name field_name = @@ -152,14 +153,14 @@ let mk_recommendation_for_third_party_field nullsafe_mode field = let get_info object_origin nullsafe_mode untrusted_kind = match object_origin with - | TypeOrigin.MethodCall {pname; call_loc} -> + | TypeOrigin.MethodCall {pname; call_loc; annotated_signature} -> let offending_object = F.asprintf "%a" MarkupFormatter.pp_monospaced (Procname.Java.to_simplified_string ~withclass:true pname) in let object_loc = call_loc in let what_is_used = "Result of this call" in - let coming_from_explanation, recommendation, issue_type = + let coming_from_explanation, recommendation, issue_type, third_party_dependent_methods = match untrusted_kind with | UserFriendlyNullable.ThirdPartyNonnull -> let suggested_third_party_sig_file = @@ -177,7 +178,8 @@ let get_info object_origin nullsafe_mode untrusted_kind = in ( "not vetted third party methods" , F.sprintf "add the correct signature to %s" where_to_add_signature - , IssueType.eradicate_unvetted_third_party_in_nullsafe ) + , IssueType.eradicate_unvetted_third_party_in_nullsafe + , [(pname, annotated_signature)] ) | UserFriendlyNullable.UncheckedNonnull | UserFriendlyNullable.LocallyCheckedNonnull -> let from = mk_coming_from_unchecked_or_locally_checked_case_only nullsafe_mode untrusted_kind @@ -188,12 +190,13 @@ let get_info object_origin nullsafe_mode untrusted_kind = untrusted_kind ~what_to_strictify in let issue_type = IssueType.eradicate_unchecked_usage_in_nullsafe in - (from, recommendation, issue_type) + (from, recommendation, issue_type, []) in { offending_object ; object_loc ; coming_from_explanation ; what_is_used + ; third_party_dependent_methods ; recommendation ; issue_type } | TypeOrigin.Field {field_name; access_loc} -> @@ -228,6 +231,7 @@ let get_info object_origin nullsafe_mode untrusted_kind = ; coming_from_explanation ; what_is_used ; recommendation + ; third_party_dependent_methods= [] ; issue_type } | other -> Logging.die InternalError @@ -243,6 +247,7 @@ let mk_nullsafe_issue_for_untrusted_values ~nullsafe_mode ~untrusted_kind ~bad_u ; coming_from_explanation ; what_is_used ; recommendation + ; third_party_dependent_methods ; issue_type } = get_info object_origin nullsafe_mode untrusted_kind in @@ -255,6 +260,7 @@ let mk_nullsafe_issue_for_untrusted_values ~nullsafe_mode ~untrusted_kind ~bad_u in NullsafeIssue.make ~description ~issue_type ~loc:object_loc ~severity:(NullsafeMode.severity nullsafe_mode) + |> NullsafeIssue.with_third_party_dependent_methods third_party_dependent_methods let find_alternative_nonnull_method_description nullable_origin = diff --git a/infer/src/nullsafe/NullsafeIssue.ml b/infer/src/nullsafe/NullsafeIssue.ml index 37cc56e43..79556b37b 100644 --- a/infer/src/nullsafe/NullsafeIssue.ml +++ b/infer/src/nullsafe/NullsafeIssue.ml @@ -11,9 +11,14 @@ type t = { issue_type: IssueType.t ; description: string (** Human-readable description *) ; loc: Location.t (** Where to report the error *) - ; severity: IssueType.severity } + ; severity: IssueType.severity + ; third_party_dependent_methods: (Procname.Java.t * AnnotatedSignature.t) list } -let make ~issue_type ~description ~loc ~severity = {issue_type; description; loc; severity} +let make ~issue_type ~description ~loc ~severity = + {issue_type; description; loc; severity; third_party_dependent_methods= []} + + +let with_third_party_dependent_methods methods t = {t with third_party_dependent_methods= methods} let get_issue_type {issue_type} = issue_type @@ -22,3 +27,53 @@ let get_description {description} = description let get_loc {loc} = loc let get_severity {severity} = severity + +let to_third_party_nullability = function + | AnnotatedNullability.Nullable _ -> + ThirdPartyMethod.Nullable + | _ -> + ThirdPartyMethod.Nonnull + + +(* Given a third party method, convert it to `.sig` format according to the current + source file annotations *) +let to_third_party_method_according_to_source_code_annotations (proc_name, annotated_signature) = + let ThirdPartyAnnotationInfo.{class_name; method_name; param_types} = + ThirdPartyAnnotationInfo.unique_repr_of_java_proc_name proc_name + in + (* We need to provide annotations for return value and param. + Do it according to the current annotations from the source code + (assuming everything not @Nullable is non-null). + *) + let ret_nullability = + annotated_signature.AnnotatedSignature.ret.ret_annotated_type.nullability + |> to_third_party_nullability + in + let params_nullability = + AnnotatedSignature.get_non_virtual_params annotated_signature + |> List.map ~f:(fun AnnotatedSignature.{param_annotated_type= {nullability}} -> + to_third_party_nullability nullability ) + in + let params = + match List.zip param_types params_nullability with + | Ok params -> + params + | Unequal_lengths -> + (* This can happen for some synthetic methods. In this case just fallback to non-nullable annotations. *) + List.map param_types ~f:(fun typ -> (typ, ThirdPartyMethod.Nonnull)) + in + ThirdPartyMethod.{class_name; method_name; ret_nullability; params} + + +let get_nullsafe_extra {third_party_dependent_methods} proc_name = + let class_name = Procname.Java.get_simple_class_name proc_name in + let package = Procname.Java.get_package proc_name in + let unvetted_3rd_party_list = + List.map third_party_dependent_methods + ~f:to_third_party_method_according_to_source_code_annotations + |> List.map ~f:ThirdPartyMethod.to_canonical_string + in + let unvetted_3rd_party = + if List.is_empty unvetted_3rd_party_list then None else Some unvetted_3rd_party_list + in + Jsonbug_t.{class_name; package; meta_issue_info= None; unvetted_3rd_party} diff --git a/infer/src/nullsafe/NullsafeIssue.mli b/infer/src/nullsafe/NullsafeIssue.mli index c8cb5e100..e202005fb 100644 --- a/infer/src/nullsafe/NullsafeIssue.mli +++ b/infer/src/nullsafe/NullsafeIssue.mli @@ -13,6 +13,8 @@ type t val make : issue_type:IssueType.t -> description:string -> loc:Location.t -> severity:IssueType.severity -> t +val with_third_party_dependent_methods : (Procname.Java.t * AnnotatedSignature.t) list -> t -> t + val get_issue_type : t -> IssueType.t val get_description : t -> string @@ -20,3 +22,5 @@ val get_description : t -> string val get_loc : t -> Location.t val get_severity : t -> IssueType.severity + +val get_nullsafe_extra : t -> Procname.Java.t -> Jsonbug_t.nullsafe_extra diff --git a/infer/src/nullsafe/ThirdPartyMethod.mli b/infer/src/nullsafe/ThirdPartyMethod.mli index 0050c04d7..c3d5e8553 100644 --- a/infer/src/nullsafe/ThirdPartyMethod.mli +++ b/infer/src/nullsafe/ThirdPartyMethod.mli @@ -34,8 +34,7 @@ val parse : string -> (t, parsing_error) result ["package.name.Class$NestedClass#foo(package.name.SomeClass, @Nullable package.name.OtherClass) @Nullable"] *) -(* used for testing *) -val to_canonical_string : t -> string [@@warning "-32"] +val to_canonical_string : t -> string val pp : Format.formatter -> t -> unit (** String representation as it can be parsed via [parse] diff --git a/infer/tests/codetoanalyze/java/nullsafe/StrictModeForThirdParty.java b/infer/tests/codetoanalyze/java/nullsafe/StrictModeForThirdParty.java index aeda79a3e..ca1236b78 100644 --- a/infer/tests/codetoanalyze/java/nullsafe/StrictModeForThirdParty.java +++ b/infer/tests/codetoanalyze/java/nullsafe/StrictModeForThirdParty.java @@ -8,6 +8,7 @@ package codetoanalyze.java.nullsafe; import com.facebook.infer.annotation.NullsafeStrict; +import java.util.List; import javax.annotation.Nullable; import some.test.pckg.ThirdPartyTestClass; @@ -79,4 +80,40 @@ public class StrictModeForThirdParty { // Independently of param signature, it is safe to pass non-nullables obj.secondParamSpecifiedAsNonnull(getNonnull(), getNonnull()); } + + // Below follow tests ensuring how we represent third party methods in the output .json file + // for interesting edge cases. + + // Expect the dependent third party signature to be correctly rendered in .json output as + // "some.test.pckg.ThirdPartyTestClass#genericObjectRepresentation(java.lang.Object, + // java.util.List)" + public String genericObjectRepresentation(String s, List l) { + return obj.generic(s, l); + } + + // Expect the dependent third party signature to be correctly rendered in .json output as + // "some.test.pckg.ThirdPartyTestClass#genericExtendsStringRepresentation(java.lang.String, + // java.util.List)" + public String genericExtendsStringRepresentation(String s, List l) { + return obj.genericString(s, l); + } + + // Expect the dependent third party signature to be correctly rendered in .json output as + // "some.test.pckg.ThirdPartyTestClass#arrayRepresentation(java.lang.String, java.lang.String[])" + public String arrayRepresentation(String s, String[] arr) { + return obj.array(s, arr); + } + + // Expect the dependent third party signature to be correctly rendered in .json output as + // "some.test.pckg.ThirdPartyTestClass#varargRepresentation(java.lang.String, java.lang.String[])" + public String varargRepresentation(String s) { + return obj.vararg(s, s, s, "Hello"); + } + + // Expect the dependent third party signature to be correctly rendered in .json output as + // "some.test.pckg.ThirdPartyTestClass#varargGenericRepresentation(java.lang.String, + // java.lang.String[])" + public String varargGenericRepresentation(String s) { + return obj.varargGeneric(s, s, s, "Hello"); + } } diff --git a/infer/tests/codetoanalyze/java/nullsafe/issues.exp b/infer/tests/codetoanalyze/java/nullsafe/issues.exp index 1e3e7d364..f4c70ace0 100644 --- a/infer/tests/codetoanalyze/java/nullsafe/issues.exp +++ b/infer/tests/codetoanalyze/java/nullsafe/issues.exp @@ -129,7 +129,7 @@ codetoanalyze/java/nullsafe/Lambdas.java, codetoanalyze.java.nullsafe.Lambdas$La codetoanalyze/java/nullsafe/Lambdas.java, codetoanalyze.java.nullsafe.Lambdas$Lambda$_28_1.apply(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `$bcvar1` of method `Lambdas$Lambda$_28_1.apply(...)` is missing `@Nullable` declaration when overriding `Lambdas$NullableFunction.apply(...)`. The parent method declared it can handle `null` for this param, so the child should also declare that.], Lambdas$Lambda$_28_1, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/Lambdas.java, codetoanalyze.java.nullsafe.Lambdas$Lambda$_29_1.apply(java.lang.Object):java.lang.Object, 0, ERADICATE_INCONSISTENT_SUBCLASS_PARAMETER_ANNOTATION, no_bucket, WARNING, [First parameter `$bcvar1` of method `Lambdas$Lambda$_29_1.apply(...)` is missing `@Nullable` declaration when overriding `Lambdas$NullableFunction.apply(...)`. The parent method declared it can handle `null` for this param, so the child should also declare that.], Lambdas$Lambda$_29_1, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/Lambdas.java, codetoanalyze.java.nullsafe.Lambdas$NullsafeClass.useJavaUtilFunction_UNSUPPORTED(java.util.function.Function):java.lang.String, 1, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, ERROR, [Third-party `Function.apply(...)` is missing a signature that would allow passing a nullable to param #1. Actual argument `getNullableString()` is nullable. Consider adding the correct signature of `Function.apply(...)` to nullsafe/third-party-signatures/java.sig.], Lambdas$NullsafeClass, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/Lambdas.java, codetoanalyze.java.nullsafe.Lambdas$NullsafeClass.useJavaUtilFunction_UNSUPPORTED(java.util.function.Function):java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`Function.apply(...)`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 143. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/java.sig.], Lambdas$NullsafeClass, codetoanalyze.java.nullsafe +codetoanalyze/java/nullsafe/Lambdas.java, codetoanalyze.java.nullsafe.Lambdas$NullsafeClass.useJavaUtilFunction_UNSUPPORTED(java.util.function.Function):java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`Function.apply(...)`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 143. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/java.sig.], Lambdas$NullsafeClass, codetoanalyze.java.nullsafe, unvetted_3rd_party:[java.util.function.Function#apply(java.lang.Object)] codetoanalyze/java/nullsafe/LibraryCalls.java, Linters_dummy_method, 16, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], LibraryCalls, codetoanalyze.java.nullsafe, issues: 5, curr_mode: "Default" codetoanalyze/java/nullsafe/LibraryCalls.java, codetoanalyze.java.nullsafe.LibraryCalls.badAtomicReferenceDereference(java.util.concurrent.atomic.AtomicReference):java.lang.String, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`ref.get()` is nullable and is not locally checked for null when calling `toString()`: call to AtomicReference.get() at line 35 (nullable according to nullsafe internal models).], LibraryCalls, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/LibraryCalls.java, codetoanalyze.java.nullsafe.LibraryCalls.badPhantomReferenceDereference(java.lang.ref.PhantomReference):java.lang.String, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`ref.get()` is nullable and is not locally checked for null when calling `toString()`: call to PhantomReference.get() at line 27 (nullable according to nullsafe internal models).], LibraryCalls, codetoanalyze.java.nullsafe @@ -214,11 +214,11 @@ codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe.Nul codetoanalyze/java/nullsafe/NullMethodCall.java, codetoanalyze.java.nullsafe.NullMethodCall.withConjuction(codetoanalyze.java.nullsafe.NullMethodCall$AnotherI,boolean,boolean):void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`i` is nullable and is not locally checked for null when calling `withBooleanParameter(...)`.], NullMethodCall, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/NullsafeMode.java, Linters_dummy_method, 16, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], NullsafeMode, codetoanalyze.java.nullsafe, issues: 13, curr_mode: "Default" codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$NullsafeWithStrictMode.BAD_returnFromNonStrict():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$VariousMethods.returnVal()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 174. Either add a local check for null or assertion, or make `NullsafeMode$VariousMethods` nullsafe strict.], NullsafeMode$NullsafeWithStrictMode, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$StrictNullsafe.BAD_dereferenceNotAnnotatedThirdParty():void, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 218. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$StrictNullsafe, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$StrictNullsafe.BAD_passThirdPartyToUnchecked():codetoanalyze.java.nullsafe.NullsafeMode$UncheckedParams, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.getUncheckedLong(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 214. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$StrictNullsafe, codetoanalyze.java.nullsafe +codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$StrictNullsafe.BAD_dereferenceNotAnnotatedThirdParty():void, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 218. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$StrictNullsafe, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#returnUnspecified()] +codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$StrictNullsafe.BAD_passThirdPartyToUnchecked():codetoanalyze.java.nullsafe.NullsafeMode$UncheckedParams, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.getUncheckedLong(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 214. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$StrictNullsafe, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#getUncheckedLong(long)] codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$StrictNullsafe.BAD_returnFromNonNullsafe():java.lang.String, 1, ERADICATE_UNCHECKED_USAGE_IN_NULLSAFE, no_bucket, ERROR, [`NullsafeMode$NonNullsafe.returnVal()`: `@NullsafeStrict` mode prohibits using values coming from non-strict classes without a check. Result of this call is used at line 197. Either add a local check for null or assertion, or make `NullsafeMode$NonNullsafe` nullsafe strict.], NullsafeMode$StrictNullsafe, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$TrustAllNullsafe.BAD_passThirdPartyToUnchecked():codetoanalyze.java.nullsafe.NullsafeMode$UncheckedParams, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.getUncheckedLong(...)`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 113. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$TrustAllNullsafe.BAD_returnFromUnvettedThirdParty():java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 92. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe +codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$TrustAllNullsafe.BAD_passThirdPartyToUnchecked():codetoanalyze.java.nullsafe.NullsafeMode$UncheckedParams, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.getUncheckedLong(...)`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 113. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#getUncheckedLong(long)] +codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$TrustAllNullsafe.BAD_returnFromUnvettedThirdParty():java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 92. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#returnUnspecified()] codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$TrustAllNullsafe.BAD_returnNonNullableFieldFromThirdParty():java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.nonNullableField`: `@NullsafeLocal(trust=all)` mode prohibits using values coming from third-party classes without a check. This field is used at line 100. Either add a local check for null or assertion, or access `nonNullableField` via a nullsafe getter.], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$TrustAllNullsafe.BAD_returnNullFromNonNulsafe():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`BAD_returnNullFromNonNulsafe()`: return type is declared non-nullable but the method returns a nullable value: call to returnNull() at line 89.], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/NullsafeMode.java, codetoanalyze.java.nullsafe.NullsafeMode$TrustAllNullsafe.BAD_returnNullableFieldFromThirdParty():java.lang.String, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, ERROR, [`BAD_returnNullableFieldFromThirdParty()`: return type is declared non-nullable but the method returns a nullable value: field nullableField at line 97.], NullsafeMode$TrustAllNullsafe, codetoanalyze.java.nullsafe @@ -350,12 +350,17 @@ codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict. codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.strictClass_dereferenceNullableFieldIsBad():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`__new(...).nullable` is nullable and is not locally checked for null when calling `toString()`.], Strict, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.strictClass_dereferenceNullableMethodIsBad():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`getNullable(...)` is nullable and is not locally checked for null when calling `toString()`: call to getNullable() at line 75.], Strict, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/StrictMode.java, codetoanalyze.java.nullsafe.Strict.strictClass_dereferenceNullableStaticMethodIsBad():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`staticNullable()` is nullable and is not locally checked for null when calling `toString()`.], Strict, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, Linters_dummy_method, 19, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], StrictModeForThirdParty, codetoanalyze.java.nullsafe, issues: 5, curr_mode: "Strict" -codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.dereferenceFieldIsBAD():void, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.nonNullableField`: `@NullsafeStrict` mode prohibits using values coming from third-party classes without a check. This field is used at line 49. Either add a local check for null or assertion, or access `nonNullableField` via a nullsafe strict getter.], StrictModeForThirdParty, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.dereferenceSpecifiedAsNullableIsBAD():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`StrictModeForThirdParty.obj.returnSpecifiedAsNullable()` is nullable and is not locally checked for null when calling `toString()`: call to ThirdPartyTestClass.returnSpecifiedAsNullable() at line 45 (declared nullable in nullsafe/third-party-signatures/some.test.pckg.sig at line 2).], StrictModeForThirdParty, codetoanalyze.java.nullsafe -codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.dereferenceUnspecifiedIsBAD():void, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 41. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, Linters_dummy_method, 20, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], StrictModeForThirdParty, codetoanalyze.java.nullsafe, issues: 10, curr_mode: "Strict" +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.arrayRepresentation(java.lang.String,java.lang.String[]):java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.array(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 103. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#array(java.lang.String, java.lang.String[])] +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.dereferenceFieldIsBAD():void, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.nonNullableField`: `@NullsafeStrict` mode prohibits using values coming from third-party classes without a check. This field is used at line 50. Either add a local check for null or assertion, or access `nonNullableField` via a nullsafe strict getter.], StrictModeForThirdParty, codetoanalyze.java.nullsafe +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.dereferenceSpecifiedAsNullableIsBAD():void, 1, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, ERROR, [`StrictModeForThirdParty.obj.returnSpecifiedAsNullable()` is nullable and is not locally checked for null when calling `toString()`: call to ThirdPartyTestClass.returnSpecifiedAsNullable() at line 46 (declared nullable in nullsafe/third-party-signatures/some.test.pckg.sig at line 2).], StrictModeForThirdParty, codetoanalyze.java.nullsafe +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.dereferenceUnspecifiedIsBAD():void, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.returnUnspecified()`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 42. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#returnUnspecified()] +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.genericExtendsStringRepresentation(java.lang.String,java.util.List):java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.genericString(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 97. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#genericString(java.lang.String, java.util.List)] +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.genericObjectRepresentation(java.lang.String,java.util.List):java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.generic(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 90. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#generic(java.lang.Object, java.util.List)] codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.passingNullableParamToUnspecifiedIsBAD():void, 1, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, ERROR, [Third-party `ThirdPartyTestClass.paramUnspecified(...)` is missing a signature that would allow passing a nullable to param #1(`param`). Actual argument `getNullable()` is nullable. Consider adding the correct signature of `ThirdPartyTestClass.paramUnspecified(...)` to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.passingNullableToParamSpecifiedAsNonnullIsBAD():void, 1, ERADICATE_PARAMETER_NOT_NULLABLE, no_bucket, ERROR, [`ThirdPartyTestClass.secondParamSpecifiedAsNonnull(...)`: parameter #2(`specifiedAsNonnull`) is declared non-nullable (see nullsafe/third-party-signatures/some.test.pckg.sig at line 3) but the argument `getNullable()` is nullable.], StrictModeForThirdParty, codetoanalyze.java.nullsafe +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.varargGenericRepresentation(java.lang.String):java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.varargGeneric(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 116. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#varargGeneric(java.lang.Object, java.lang.Object[])] +codetoanalyze/java/nullsafe/StrictModeForThirdParty.java, codetoanalyze.java.nullsafe.StrictModeForThirdParty.varargRepresentation(java.lang.String):java.lang.String, 1, ERADICATE_UNVETTED_THIRD_PARTY_IN_NULLSAFE, no_bucket, ERROR, [`ThirdPartyTestClass.vararg(...)`: `@NullsafeStrict` mode prohibits using values coming from not vetted third party methods without a check. Result of this call is used at line 109. Either add a local check for null or assertion, or add the correct signature to nullsafe/third-party-signatures/some.test.pckg.sig.], StrictModeForThirdParty, codetoanalyze.java.nullsafe, unvetted_3rd_party:[some.test.pckg.ThirdPartyTestClass#vararg(java.lang.String, java.lang.String[])] codetoanalyze/java/nullsafe/SwitchCase.java, Linters_dummy_method, 12, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], SwitchCase, codetoanalyze.java.nullsafe, issues: 2, curr_mode: "Default" codetoanalyze/java/nullsafe/SwitchCase.java, Linters_dummy_method, 63, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], Color, codetoanalyze.java.nullsafe, issues: 0, curr_mode: "Default" codetoanalyze/java/nullsafe/SwitchCase.java, codetoanalyze.java.nullsafe.SwitchCase.getNullableColor():codetoanalyze.java.nullsafe.Color, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, ADVICE, [Method `getNullableColor()` is annotated with `@Nullable` but never returns null.], SwitchCase, codetoanalyze.java.nullsafe diff --git a/infer/tests/codetoanalyze/java/nullsafe/third-party-test-code/some/test/pckg/ThirdPartyTestClass.java b/infer/tests/codetoanalyze/java/nullsafe/third-party-test-code/some/test/pckg/ThirdPartyTestClass.java index 1da037930..cf2268cd2 100644 --- a/infer/tests/codetoanalyze/java/nullsafe/third-party-test-code/some/test/pckg/ThirdPartyTestClass.java +++ b/infer/tests/codetoanalyze/java/nullsafe/third-party-test-code/some/test/pckg/ThirdPartyTestClass.java @@ -6,6 +6,7 @@ */ package some.test.pckg; +import java.util.List; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -67,4 +68,29 @@ public class ThirdPartyTestClass { public void secondParamSpecifiedAsNonnull( String specifiedAsNullable, String specifiedAsNonnull) {} + + // Special case: a generic method + public T generic(T obj, List list) { + return obj; + } + + // Special case: a generic method extending String + public T genericString(T obj, List list) { + return obj; + } + + // Special case: an array + public String array(String obj, String[] arr) { + return obj; + } + + // Special case: a variable argument + public String vararg(String obj, String... arr) { + return obj; + } + + // Special case: a variable argument generic + public T varargGeneric(T obj, T... arr) { + return obj; + } }