From ea3e614cce749445078b4fe9c0f0786660ca804b Mon Sep 17 00:00:00 2001 From: Dulma Rodriguez Date: Tue, 30 Jun 2015 13:49:19 -0100 Subject: [PATCH] [clang] Adding support for NSMakeCollectable and CFMakeCollectable Summary: @public Adding support for NSMakeCollectable and CFMakeCollectable. Fixes issue https://github.com/facebook/infer/issues/116 Test Plan: Tested on the example of the issue https://github.com/facebook/infer/issues/116 and we don't get the leak there anymore. --- infer/models/objc/src/CoreFoundation/CFType.c | 5 ++ infer/src/clang/cFrontend_config.ml | 2 + infer/src/clang/cFrontend_config.mli | 2 + infer/src/clang/cTrans_models.ml | 3 +- .../NSMakeCollectableExample.m | 19 ++++++ .../endtoend/objc/NSMakeCollectableTest.java | 62 +++++++++++++++++++ 6 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 infer/models/objc/src/CoreFoundation/CFType.c create mode 100644 infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/NSMakeCollectableExample.m create mode 100644 infer/tests/endtoend/objc/NSMakeCollectableTest.java diff --git a/infer/models/objc/src/CoreFoundation/CFType.c b/infer/models/objc/src/CoreFoundation/CFType.c new file mode 100644 index 000000000..11f08b5f5 --- /dev/null +++ b/infer/models/objc/src/CoreFoundation/CFType.c @@ -0,0 +1,5 @@ +#import + +CFTypeRef CFMakeCollectable ( CFTypeRef cf ) { + return cf; +} diff --git a/infer/src/clang/cFrontend_config.ml b/infer/src/clang/cFrontend_config.ml index 2695c0aef..1997ee2e5 100644 --- a/infer/src/clang/cFrontend_config.ml +++ b/infer/src/clang/cFrontend_config.ml @@ -106,6 +106,8 @@ let cf_bridging_retain = "CFBridgingRetain" let cf_autorelease = "CFAutorelease" +let ns_make_collectable = "NSMakeCollectable" + let builtin_expect = "__builtin_expect" let builtin_memset_chk = "__builtin___memset_chk" diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index 25918f50f..8004e74af 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -103,6 +103,8 @@ val cf_bridging_retain : string val cf_autorelease : string +val ns_make_collectable : string + val builtin_expect : string val builtin_memset_chk : string diff --git a/infer/src/clang/cTrans_models.ml b/infer/src/clang/cTrans_models.ml index 8b8a0c50c..40c8ccbea 100644 --- a/infer/src/clang/cTrans_models.ml +++ b/infer/src/clang/cTrans_models.ml @@ -90,7 +90,8 @@ let is_toll_free_bridging pn_opt = let funct = (Procname.to_string pn) in funct = CFrontend_config.cf_bridging_release || funct = CFrontend_config.cf_bridging_retain || - funct = CFrontend_config.cf_autorelease + funct = CFrontend_config.cf_autorelease || + funct = CFrontend_config.ns_make_collectable | None -> false (** If the function is a builtin model, return the model, otherwise return the function *) diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/NSMakeCollectableExample.m b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/NSMakeCollectableExample.m new file mode 100644 index 000000000..5b523d211 --- /dev/null +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/NSMakeCollectableExample.m @@ -0,0 +1,19 @@ +#import + +@interface E : NSObject + +@end + +@implementation E + +- (CFReadStreamRef) readStream { + return nil; +} + +- (void) handleStreamError +{ + NSError *underlyingError = NSMakeCollectable( + [(NSError*)CFReadStreamCopyError((CFReadStreamRef)[self readStream]) autorelease]); +} + +@end diff --git a/infer/tests/endtoend/objc/NSMakeCollectableTest.java b/infer/tests/endtoend/objc/NSMakeCollectableTest.java new file mode 100644 index 000000000..5035db708 --- /dev/null +++ b/infer/tests/endtoend/objc/NSMakeCollectableTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013- Facebook. + * All rights reserved. + */ + +package endtoend.objc; + +import static org.hamcrest.MatcherAssert.assertThat; +import static utils.matchers.ResultContainsExactly.containsExactly; + +import com.google.common.collect.ImmutableList; + +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Test; + +import java.io.IOException; + +import utils.DebuggableTemporaryFolder; +import utils.InferException; +import utils.InferResults; +import utils.InferRunner; + +public class NSMakeCollectableTest { + + public static final String memory_leak_file = + "infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/NSMakeCollectableExample.m"; + + private static ImmutableList inferCmd; + + public static final String MEMORY_LEAK = "MEMORY_LEAK"; + + @ClassRule + public static DebuggableTemporaryFolder folder = + new DebuggableTemporaryFolder(); + + @BeforeClass + public static void runInfer() throws InterruptedException, IOException { + inferCmd = InferRunner.createObjCInferCommandWithMLBuckets( + folder, + memory_leak_file, + "cf", + false); + } + + @Test + public void whenInferRunsOnTestWithBucketingThenMLIsNotFound() + throws InterruptedException, IOException, InferException { + InferResults inferResults = InferRunner.runInferObjC(inferCmd); + String[] procedures = { + }; + assertThat( + "Results should not contain memory leak", + inferResults, + containsExactly( + MEMORY_LEAK, + memory_leak_file, + procedures)); + } + + +}