You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 33 Next »

An exception can occur in the finally block despite compile-time checking. This can prevent other clean-up statements from being executed.

Noncompliant Code Example

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.

public class Login {
  static void checkPassword(String password_file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(password_file));
    // Compare credentials 
     
    } finally {
      reader.close();
      // Other clean-up code 
    }
}

  public static void main(String[] args) throws IOException {
    String path = "password";
    checkPassword(path);
  }
}

Compliant Solution (1)

This compliant solution correctly places the close() statement in a try-catch block. As a result, an IOException can be handled without letting it propagate any further.

public class Login {
  static void checkPassword(String password_file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(password_file));

    try {
      // Compare credentials
    } finally {
        try {    
          // Enclose in try-catch block
          reader.close();
        } catch (IOException ie) {
          // Forward to handler
        }
        // Other clean-up code
    }
  }

  public static void main(String[] args) throws IOException {
    String path = "password";
    checkPassword(path);
  }
}

Compliant Solution (2)

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.

public class Login {
  static void checkPassword(String password_file) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader(password_file));

    try {
      // Compare credentials
    } finally {
      closeIgnoringException(reader);
      // 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 = "password";
    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 MSC10-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.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXC05- J

low

unlikely

medium

P2

L3

Automated Detection

TODO

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

[[Bloch 05]] Puzzle 41: Field and Stream
[[Harold 99]]
[[Chess 07]] 8.3 Preventing Resource Leaks (Java)


EXC04-J. Do not exit abruptly from a finally block      13. Exceptional Behavior (EXC)      EXC06-J. Do not allow exceptions to transmit sensitive information

  • No labels