Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

A response is said to be committed if its status code and HTML headers have been sent . [J2EE API 2013]. After a response is committed, further data may be added to the response, but certain behaviors become impossible. For example, it is impossible to change the character encoding, because the encoding is included in the HTML header. Some of these illegal operations will yield a IllegalStateException, while others will have no effect. These illegal behaviors include the following:

  • Resetting the stream or re-committing recommitting to the stream
  • Flushing the stream's or writer's buffer
  • Invoking either getWriter() or getOutputStream()
  • Redirecting an HttpServletResponse to another server
  • Modifying the stream's character encoding, content type, or buffer size

Noncompliant Code Example

...

Code Block
bgColor#ffcccc
languagejava
public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {

  PrintWriter out = response.getWriter();
  try {
    out.println("<html>");

    // ... writeWrite some response text

    out.flush();  // commitsCommits the stream

    // ... moreMore work

  } catch (IOException x) {
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  }
}

If an IOException occurs after flushing the stream, the stream will be committed when the catch clause executes. Consequently, the sendError() operation will throw an IllegalStateException.

...

This noncompliant code example illustrates a servlet that indicates if an internal error occurs by printing an error message to the output stream and flushing it.:

Code Block
bgColor#ffcccc
languagejava
public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {

  PrintWriter out = response.getWriter();
  try {
    out.println("<html>");

    // ... writeWrite some response text

    out.flush();  // commitsCommits the stream

    // ... moreMore work

  } catch (IOException x) {
    out.println(x.getMessage());
    out.flush();
  }
}

If an IOException occurs after flushing the stream, the stream will be re-flushed reflushed in the catch clause.

Compliant Solution

The sendError() method should only be used only before an output stream or writer has been created , as because it overwrites any output. Once the output stream or writer has been created, errors should be output alongside valid HTML. This compliant solution uses both strategies, ensuring that the stream is flushed only once, in the finally clause.

Code Block
bgColor#ccccff
languagejava
public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException {

  try {
    // doDo work that doesn't require the output writer
  } catch (IOException x) {
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
  }

  PrintWriter out = response.getWriter();
  try {
    out.println("<html>");

    // ... allAll work

  } catch (IOException ex) {
    out.println(ex.getMessage());
  } finally {
    out.flush();
  }
}

...

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

FIO15-J

Low

Probable

Medium

P4

L3

Automated Detection

Fortify6.10.0120

Multiple_Stream_Commits

Implemented
Tool
Version
Checker
Description

...