diff --git a/infer/lib/python/inferlib/bucklib.py b/infer/lib/python/inferlib/bucklib.py index 7bcef0f19..391695cde 100644 --- a/infer/lib/python/inferlib/bucklib.py +++ b/infer/lib/python/inferlib/bucklib.py @@ -151,6 +151,21 @@ def get_key(e): e[issues.JSON_INDEX_LINE], e[issues.JSON_INDEX_QUALIFIER]) +def remove_eradicate_conflicts(report): + eradicate_warnings = { + (e[issues.JSON_INDEX_FILENAME], e[issues.JSON_INDEX_LINE]) + for e in report + if e[issues.JSON_INDEX_TYPE] == 'ERADICATE_NULL_METHOD_CALL' or + e[issues.JSON_INDEX_TYPE] == 'ERADICATE_NULL_FIELD_ACCESS'} + if eradicate_warnings == set(): + return report + else: + return [e for e in report + if e[issues.JSON_INDEX_TYPE] != 'NULL_DEREFERENCE' or + (e[issues.JSON_INDEX_FILENAME], e[issues.JSON_INDEX_LINE]) + not in eradicate_warnings] + + def merge_reports(report, collected): for e in report: key = get_key(e) @@ -168,6 +183,8 @@ def collect_results(buck_args, infer_args, start_time, targets): try: with zipfile.ZipFile(path) as jar: report = load_json_report(jar) + if not infer_args.no_filtering: + report = remove_eradicate_conflicts(report) merge_reports(report, collected_reports) except NotFoundInJar: pass diff --git a/infer/tests/build_systems/buck/Makefile b/infer/tests/build_systems/buck/Makefile index 7cae25d51..be3e0e72e 100644 --- a/infer/tests/build_systems/buck/Makefile +++ b/infer/tests/build_systems/buck/Makefile @@ -12,6 +12,7 @@ ANALYZER = checkers BUCK_TARGET = //infer/tests/build_systems/genrule/module2:module2 SOURCES = $(wildcard $(TESTS_DIR)/codetoanalyze/java/infer/*.java) OBJECTS = $(ROOT_DIR)/buck-out/gen/infer/tests/build_systems/genrule/module2/lib__module2__output/module2.jar +INFER_OPTIONS = --eradicate INFERPRINT_OPTIONS = --project-root $(ROOT_DIR) --issues-tests CLEAN_EXTRA = $(ROOT_DIR)/buck-out @@ -29,5 +30,5 @@ infer-out/report.json: $(JAVA_DEPS) $(JAVA_SOURCE_FILES) $(REMOVE_DIR) buck-out && \ $(call silent_on_success,Testing Buck Java integration,\ INFER_BIN=$(INFER_BIN) NO_BUCKD=1 \ - $(INFER_BIN) -a $(ANALYZER) --results-dir $(CURDIR)/infer-out -- \ + $(INFER_BIN) $(INFER_OPTIONS) -a $(ANALYZER) --results-dir $(CURDIR)/infer-out -- \ $(BUCK) build --deep --no-cache $(BUCK_TARGET)) diff --git a/infer/tests/build_systems/buck/issues.exp b/infer/tests/build_systems/buck/issues.exp index b2ecc4c00..56274286a 100644 --- a/infer/tests/build_systems/buck/issues.exp +++ b/infer/tests/build_systems/buck/issues.exp @@ -1,8 +1,11 @@ -infer/tests/build_systems/genrule/module1/Class1.java, void Class1.localNPE1(), 2, NULL_DEREFERENCE, [start of procedure localNPE1()] -infer/tests/build_systems/genrule/module2/Class2.java, void Class2.dereferenceInterTargetFieldBad(Class1), 1, NULL_DEREFERENCE, [start of procedure dereferenceInterTargetFieldBad(...)] -infer/tests/build_systems/genrule/module2/Class2.java, void Class2.dereferenceLocalNullableFieldBad(), 1, NULL_DEREFERENCE, [start of procedure dereferenceLocalNullableFieldBad()] -infer/tests/build_systems/genrule/module2/Class2.java, void Class2.followMethodDeclarationOnlyBad(SkipImplementationClass1), 2, NULL_DEREFERENCE, [start of procedure followMethodDeclarationOnlyBad(...),Skipping annotatedNullable(): method has no implementation,Definition of annotatedNullable()] -infer/tests/build_systems/genrule/module2/Class2.java, void Class2.interTargetAbstractNPEBad(Class1), 2, NULL_DEREFERENCE, [start of procedure interTargetAbstractNPEBad(...),Skipping abstractMayReturnNull(): abstract method,Definition of abstractMayReturnNull()] -infer/tests/build_systems/genrule/module2/Class2.java, void Class2.interTargetNPEBad(), 2, NULL_DEREFERENCE, [start of procedure interTargetNPEBad(),start of procedure returnsNull(),return from a call to String Class1.returnsNull()] -infer/tests/build_systems/genrule/module2/Class2.java, void Class2.interTargetNativeNPEBad(Class1), 2, NULL_DEREFERENCE, [start of procedure interTargetNativeNPEBad(...),Skipping nativeMayReturnNull(): method has no implementation,Definition of nativeMayReturnNull()] -infer/tests/build_systems/genrule/module2/Class2.java, void Class2.localNPE2Bad(), 2, NULL_DEREFERENCE, [start of procedure localNPE2Bad()] +infer/tests/build_systems/genrule/module1/Class1.java, Object Class1.unannotatedReturnNull(), 0, ERADICATE_RETURN_NOT_NULLABLE, [origin,Method `unannotatedReturnNull()` may return null but it is not annotated with `@Nullable`. (Origin: null constant at line 35)] +infer/tests/build_systems/genrule/module1/Class1.java, void Class1.localNPE1(), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj` in the call to `toString()` could be null. (Origin: null constant at line 26)] +infer/tests/build_systems/genrule/module2/Class2.java, int Class2.dereferenceInterTargetField2Bad(Class1), 1, ERADICATE_NULL_FIELD_ACCESS, [origin,Object `class1.field2` could be null when accessing field `Class1.x`. (Origin: field Class1.field2 at line 59)] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.dereferenceInterTargetField1Bad(Class1), 1, ERADICATE_NULL_METHOD_CALL, [origin,The value of `class1.field1` in the call to `toString()` could be null. (Origin: field Class1.field1 at line 55)] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.dereferenceLocalNullableFieldBad(), 1, ERADICATE_NULL_METHOD_CALL, [origin,The value of `Class2.field` in the call to `toString()` could be null. (Origin: field Class2.field at line 51)] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.dereferenceUnannotatedMethodReturningNullBad(Class1), 1, NULL_DEREFERENCE, [start of procedure dereferenceUnannotatedMethodReturningNullBad(...),start of procedure unannotatedReturnNull(),return from a call to Object Class1.unannotatedReturnNull()] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.followMethodDeclarationOnlyBad(SkipImplementationClass1), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj2` in the call to `toString()` could be null. (Origin: call to annotatedNullable() at line 41)] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.interTargetAbstractNPEBad(Class1), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj` in the call to `toString()` could be null. (Origin: call to abstractMayReturnNull() at line 31)] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.interTargetNPEBad(), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj` in the call to `toString()` could be null. (Origin: call to returnsNull() at line 26)] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.interTargetNativeNPEBad(Class1), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj` in the call to `toString()` could be null. (Origin: call to nativeMayReturnNull() at line 36)] +infer/tests/build_systems/genrule/module2/Class2.java, void Class2.localNPE2Bad(), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj` in the call to `toString()` could be null. (Origin: null constant at line 21)] diff --git a/infer/tests/build_systems/genrule/issues.exp b/infer/tests/build_systems/genrule/issues.exp index 60cf4a3b5..bd62ce963 100644 --- a/infer/tests/build_systems/genrule/issues.exp +++ b/infer/tests/build_systems/genrule/issues.exp @@ -1,5 +1,6 @@ -build_systems/genrule/module2/Class2.java, void Class2.dereferenceInterTargetFieldBad(Class1), 1, ERADICATE_NULL_METHOD_CALL, [origin,The value of `class1.field1` in the call to `toString()` could be null. (Origin: field Class1.field1 at line 55)] -build_systems/genrule/module2/Class2.java, void Class2.dereferenceLocalNullableFieldBad(), 1, ERADICATE_NULL_METHOD_CALL, [origin,The value of `Class2.field2` in the call to `toString()` could be null. (Origin: field Class2.field2 at line 51)] +build_systems/genrule/module2/Class2.java, int Class2.dereferenceInterTargetField2Bad(Class1), 1, ERADICATE_NULL_FIELD_ACCESS, [origin,Object `class1.field2` could be null when accessing field `Class1.x`. (Origin: field Class1.field2 at line 59)] +build_systems/genrule/module2/Class2.java, void Class2.dereferenceInterTargetField1Bad(Class1), 1, ERADICATE_NULL_METHOD_CALL, [origin,The value of `class1.field1` in the call to `toString()` could be null. (Origin: field Class1.field1 at line 55)] +build_systems/genrule/module2/Class2.java, void Class2.dereferenceLocalNullableFieldBad(), 1, ERADICATE_NULL_METHOD_CALL, [origin,The value of `Class2.field` in the call to `toString()` could be null. (Origin: field Class2.field at line 51)] build_systems/genrule/module2/Class2.java, void Class2.followMethodDeclarationOnlyBad(SkipImplementationClass1), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj2` in the call to `toString()` could be null. (Origin: call to annotatedNullable() at line 41)] build_systems/genrule/module2/Class2.java, void Class2.interTargetAbstractNPEBad(Class1), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj` in the call to `toString()` could be null. (Origin: call to abstractMayReturnNull() at line 31)] build_systems/genrule/module2/Class2.java, void Class2.interTargetNPEBad(), 2, ERADICATE_NULL_METHOD_CALL, [origin,The value of `obj` in the call to `toString()` could be null. (Origin: call to returnsNull() at line 26)] diff --git a/infer/tests/build_systems/genrule/module1/Class1.java b/infer/tests/build_systems/genrule/module1/Class1.java index 6ad802d7f..f5339c47b 100644 --- a/infer/tests/build_systems/genrule/module1/Class1.java +++ b/infer/tests/build_systems/genrule/module1/Class1.java @@ -15,6 +15,9 @@ public abstract class Class1 { public @Nullable Object field1; + public int x; + public @Nullable Class1 field2; + public static @Nullable String returnsNull() { return null; } @@ -28,4 +31,7 @@ public abstract class Class1 { public native @Nullable Object nativeMayReturnNull(); + public Object unannotatedReturnNull() { + return null; + } } diff --git a/infer/tests/build_systems/genrule/module2/Class2.java b/infer/tests/build_systems/genrule/module2/Class2.java index 3e31859fe..5e109c922 100644 --- a/infer/tests/build_systems/genrule/module2/Class2.java +++ b/infer/tests/build_systems/genrule/module2/Class2.java @@ -15,7 +15,7 @@ import genrule.module1.SkipImplementationClass1; public class Class2 { - @Nullable Object field2; + @Nullable Object field; void localNPE2Bad() { Object obj = null; @@ -48,11 +48,18 @@ public class Class2 { } void dereferenceLocalNullableFieldBad() { - field2.toString(); + field.toString(); } - void dereferenceInterTargetFieldBad(Class1 class1) { + void dereferenceInterTargetField1Bad(Class1 class1) { class1.field1.toString(); } + int dereferenceInterTargetField2Bad(Class1 class1) { + return class1.field2.x; + } + + void dereferenceUnannotatedMethodReturningNullBad(Class1 class1) { + class1.unannotatedReturnNull().toString(); + } }