From d470ed6edc0356eb55b11530ed1fd3c8cf07d81a Mon Sep 17 00:00:00 2001 From: Jeremy Dubreil Date: Mon, 22 May 2017 15:59:04 -0700 Subject: [PATCH] [infer][models] model java.io.BufferedReader as a wrapper Summary: This fixes a couple of false positives as objects of BufferedReader don't need to be closed if the wrapped reader resource gets closed correctly. Reviewed By: sblackshear Differential Revision: D5106596 fbshipit-source-id: 725fb80 --- .../java/src/java/io/BufferedReader.java | 73 ++++++++++++------- infer/tests/build_systems/ant/issues.exp | 2 +- infer/tests/build_systems/buck/issues.exp | 2 +- .../codetoanalyze/java/infer/ReaderLeaks.java | 15 +++- .../tests/codetoanalyze/java/infer/issues.exp | 6 +- 5 files changed, 62 insertions(+), 36 deletions(-) diff --git a/infer/models/java/src/java/io/BufferedReader.java b/infer/models/java/src/java/io/BufferedReader.java index 3d50101ff..5338dbb5f 100644 --- a/infer/models/java/src/java/io/BufferedReader.java +++ b/infer/models/java/src/java/io/BufferedReader.java @@ -13,32 +13,51 @@ import com.facebook.infer.builtins.InferUndefined; public abstract class BufferedReader { - public int read() throws IOException { - return InferUndefined.can_throw_ioexception_int(); + Reader mReader; + + public BufferedReader(Reader in) { + mReader = in; + } + + public BufferedReader(Reader in, int sz) { + mReader = in; + } + + public int read() throws IOException { + return InferUndefined.can_throw_ioexception_int(); + } + + public int read(char cbuf[]) throws IOException { + return InferUndefined.can_throw_ioexception_int(); + } + + public int read(char[] cbuf, int off, int len) throws IOException { + return InferUndefined.can_throw_ioexception_int(); + } + + public String readLine() throws IOException { + return InferUndefined.can_throw_ioexception_string(); + } + + public boolean ready() throws IOException { + return InferUndefined.can_throw_ioexception_boolean(); + } + + public void reset() throws IOException { + InferUndefined.can_throw_ioexception_void(); + } + + public long skip(long n) throws IOException { + return InferUndefined.can_throw_ioexception_long(); + } + + public void close() { + try { + if (mReader != null) { + mReader.close(); + } + } catch (Exception e) { + // Swallow exception } - - public int read(char cbuf[]) throws IOException { - return InferUndefined.can_throw_ioexception_int(); - } - - public int read(char[] cbuf, int off, int len) throws IOException { - return InferUndefined.can_throw_ioexception_int(); - } - - public String readLine() throws IOException { - return InferUndefined.can_throw_ioexception_string(); - } - - public boolean ready() throws IOException { - return InferUndefined.can_throw_ioexception_boolean(); - } - - public void reset() throws IOException { - InferUndefined.can_throw_ioexception_void(); - } - - public long skip(long n) throws IOException { - return InferUndefined.can_throw_ioexception_long(); - } - + } } diff --git a/infer/tests/build_systems/ant/issues.exp b/infer/tests/build_systems/ant/issues.exp index df837d483..30dd1f2af 100644 --- a/infer/tests/build_systems/ant/issues.exp +++ b/infer/tests/build_systems/ant/issues.exp @@ -118,7 +118,7 @@ codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions. codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.stringConstantEqualsFalseNotNPE_FP(), 10, NULL_DEREFERENCE, [start of procedure stringConstantEqualsFalseNotNPE_FP(),Taking false branch] codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.stringVarEqualsFalseNPE(), 5, NULL_DEREFERENCE, [start of procedure stringVarEqualsFalseNPE(),start of procedure getString2(),return from a call to String NullPointerExceptions.getString2(),Skipped call: function or method not found,Taking true branch] codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.testSystemGetPropertyReturn(), 2, NULL_DEREFERENCE, [start of procedure testSystemGetPropertyReturn()] -codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure bufferedReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] +codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure bufferedReaderNotClosedAfterRead(),exception java.io.IOException] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.fileReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure fileReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.inputStreamReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure inputStreamReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.pipedReaderFalsePositive(), 5, RESOURCE_LEAK, [start of procedure pipedReaderFalsePositive()] diff --git a/infer/tests/build_systems/buck/issues.exp b/infer/tests/build_systems/buck/issues.exp index fe0789c48..3b5caa9ce 100644 --- a/infer/tests/build_systems/buck/issues.exp +++ b/infer/tests/build_systems/buck/issues.exp @@ -118,7 +118,7 @@ infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointe infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.stringConstantEqualsFalseNotNPE_FP(), 10, NULL_DEREFERENCE, [start of procedure stringConstantEqualsFalseNotNPE_FP(),Taking false branch] infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.stringVarEqualsFalseNPE(), 5, NULL_DEREFERENCE, [start of procedure stringVarEqualsFalseNPE(),start of procedure getString2(),return from a call to String NullPointerExceptions.getString2(),Skipped call: function or method not found,Taking true branch] infer/tests/codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.testSystemGetPropertyReturn(), 2, NULL_DEREFERENCE, [start of procedure testSystemGetPropertyReturn()] -infer/tests/codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure bufferedReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] +infer/tests/codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure bufferedReaderNotClosedAfterRead(),exception java.io.IOException] infer/tests/codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.fileReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure fileReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] infer/tests/codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.inputStreamReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure inputStreamReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] infer/tests/codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.pipedReaderFalsePositive(), 5, RESOURCE_LEAK, [start of procedure pipedReaderFalsePositive()] diff --git a/infer/tests/codetoanalyze/java/infer/ReaderLeaks.java b/infer/tests/codetoanalyze/java/infer/ReaderLeaks.java index 41df66327..be140d654 100644 --- a/infer/tests/codetoanalyze/java/infer/ReaderLeaks.java +++ b/infer/tests/codetoanalyze/java/infer/ReaderLeaks.java @@ -11,6 +11,7 @@ package codetoanalyze.java.infer; import java.io.BufferedReader; import java.io.FileInputStream; +import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; @@ -21,6 +22,7 @@ import java.io.Reader; public class ReaderLeaks { + private void ignore(Object o) {} //Reader tests @@ -52,7 +54,7 @@ public class ReaderLeaks { BufferedReader reader; try { reader = new BufferedReader(new FileReader("testing.txt")); - reader.read(); + ignore(reader.read()); reader.close(); } catch (IOException e) { } @@ -62,13 +64,20 @@ public class ReaderLeaks { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("testing.txt")); - reader.read(); + ignore(reader.read()); } catch (IOException e) { } finally { if (reader != null) reader.close(); } } + public void noNeedToCloseBufferReaderWrapperOk(File file) throws IOException { + try (InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file))) { + BufferedReader reader = new BufferedReader(inputStreamReader); + ignore(reader.readLine()); + } + } + //InputStreamReader tests @@ -86,7 +95,7 @@ public class ReaderLeaks { InputStreamReader reader = null; try { reader = new InputStreamReader(new FileInputStream("testing.txt")); - reader.read(); + ignore(reader.read()); } catch (IOException e) { } finally { if (reader != null) reader.close(); diff --git a/infer/tests/codetoanalyze/java/infer/issues.exp b/infer/tests/codetoanalyze/java/infer/issues.exp index de477e0e0..794451bed 100644 --- a/infer/tests/codetoanalyze/java/infer/issues.exp +++ b/infer/tests/codetoanalyze/java/infer/issues.exp @@ -187,13 +187,11 @@ codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions. codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.stringVarEqualsFalseNPE(), 5, NULL_DEREFERENCE, [start of procedure stringVarEqualsFalseNPE(),start of procedure getString2(),return from a call to String NullPointerExceptions.getString2(),Skipped call: function or method not found,Taking true branch] codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.testSystemGetPropertyReturn(), 2, NULL_DEREFERENCE, [start of procedure testSystemGetPropertyReturn()] codetoanalyze/java/infer/NullPointerExceptions.java, void NullPointerExceptions.testSystemGetPropertyReturn(), 2, RETURN_VALUE_IGNORED, [start of procedure testSystemGetPropertyReturn()] -codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderClosed(), 4, RETURN_VALUE_IGNORED, [start of procedure bufferedReaderClosed(),Skipped call: function or method not found] -codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderNotClosedAfterRead(), 4, RETURN_VALUE_IGNORED, [start of procedure bufferedReaderNotClosedAfterRead(),Skipped call: function or method not found] -codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure bufferedReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] +codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderClosed(), 7, NULL_TEST_AFTER_DEREFERENCE, [start of procedure bufferedReaderClosed(),exception java.io.IOException,Switch condition is true. Entering switch case,Taking false branch] +codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.bufferedReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure bufferedReaderNotClosedAfterRead(),exception java.io.IOException] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.fileReaderClosed(), 4, RETURN_VALUE_IGNORED, [start of procedure fileReaderClosed(),Skipped call: function or method not found] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.fileReaderNotClosedAfterRead(), 4, RETURN_VALUE_IGNORED, [start of procedure fileReaderNotClosedAfterRead(),Skipped call: function or method not found] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.fileReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure fileReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] -codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.inputStreamReaderClosed(), 4, RETURN_VALUE_IGNORED, [start of procedure inputStreamReaderClosed(),Skipped call: function or method not found] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.inputStreamReaderNotClosedAfterRead(), 4, RETURN_VALUE_IGNORED, [start of procedure inputStreamReaderNotClosedAfterRead(),Skipped call: function or method not found] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.inputStreamReaderNotClosedAfterRead(), 6, RESOURCE_LEAK, [start of procedure inputStreamReaderNotClosedAfterRead(),Skipped call: function or method not found,exception java.io.IOException] codetoanalyze/java/infer/ReaderLeaks.java, void ReaderLeaks.pipedReaderClosed(PipedWriter), 5, RETURN_VALUE_IGNORED, [start of procedure pipedReaderClosed(...)]