When a web servlet receives a request from a client, it must produce some suitable response. Java's HttpServlet
provides the HttpServletResponse
object to capture a suitable response. This response can be built using an output stream provided by getOutputStream()
or a writer provided by getWriter()
.
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 recommitting to the stream
- Flushing the stream's or writer's buffer
- Invoking either
getWriter()
orgetOutputStream()
- Redirecting an
HttpServletResponse
to another server - Modifying the stream's character encoding, content type, or buffer size
This rule is a stub.
Noncompliant Code Example
This noncompliant code example shows an example where ...
Code Block | ||
---|---|---|
| ||
|
Compliant Solution
In this compliant solution, ...
illustrates a servlet that indicates if an internal error occurs by using the HttpServletResponse.sendError()
method to indicate an internal server error.
Code Block | ||||
---|---|---|---|---|
| ||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
ServletOutputStream out = response.getOutputStream();
try {
out.println("<html>");
// ... Write some response text
out.flush(); // Commits the stream
// ... More 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
.
Noncompliant Code Example
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 | ||||
---|---|---|---|---|
| ||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
ServletOutputStream out = response.getOutputStream();
try {
out.println("<html>");
// ... Write some response text
out.flush(); // Commits the stream
// ... More work
} catch (IOException x) {
out.println(x.getMessage());
out.flush();
}
}
|
If an IOException
occurs after flushing the stream, the stream will be reflushed in the catch
clause.
Compliant Solution
The sendError()
method should be used only before an output stream or writer has been created 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 | ||||
---|---|---|---|---|
| ||||
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
try {
// Do work that doesn't require the output stream
} catch (IOException x) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
ServletOutputStream out = response.getOutputStream();
try {
out.println("<html>");
// ... All work
} catch (IOException ex) {
out.println(ex.getMessage());
} finally {
out.flush();
}
}
| ||||
Code Block | ||||
| ||||
|
Risk Assessment
If a servlet's output stream is reset after it has been committed then .., an IllegalStateException
usually results, which can cause the servlet's response to be truncated.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
FIO15-J | Low | Probable |
Medium |
P4 | L3 |
Automated Detection
...
Fortify | 6.10.0120 | Multiple_Stream_Commits | Implemented |
Tool | Version | Checker | Description |
---|
Bibliography
...