From 14d01620d236e0435340a841ca3288c07d0c7445 Mon Sep 17 00:00:00 2001 From: Jeremy Dubreil Date: Tue, 26 Sep 2017 08:46:42 -0700 Subject: [PATCH] [infer][objc] example of nullable annotation suggestion on Objective C Summary: Example of combination between annotating fields with nullable and the biabduction analysis in Objective C Reviewed By: dulmarod Differential Revision: D5906016 fbshipit-source-id: b95c6e0 --- Makefile | 4 +- .../tests/codetoanalyze/cpp/nullable/Makefile | 1 - .../codetoanalyze/objc/checkers/Makefile | 19 +++++ .../codetoanalyze/objc/checkers/Nullable.m | 72 +++++++++++++++++++ .../codetoanalyze/objc/checkers/issues.exp | 9 +++ 5 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 infer/tests/codetoanalyze/objc/checkers/Makefile create mode 100644 infer/tests/codetoanalyze/objc/checkers/Nullable.m create mode 100644 infer/tests/codetoanalyze/objc/checkers/issues.exp diff --git a/Makefile b/Makefile index 620b47723..436e1f4a3 100644 --- a/Makefile +++ b/Makefile @@ -65,7 +65,7 @@ BUILD_SYSTEMS_TESTS += xcodebuild_no_xcpretty DIRECT_TESTS += \ objc_frontend objc_errors objc_linters objc_ioslints \ objcpp_frontend objcpp_linters objc_linters-for-test-only objcpp_linters-for-test-only \ - objc_linters-def-folder + objc_linters-def-folder objc_checkers ifneq ($(XCPRETTY),no) BUILD_SYSTEMS_TESTS += xcodebuild endif @@ -406,7 +406,7 @@ ifeq ($(BUILD_C_ANALYZERS),yes) test -d $(DESTDIR)$(libdir)/infer/infer/lib/linter_rules/ || \ $(MKDIR_P) $(DESTDIR)$(libdir)/infer/infer/lib/linter_rules test -d $(DESTDIR)$(libdir)/infer/infer/etc/ || \ - $(MKDIR_P) $(DESTDIR)$(libdir)/infer/infer/etc + $(MKDIR_P) $(DESTDIR)$(libdir)/infer/infer/etc endif ifeq ($(BUILD_JAVA_ANALYZERS),yes) test -d $(DESTDIR)$(libdir)/infer/infer/lib/java/ || \ diff --git a/infer/tests/codetoanalyze/cpp/nullable/Makefile b/infer/tests/codetoanalyze/cpp/nullable/Makefile index 0adceab72..2739f1b77 100644 --- a/infer/tests/codetoanalyze/cpp/nullable/Makefile +++ b/infer/tests/codetoanalyze/cpp/nullable/Makefile @@ -11,7 +11,6 @@ ANALYZER = checkers # see explanations in cpp/errors/Makefile for the custom isystem CLANG_OPTIONS = -x c++ -std=c++11 -nostdinc++ -isystem$(ROOT_DIR) -isystem$(CLANG_INCLUDES)/c++/v1/ -c INFER_OPTIONS = --biabduction --suggest-nullable --debug-exceptions --project-root $(TESTS_DIR) -INFER_OPTIONS += --debug INFERPRINT_OPTIONS = --issues-tests SOURCES = $(wildcard *.cpp) diff --git a/infer/tests/codetoanalyze/objc/checkers/Makefile b/infer/tests/codetoanalyze/objc/checkers/Makefile new file mode 100644 index 000000000..ebe9279c1 --- /dev/null +++ b/infer/tests/codetoanalyze/objc/checkers/Makefile @@ -0,0 +1,19 @@ +# Copyright (c) 2017 - present Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +TESTS_DIR = ../../.. + +ANALYZER = checkers +CLANG_OPTIONS = -c +INFER_OPTIONS = --biabduction --suggest-nullable --debug-exceptions --project-root $(TESTS_DIR) +INFERPRINT_OPTIONS = --issues-tests + +SOURCES = $(wildcard *.m) + +include $(TESTS_DIR)/clang.make + +infer-out/report.json: $(MAKEFILE_LIST) diff --git a/infer/tests/codetoanalyze/objc/checkers/Nullable.m b/infer/tests/codetoanalyze/objc/checkers/Nullable.m new file mode 100644 index 000000000..81b6f3d75 --- /dev/null +++ b/infer/tests/codetoanalyze/objc/checkers/Nullable.m @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +#import + +@interface T : NSObject +- (void)assignUnnanotatedFieldToNullBad; +@end + +@implementation T { + int* unnanotatedField; + int* __nullable nullableField; + int* nonnullField; +} + +- (void)assignNullableFieldToNullOkay { + nullableField = nil; +} + +- (void)assignUnnanotatedFieldToNullBad { + unnanotatedField = nil; +} + +- (void)assignNonnullFieldToNullBad { + nonnullField = nil; +} + +- (void)testNullableFieldForNullOkay { + if (nullableField == nil) { + } +} + +- (void)testUnnanotatedFieldForNullBad { + if (unnanotatedField == nil) { + } +} + +- (void)testNonnullFieldForNullBad { + if (nonnullField == nil) { + } +} + +- (void)dereferenceUnnanotatedFieldOkay { + *unnanotatedField = 42; +} + +- (void)dereferenceNonnullFieldOkay { + *nonnullField = 42; +} + +- (void)dereferenceNullableFieldBad { + *nullableField = 42; +} + +- (void)dereferenceUnnanotatedFieldAfterTestForNullBad { + if (unnanotatedField == nil) { + *unnanotatedField = 42; + } +} + +- (void)FP_dereferenceNonnullFieldAfterTestForNullOkay { + if (nonnullField == nil) { + *nonnullField = 42; + } +} + +@end diff --git a/infer/tests/codetoanalyze/objc/checkers/issues.exp b/infer/tests/codetoanalyze/objc/checkers/issues.exp new file mode 100644 index 000000000..a3edd6264 --- /dev/null +++ b/infer/tests/codetoanalyze/objc/checkers/issues.exp @@ -0,0 +1,9 @@ +codetoanalyze/objc/checkers/Nullable.m, T_FP_dereferenceNonnullFieldAfterTestForNullOkay, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnullField is compared to null here] +codetoanalyze/objc/checkers/Nullable.m, T_FP_dereferenceNonnullFieldAfterTestForNullOkay, 2, NULL_DEREFERENCE, [start of procedure FP_dereferenceNonnullFieldAfterTestForNullOkay,Condition is true] +codetoanalyze/objc/checkers/Nullable.m, T_assignNonnullFieldToNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnullField is assigned null here] +codetoanalyze/objc/checkers/Nullable.m, T_assignUnnanotatedFieldToNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is assigned null here] +codetoanalyze/objc/checkers/Nullable.m, T_dereferenceNullableFieldBad, 1, NULL_DEREFERENCE, [start of procedure dereferenceNullableFieldBad] +codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here] +codetoanalyze/objc/checkers/Nullable.m, T_dereferenceUnnanotatedFieldAfterTestForNullBad, 2, NULL_DEREFERENCE, [start of procedure dereferenceUnnanotatedFieldAfterTestForNullBad,Condition is true] +codetoanalyze/objc/checkers/Nullable.m, T_testNonnullFieldForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field nonnullField is compared to null here] +codetoanalyze/objc/checkers/Nullable.m, T_testUnnanotatedFieldForNullBad, 1, FIELD_SHOULD_BE_NULLABLE, [Field unnanotatedField is compared to null here]