Java's file-manipulation methods often indicate failure with a return value instead of throwing an exception. Consequently, programs that ignore the return values from file operations often fail to detect that those operations have failed. Java programs must check the return values of methods that perform file I/O. This is a specific instance of EXP00-J. Do not ignore values returned by methods.

Noncompliant Code Example (delete())

This noncompliant code example attempts to delete a specified file but gives no indication of its success. The Java platform requires File.delete() to throw a SecurityException only when the program lacks authorization to delete the file [API 2014]. No other exceptions are thrown, so the deletion can silently fail.

File file = new File(args[0]);
file.delete();

Compliant Solution

This compliant solution checks the return value of delete():

File file = new File("file");
if (!file.delete()) {
  // Deletion failed, handle error
}

Compliant Solution

This compliant solution uses the java.nio.file.Files.delete() method from Java SE 7 to delete the file:

Path file = new File(args[0]).toPath();
try {
  Files.delete(file);
} catch (IOException x) {
  // Deletion failed, handle error
}

The Java SE 7 Documentation [J2SE 2011] defines Files.delete() to throw the following exceptions:

Exception

Reason

NoSuchFileException

File does not exist

DirectoryNotEmptyException

File is a directory and could not otherwise be deleted because the directory is not empty

IOException

An I/O error occurs

SecurityException

In the case of the default provider and a security manager is installed, the SecurityManager.checkDelete(String) method is invoked to check delete access to the file

Because SecurityException is a runtime exception, it need not be declared. Because NoSuchFileException and DirectoryNotExmptyException both inherit from IOException, they will be caught by the compliant solution's catch clause.

Risk Assessment

Failure to check the return values of methods that perform file I/O can result in unexpected behavior.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FIO02-J

Medium

Probable

Medium

P8

L2

Automated Detection

ToolVersionChecker

Description

CodeSonar
8.1p0

JAVA.FUNCS.IRV

Ignored Return Value (Java)

SonarQube
9.9
S899


Related Guidelines

Bibliography

[API 2014]

File.delete()

[J2SE 2011]

Files.delete()

[Seacord 2013]

Chapter 8, "File I/O"



10 Comments

  1. Marked as tech-edit-done although the Automated Detection section has a "TODO."

  2. Comment:
    The last CCE catches only IOException but no other exceptions mentioned in the following table. Is that what is intended? It would be better if some text fill the gap between the code example catching only IOException and the following list of exceptions.

    1. The code is good as is, but requires more explanation as you note. I added a paragraph after the table justifying the code.

  3. Hi!

    I don't understand why 'remediation cost' is high. Proper solution seems relatively simple.

    Best regards,

    Isabelle

    1. I think the cost was high because the rule was vague on how to detect file-related errors (since many errors don't cause an exception to be thrown). If we can assume that Java indicates errors in some way, such as function return value, setting of an 'error' flag in a stream, etc, then we can automatically detect all file-related errors. (although such a task may be huge depending on the different behavior of functions).

      Fixing code to handle a file-related error still must be done manually, because it is up to the developer to decide upon a course of action. (There are solutions that could be done automatically, such as always throwing a NewTypeOfFileException, but it's up to the developer to implement such a solution.)

      So I'd argue that the remediation cost should be Medium, not High. I've changed the rule accordingly.

  4. Shouldn't the pre-NIO solution be NON-Compliant for newer Java versions?

    It seems safer to push for the newer APIs which are less-error prone (i.e. cannot forget to check the return value).


    1. Not by our definition of non-compliance.

      If you are writing new Java code then we would recommend using the static Files.delete() method rather than the File.delete() method because of its error handling.

      But the code that checks the return value of File.delete() and handles the error is also correct, and not less secure than code using Files.delete(). So it is compliant (even if less preferred to Files.delete()).

  5. If we're pushing programmers to write safer code the compliant versions should NOT just print to the console.

    As a minimum they should write to a log file + have the comment "// Handle error or throw exception".

    Current first compliant examples might lead some programmers to think outputing the error is enough.

    1. True, our common mechanism is the "//handle error" comment, which we consistently use throughout the standard. I've modified the compliant examples to do the same.