CodeQL documentation

Potential input resource leak

ID: java/input-resource-leak
Kind: problem
Severity: warning
Precision: high
Tags:
   - efficiency
   - correctness
   - resources
   - external/cwe/cwe-404
   - external/cwe/cwe-772
Query suites:
   - java-security-and-quality.qls

Click to see the query in the CodeQL repository

A subclass of Reader or InputStream that is opened for reading but not closed may cause a resource leak.

Recommendation

Ensure that the resource is always closed to avoid a resource leak. Note that, because of exceptions, it is safest to close a resource in a finally block. (However, this is unnecessary for subclasses of StringReader and ByteArrayInputStream.)

For Java 7 or later, the recommended way to close resources that implement java.lang.AutoCloseable is to declare them within a try-with-resources statement, so that they are closed implicitly.

Example

In the following example, the resource br is opened but not closed.

public class CloseReader {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("C:\\test.txt"));
		System.out.println(br.readLine());
		// ...
	}
}

In the following example, the resource br is opened in a try block and later closed in a finally block.

public class CloseReaderFix {
	public static void main(String[] args) throws IOException {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader("C:\\test.txt"));
			System.out.println(br.readLine());
		}
		finally {
			if(br != null)
				br.close();  // 'br' is closed
		}
		// ...
	}
}

Note that nested class instance creation expressions of Readers or InputStreams are not safe to use if the constructor of the outer expression may throw an exception. In the following example, the InputStreamReader may throw an exception, in which case the inner FileInputStream is not closed.

public class CloseReaderNested {
	public static void main(String[] args) throws IOException {
		InputStreamReader reader = null;
		try {
			// InputStreamReader may throw an exception, in which case the ...
			reader = new InputStreamReader(
					// ... FileInputStream is not closed by the finally block
					new FileInputStream("C:\\test.txt"), "UTF-8");
			System.out.println(reader.read());
		}
		finally {
			if (reader != null)
				reader.close();
		}
	}
}

In this case, the inner expression needs to be assigned to a local variable and closed separately, as shown below.

public class CloseReaderNestedFix {
	public static void main(String[] args) throws IOException {
		FileInputStream fis = null;
		InputStreamReader reader = null;
		try {
			fis = new FileInputStream("C:\\test.txt");
			reader = new InputStreamReader(fis);
			System.out.println(reader.read());
		}
		finally {
			if (reader != null)
				reader.close();  // 'reader' is closed
			if (fis != null)
				fis.close();  // 'fis' is closed
		}
	}
}

References