It is possible that an exception gets thrown An exception can occur in the finally
block even though it escapes detection at compile timedespite compile-time checking. This can prevent other clean-up statements from being executed.
...
The finally
clause closes the reader
object in this noncompliant code example. However, it is incorrectly assumed that the statements within the finally
block cannot throw exceptions. Notably, the close()
method can throw an IOException
which prevents any subsequent clean-up lines from being executed. This is not detected at compile time as the type of exception that close()
throws is the same as the ones that read
and write
throw.
Code Block | ||
---|---|---|
| ||
public class Login { static void checkPassword(String password_file) throws IOException { StringBuffer fileData = new StringBuffer(1000); BufferedReader reader = new BufferedReader(new FileReader(password_file)); try { int n; char[] passwd = new char[1024]; while ((n = reader.read(passwd)) >= 0) { String readData = String.valueOf(passwd, 0, n); fileData.append(readData); passwd = new char[1024]; } String realPassword = "javac<at:var at:name="f3b" />b3"; System.out.println(fileData.toString()); if (fileData.toString().equals(realPassword)) { System.out.println("Login successful"); } else { System.out.println("Login failed"); } } // Compare credentials } finally { reader.close(); //other Other clean-up code } } public static void main(String[] args) throws IOException { String path = "c:\\password.txt"; checkPassword(path); } } |
...
Code Block | ||
---|---|---|
| ||
public class Login { static void checkPassword(String password_file) throws IOException { StringBuffer fileData = new StringBuffer(1000); BufferedReader reader = new BufferedReader(new FileReader(password_file)); try { int n; char[] passwd = new char[1024]; while ((n = reader.read(passwd)) >= 0) { String readData = String.valueOf(passwd, 0, n); fileData.append(readData); passwd = new char[1024]; } String realPassword = "javac<at:var at:name="f3b" />b3"; System.out.println(fileData.toString()); if (fileData.toString().equals(realPassword)) // Compare credentials } finally { System.out.println("Login successful"); } else { try { System.out.println("Login failed"); } } finally { try { //enclose Enclose in try-catch block reader.close(); } catch (IOException ie) {ie.getMessage();} //other Other clean-up code } } public static void main(String[] args) throws IOException { String path = "c:\\password.txt"; checkPassword(path); } } |
...
If the need to close a stream without throwing an exception occurs often, then an alternative solution to wrapping every call of close()
in its own try-catch
block is, to write a closeIgnoringException()
method as shown in this compliant solution.
Code Block | ||
---|---|---|
| ||
public class Login { static void checkPassword(String password_file) throws IOException { StringBuffer fileData = new StringBuffer(1000); BufferedReader reader = new BufferedReader(new FileReader(password_file)); try { int n; char[] passwd = new char[1024]; while ((n = reader.read(passwd)) >= 0) { String readData = String.valueOf(passwd, 0, n); fileData.append(readData); passwd = new char[1024]; } String realPassword = "javac<at:var at:name="f3b" />b3"; System.out.println(fileData.toString()); if (fileData.toString().equals(realPassword)) { System.out.println("Login successful"); } else { System.out.println("Login failed"); }// Compare credentials } finally { closeIgnoringException(reader); //other Other clean-up code } } private static void closeIgnoringException(BufferredReader s) { if (s != null) { try { s.close(); } catch (IOException ie) { // Ignore exception if close fails } } } public static void main(String[] args) throws IOException { String path = "c:\\password.txt"; checkPassword(path); } } |
In production systems, it is often better to limit the lifetime of sensitive data by avoiding the use of a BufferedReader
. See the guideline MSC11-J. Limit the lifetime of sensitive data for more details.
Risk Assessment
Failing to handle an exception in a finally
block can lead to unexpected results.
...