You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
5.5 KiB

/*
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package codetoanalyze.java.infer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;
class LocalException extends IOException {}
class SomeResource implements Closeable {
void doSomething() throws LocalException {
if (!CloseableAsResourceExample.star()) {
throw new LocalException();
}
}
public void close() {}
native void foo(int i);
static native void bar(SomeResource r);
}
class Resource implements Closeable {
public Resource() {}
public void close() {}
}
class Wrapper implements Closeable {
Resource mR;
public Wrapper(Resource r) {
mR = r;
}
public void close() {
mR.close();
}
}
class Sub extends Wrapper {
public Sub(Resource r) {
super(r);
}
}
class ResourceWithException implements Closeable {
public void close() throws IOException {
if (CloseableAsResourceExample.star()) {
throw new IOException();
}
}
}
class ByteArrayOutputStreamWrapper extends ByteArrayOutputStream {}
class ByteArrayInputStreamWrapper extends ByteArrayInputStream {
public ByteArrayInputStreamWrapper(byte[] arr) {
super(arr);
}
}
public class CloseableAsResourceExample {
static native boolean star();
void closingCloseable() {
SomeResource res = new SomeResource();
res.close();
}
void notClosingCloseable() {
SomeResource res = new SomeResource();
} // should report a resource leak
void tryWithResource() {
try (SomeResource res = new SomeResource()) {
try {
res.doSomething();
} catch (LocalException e) {
// do nothing
}
}
}
void withException() throws LocalException {
SomeResource res = new SomeResource();
res.doSomething();
res.close();
} // should report a resource leak
void closingWrapper() {
Resource r = new Resource();
Sub s = new Sub(r);
s.close();
}
void notClosingWrapper() {
Sub s = new Sub(new Resource());
s.mR.close();
} // should report a resource leak
void noNeedToCloseStringReader() {
StringReader stringReader = new StringReader("paf!");
}
void noNeedToCloseByteArrayOutputStream() {
ByteArrayOutputStream stream = new ByteArrayOutputStream(42);
}
void noCloseByteArrayWrappersOk(byte[] array) {
ByteArrayOutputStreamWrapper stream1 = new ByteArrayOutputStreamWrapper();
ByteArrayInputStreamWrapper stream2 = new ByteArrayInputStreamWrapper(array);
}
void noNeedToCloseByteArrayInputStream(byte[] array) {
ByteArrayInputStream stream = new ByteArrayInputStream(array);
}
void closingWithCloseQuietly() {
SomeResource r = null;
try {
r = new SomeResource();
r.doSomething();
} catch (IOException e) {
} finally {
Utils.closeQuietly(r);
}
}
void failToCloseWithCloseQuietly() {
try {
SomeResource r = new SomeResource();
r.doSomething();
Utils.closeQuietly(r);
} catch (IOException e) {
}
}
void noLeakwithExceptionOnClose() throws IOException {
ResourceWithException res = new ResourceWithException();
res.close();
}
void noLeakWithCloseQuietlyAndExceptionOnClose() {
ResourceWithException res = new ResourceWithException();
Utils.closeQuietly(res);
}
static T sourceOfNullWithResourceLeak() {
SomeResource r = new SomeResource();
return null;
}
interface MyCloseable extends Closeable {}
class MyResource implements MyCloseable {
public void close() {}
}
void leakFoundWhenIndirectlyImplementingCloseable() {
MyResource res = new MyResource();
}
void skippedCallClosesResourceOnArgs() {
SomeResource res = new SomeResource();
SomeResource.bar(res);
}
void skippedVritualCallDoesNotCloseResourceOnReceiver() {
SomeResource res = new SomeResource();
res.foo(42);
}
Map returnsLocalMapContainingResourcesOk() {
HashMap<Integer, Closeable> map = new HashMap<>();
SomeResource res = new SomeResource();
Integer key = 42;
map.put(key, res);
return map;
}
void createsLocalMapContainingResourcesOk() {
HashMap<Integer, Closeable> map = new HashMap<>();
SomeResource res = new SomeResource();
Integer key = 42;
map.put(key, res);
map.clear();
}
HashMap<Integer, Closeable> resourceMap = new HashMap<>();
void fieldMapContainingResourcesOk() {
Integer key = 42;
SomeResource res = new SomeResource();
resourceMap.put(key, res);
}
// this case is not supported
void FN_notClearinglocalMapContainingResourcesBad() {
HashMap<Integer, Closeable> map = new HashMap<>();
SomeResource res = new SomeResource();
Integer key = 42;
map.put(key, res);
}
public static void closeCloseable(Closeable closeable) {
try {
if (closeable != null) {
closeable.close();
}
} catch (Exception ex) {
}
}
public void finallyCloseOk(File file, String fileContent) {
if (!file.exists()) {
FileWriter writer = null;
try {
writer = new FileWriter(file);
writer.write(fileContent);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
closeCloseable(writer);
}
}
}
}