From fa36ecd5918e76bf6524cb6fb13535ccadd9919a Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 25 Nov 2019 11:51:09 -0500 Subject: [PATCH] [IO-640] NPE in org.apache.commons.io.IOUtils.contentEquals(InputStream, InputStream) when only one input is null. --- src/changes/changes.xml | 3 +++ .../java/org/apache/commons/io/IOUtils.java | 19 ++++++++++++------- .../apache/commons/io/IOUtilsTestCase.java | 12 ++++++++++++ 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 245f7486ac9..fc34f479972 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -165,6 +165,9 @@ The type attribute can be add,update,fix,remove. Add and reuse org.apache.commons.io.IOUtils.closeQuitely(Closeable, Consumer<IOException>). Add and reuse org.apache.commons.io.IOUtils.close(Closeable, IOConsumer<IOException>). + + NPE in org.apache.commons.io.IOUtils.contentEquals(InputStream, InputStream) when only one input is null. + diff --git a/src/main/java/org/apache/commons/io/IOUtils.java b/src/main/java/org/apache/commons/io/IOUtils.java index 993828ae1a8..ba92c2e9447 100644 --- a/src/main/java/org/apache/commons/io/IOUtils.java +++ b/src/main/java/org/apache/commons/io/IOUtils.java @@ -712,6 +712,9 @@ public static boolean contentEquals(final InputStream input1, final InputStream if (input1 == input2) { return true; } + if (input1 == null ^ input2 == null) { + return false; + } final BufferedInputStream bufferedInput1 = buffer(input1); final BufferedInputStream bufferedInput2 = buffer(input2); int ch = bufferedInput1.read(); @@ -740,25 +743,26 @@ public static boolean contentEquals(final InputStream input1, final InputStream * @throws IOException if an I/O error occurs * @since 1.1 */ - public static boolean contentEquals(Reader input1, Reader input2) + @SuppressWarnings("resource") + public static boolean contentEquals(final Reader input1, final Reader input2) throws IOException { if (input1 == input2) { return true; } - input1 = toBufferedReader(input1); - input2 = toBufferedReader(input2); + BufferedReader bufferedInput1 = toBufferedReader(input1); + BufferedReader bufferedInput2 = toBufferedReader(input2); - int ch = input1.read(); + int ch = bufferedInput1.read(); while (EOF != ch) { - final int ch2 = input2.read(); + final int ch2 = bufferedInput2.read(); if (ch != ch2) { return false; } - ch = input1.read(); + ch = bufferedInput1.read(); } - final int ch2 = input2.read(); + final int ch2 = bufferedInput2.read(); return ch2 == EOF; } @@ -776,6 +780,7 @@ public static boolean contentEquals(Reader input1, Reader input2) * @throws IOException if an I/O error occurs * @since 2.2 */ + @SuppressWarnings("resource") public static boolean contentEqualsIgnoreEOL(final Reader input1, final Reader input2) throws IOException { if (input1 == input2) { diff --git a/src/test/java/org/apache/commons/io/IOUtilsTestCase.java b/src/test/java/org/apache/commons/io/IOUtilsTestCase.java index cc4c3b19b7f..4ea628e76c9 100644 --- a/src/test/java/org/apache/commons/io/IOUtilsTestCase.java +++ b/src/test/java/org/apache/commons/io/IOUtilsTestCase.java @@ -229,6 +229,18 @@ public synchronized void close() throws IOException { } @Test public void testContentEquals_InputStream_InputStream() throws Exception { + { + final ByteArrayInputStream input1 = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8)); + assertTrue(IOUtils.contentEquals((InputStream) null, null)); + } + { + final ByteArrayInputStream input1 = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8)); + assertFalse(IOUtils.contentEquals(input1, null)); + } + { + final ByteArrayInputStream input1 = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8)); + assertFalse(IOUtils.contentEquals(null, input1)); + } { final ByteArrayInputStream input1 = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8)); assertTrue(IOUtils.contentEquals(input1, input1));