From 9af4fe0b8edbcd8aeac6c6351fb95159d82b7b0d Mon Sep 17 00:00:00 2001 From: Artem Pianykh Date: Fri, 19 Jun 2020 07:06:32 -0700 Subject: [PATCH] [nullsafe] Add a FP test for null-checking assignment result Summary: Nullability of the assignment result is not refined in code snippets like: ``` while ((a = foo.getA()) != null) { nonNullableVal = a; } ``` Let's add a test for this. Reviewed By: jvillard Differential Revision: D22136218 fbshipit-source-id: 206c368d6 --- .../java/nullsafe/ReturnNotNullable.java | 12 ++++++++++++ infer/tests/codetoanalyze/java/nullsafe/issues.exp | 4 +++- .../java/nullsafe/third-party-signatures/java.sig | 3 ++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/infer/tests/codetoanalyze/java/nullsafe/ReturnNotNullable.java b/infer/tests/codetoanalyze/java/nullsafe/ReturnNotNullable.java index 33eef2c1c..5f7008799 100644 --- a/infer/tests/codetoanalyze/java/nullsafe/ReturnNotNullable.java +++ b/infer/tests/codetoanalyze/java/nullsafe/ReturnNotNullable.java @@ -214,4 +214,16 @@ public class ReturnNotNullable { field = 0; return field; } + + static class AssignmentResultCheck { + // T58407328 + public Throwable nullCheckAssignmentResultAsNonnull_FP(Throwable error) { + Throwable cause; + while ((cause = error.getCause()) != null) { + error = cause; + } + + return error; + } + } } diff --git a/infer/tests/codetoanalyze/java/nullsafe/issues.exp b/infer/tests/codetoanalyze/java/nullsafe/issues.exp index 1252781a4..5394c4ee3 100644 --- a/infer/tests/codetoanalyze/java/nullsafe/issues.exp +++ b/infer/tests/codetoanalyze/java/nullsafe/issues.exp @@ -302,7 +302,9 @@ codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestSecondParameter.test(java.lang.String,java.lang.String):void, 7, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`nullable(...)` is nullable and is not locally checked for null when calling `length()`.] codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestSecondParameter.test(java.lang.String,java.lang.String):void, 11, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`nullable(...)` is nullable and is not locally checked for null when calling `length()`.] codetoanalyze/java/nullsafe/PropagatesNullable.java, codetoanalyze.java.nullsafe_default.TestPropagatesNullable$TestSecondParameter.test(java.lang.String,java.lang.String):void, 15, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`nullable(...)` is nullable and is not locally checked for null when calling `length()`.] -codetoanalyze/java/nullsafe/ReturnNotNullable.java, Linters_dummy_method, 19, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ReturnNotNullable, codetoanalyze.java.nullsafe_default, issues: 9, curr_mode: "Default" +codetoanalyze/java/nullsafe/ReturnNotNullable.java, Linters_dummy_method, 19, ERADICATE_META_CLASS_NEEDS_IMPROVEMENT, no_bucket, INFO, [], ReturnNotNullable, codetoanalyze.java.nullsafe_default, issues: 11, curr_mode: "Default" +codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable$AssignmentResultCheck.nullCheckAssignmentResultAsNonnull_FP(java.lang.Throwable):java.lang.Throwable, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`nullCheckAssignmentResultAsNonnull_FP(...)`: return type is declared non-nullable but the method returns a nullable value: call to Throwable.getCause() at line 222 (declared nullable in nullsafe/third-party-signatures/java.sig at line 2).] +codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable$AssignmentResultCheck.nullCheckAssignmentResultAsNonnull_FP(java.lang.Throwable):java.lang.Throwable, 2, ERADICATE_NULLABLE_DEREFERENCE, no_bucket, WARNING, [`error` is nullable and is not locally checked for null when calling `getCause()`: call to Throwable.getCause() at line 222 (declared nullable in nullsafe/third-party-signatures/java.sig at line 2).] codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable$ConditionalAssignment.test(boolean):java.lang.Object, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`test(...)`: return type is declared non-nullable but the method returns a nullable value: field f1 at line 199.] codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable.constantToNullableIsOverannotated():java.lang.String, 0, ERADICATE_RETURN_OVER_ANNOTATED, no_bucket, ADVICE, [Method `constantToNullableIsOverannotated()` is annotated with `@Nullable` but never returns null.] codetoanalyze/java/nullsafe/ReturnNotNullable.java, codetoanalyze.java.nullsafe_default.ReturnNotNullable.getResourceNullable(java.lang.Class,java.lang.String):java.net.URL, 0, ERADICATE_RETURN_NOT_NULLABLE, no_bucket, WARNING, [`getResourceNullable(...)`: return type is declared non-nullable but the method returns a nullable value: call to Class.getResource(...) at line 177 (nullable according to nullsafe internal models).] diff --git a/infer/tests/codetoanalyze/java/nullsafe/third-party-signatures/java.sig b/infer/tests/codetoanalyze/java/nullsafe/third-party-signatures/java.sig index 6ca056345..f55cdc9af 100644 --- a/infer/tests/codetoanalyze/java/nullsafe/third-party-signatures/java.sig +++ b/infer/tests/codetoanalyze/java/nullsafe/third-party-signatures/java.sig @@ -1 +1,2 @@ -java.lang.String#concat(java.lang.String) \ No newline at end of file +java.lang.String#concat(java.lang.String) +java.lang.Throwable#getCause() @Nullable