Fixing Memory leak false positives in C++/ObjC

Summary: Follow up D3579581. We forget about memory acquired in resources with assumption that developers use raii and free memory in destructors.

Reviewed By: jvillard

Differential Revision: D3614056

fbshipit-source-id: 08fa112
master
Daiva Naudziuniene 8 years ago committed by Facebook Github Bot 6
parent 9a79e74380
commit ac9cabe677

@ -772,7 +772,11 @@ let collect_postconditions wl tenv pdesc : Paths.PathSet.t * Specs.Visitedset.t
let pathset = match pname with let pathset = match pname with
| Procname.ObjC_Cpp _ -> | Procname.ObjC_Cpp _ ->
if (Procname.is_constructor pname) then if (Procname.is_constructor pname) then
Paths.PathSet.map (Prop.remove_resource_attribute Sil.Racquire Sil.Rfile) pathset Paths.PathSet.map (fun prop ->
let prop = Prop.remove_resource_attribute Sil.Racquire Sil.Rfile prop in
let prop = Prop.remove_resource_attribute Sil.Racquire (Sil.Rmemory Sil.Mmalloc) prop in
Prop.remove_resource_attribute Sil.Racquire (Sil.Rmemory Sil.Mobjc) prop
) pathset
else pathset else pathset
| _ -> pathset in | _ -> pathset in

@ -0,0 +1,20 @@
/*
* Copyright (c) 2016 - 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.
*/
#include <stdlib.h>
struct MyResourceManager {
void* p;
MyResourceManager(size_t n) : p(malloc(sizeof(int) * n)) {}
~MyResourceManager() { free(p); }
};
void no_memory_leak() { MyResourceManager resource(1); }
void memory_leak() { void* p = malloc(sizeof(int)); }

@ -0,0 +1,35 @@
/*
* Copyright (c) 2016 - 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.
*/
#include <Foundation/NSObject.h>
#include <stdlib.h>
@interface A : NSObject
@property char* buffer;
@end
@implementation A
- (instancetype)initWithBuffer {
_buffer = malloc(sizeof(char));
return self;
}
- (void)dealloc {
free(_buffer);
}
@end
int main() {
[[A alloc] initWithBuffer];
return 0;
}

@ -0,0 +1,62 @@
/*
* Copyright (c) 2015 - 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.
*/
package endtoend.cpp.infer;
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 MemoryLeakRaiiTest {
public static final String FILE =
"infer/tests/codetoanalyze/cpp/errors/memory_leaks/raii_malloc.cpp";
private static ImmutableList<String> 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.createCPPInferCommandWithMLBuckets(folder, FILE, "cpp");
}
@Test
public void whenInferRunsOnObject_leakThenMLIsFound()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferCPP(inferCmd);
String[] methods = { "memory_leak" };
assertThat(
"Results should contain " + MEMORY_LEAK,
inferResults,
containsExactly(
MEMORY_LEAK,
FILE,
methods
)
);
}
}

@ -0,0 +1,67 @@
/*
* Copyright (c) 2013 - 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.
*/
package endtoend.objc.infer;
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 MemoryLeakRaiiTest {
public static final String memory_leak_file =
"infer/tests/codetoanalyze/objc/errors/" +
"memory_leaks_benchmark/MemoryLeakRaii.m";
private static ImmutableList<String> 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.createiOSInferCommandWithMLBuckets(
folder,
memory_leak_file,
"cf",
false);
}
@Test
public void matchErrors()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
String[] procedures = {};
assertThat(
"Results should contain the expected memory leak",
inferResults,
containsExactly(
MEMORY_LEAK,
memory_leak_file,
procedures
)
);
}
}
Loading…
Cancel
Save