The abstract {{InputStream Wiki Markup InputStream.read() and Reader.read()}} method is defined as follows, according to \[[API 2006|AA. Bibliography#API 06]\]:
...
methods are used to read a byte or character, respectively, from a stream. The InputStream.read() method reads a single byte from an input source and returns its value as an int in the range 0 to 255 (0x00-0xff). The Reader.read() method reads a single character and returns its value as an int in the range 0 to
...
65,535 (0x0000-0xffff). Both methods return the 32-bit value -1 (0xffffffff) to indicate that the end of the stream has been reached
...
and no data is available. The larger int size is used by both methods to differentiate between the end-of-stream indicator and the maximum byte (0xff) or character (0xffff) value. The end-of-stream indicator is an example of an in-band error indicator. In-band error indicators are problematic to work with, and the creation of new in-band-error indicators is discouraged.
Prematurely converting This method is often used to read a byte from an input stream. It is sometimes also used to read a character from the input stream when the character is known to require only 8 bits. Unfortunately many programmers eagerly convert the resulting int to a byte or char before checking the value for -1. It is vital to check that read() did not return -1 testing for the value −1 makes it impossible to distinguish between characters read and the end of stream indicator. Programs must check for the end of stream before narrowing the return value to a byte or char.
This guideline applies to any InputStream subclass that provide rule applies to any method that returns the value −1 to indicate the end of a stream. It includes any InputStream or Reader subclass that provides an implementation of the read() method. This guideline rule is a specific instance of NUM15 NUM12-J. Ensure conversions of numeric types to narrower types do not result in lost or misinterpreted data.
Noncompliant Code Example (byte)
FileInputStream is a subclass of InputStream. It will return −1 only when the end of the input stream has been reached. This noncompliant code example casts the value returned by the read() method directly to a value of type byte, and then compares this value with -1 −1 in an attempt to detect the end of the stream.
| Code Block | ||
|---|---|---|
| ||
FileInputStream in; // initializeInitialize stream byte data; while ((data = (byte) in.read()) != -1) { // ... } |
If the read() method encounters a 0xFF byte in this noncompliant code example returns the byte value 0xFF, it will be the file, this value becomes indistinguishable from the -1 −1 value used to indicate the end of stream, because the byte value is promoted and sign-extended to an int before being compared with -1−1. Consequently, the loop will halt prematurely if a 0xFF byte is read.
Compliant Solution (byte)
Use and value a variable of type int to capture the return value of the byte input method. If When the value returned by read() is not -1−1, it can be safely cast to type byte. If When read() returns 0XFF 0x000000FF, the comparison will test 0x000000FF against 0xFFFFFFFF and fail, which evaluates to false.
| Code Block | ||
|---|---|---|
| ||
FileInputStream in; // Initialize stream int inbuff; byte data; while ((inbuff = in.read()) != -1) { data = (byte) inbuff; // ... } |
Noncompliant Code Example (char)
FileReader is a subclass of InputStreamReader, which is in turn a subclass of Reader. It also returns −1 only when the end of the stream is reached. This noncompliant code example casts the value of type int returned by the read() method directly to a value of type char, which is then compared with -1 −1 in an attempt to detect the end of stream. This conversion leaves the value of c data as 0xffff 0xFFFF (e.g., Character.MAX_VALUE) instead of -1. As a result−1. Consequently, the test for the end of stream file never evaluates to true.
| Code Block | ||
|---|---|---|
| ||
FileReader in; // Initialize stream char cdata; while ((cdata = (char) in.read()) != -1) { // ... } |
Compliant Solution (char)
Use and value a variable of type int to capture the return value of the character input method. When the value of returned by read() is not -1−1, it can be safely cast to type char.
| Code Block | ||
|---|---|---|
| ||
FileReader in;
// Initialize stream
int inbuff;
char data;
while ((inbuff = in.read()) != -1) {
data = (char) inbuff;
// ...
}
|
Risk Assessment
Historically, using a narrow type to capture the return value of a byte input function method has resulted in significant vulnerabilities, including command injection attacks. (See the ; see CA-1996-22 advisory. ) As a resultConsequently, the severity of this error is high.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|
FIO08-J | High |
Probable |
Yes |
Yes |
P18 | L1 |
Automated Detection
FindBugs version 1.3.9 Some static analysis tools can detect violations of this guideline with the INT: Bad comparison of nonnegative value with negative constant detector.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Related Guidelines
C Secure Coding Standard: FIO34-C. Use int to capture the return value of character IO functions
...
rule.
| Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Parasoft Jtest |
| CERT.FIO08.CRRV | Check the return value of methods which read or skip input | ||||||
| SpotBugs |
| EOS_BAD_END_OF_STREAM_CHECK | Implemented (since 4.4.0) |
Related Guidelines
FIO34-C. Distinguish between characters read from a file and EOF or WEOF | |
FIO34-CPP. Use int to capture the return value of character IO functions |
Bibliography
| Wiki Markup |
|---|
\[[API 2006|AA. Bibliography#API 06]\] Class {{InputStream}}
\[[JLS 2005|AA. Bibliography#JLS 05]\] [Section 4.2|http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html#4.2] "Primitive Types and Values"
\[[Pugh 2008|AA. Bibliography#Pugh 08]\] "Waiting for the end" |
FIO35-CPP. Use feof() and ferror() to detect end-of-file and file errors when sizeof(int) == sizeof(char) |
Bibliography
...
NUM17-J. Beware of precision loss when converting primitive integers to floating-point 03. Integers (INT) NUM04-J. Use shift operators correctly