Input methods that return a byte or char may also return or -1 if The abstract InputStream.read() and Reader.read() 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 is reached.
In the case of a function that returns a char, these methods return a value of type int so that the end of stream may be indicated by a -1.
In the case of a function that returns a byte, these methods return a value of type int which allows the caller to distinguish between -1 and the byte value 0xFF promoted and sign extended to an int.
In particular, this guideline applies to any InputStream subclass that provide an implementation of this classes' abstract read() method.
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 the resulting int to a byte or char before 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 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 rule is a specific instance of NUM12This guideline is a specific instances of NUM15-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. When read() returns 0x000000FF, the comparison will test against 0xFFFFFFFF, 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