Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: significantly revised, renamed, and moved

Input methods that return a byte or char may also return or -1 if 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.

Noncompliant Code Example (byte)

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 in an attempt to detect the end of the stream.

Code Block
bgColor#FFcccc

FileInputStream in;
// initialize stream 
byte data;
while ((data = (byte) in.read()) != -1) { 
  // ... 
}

If the read() method in this noncompliant code example returns the byte value 0xFF, it will be indistinguishable from the -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.

Compliant Solution (byte)

Use and value of type int to capture the return value of the byte input method. If the value returned by read() is not -1, it can be safely cast to type byte.

Code Block
bgColor#ccccff

FileInputStream in;
int inbuff;
byte data;
while ((inbuff = in.read()) != -1) { 
  data = (byte) inbuff;
  // ...  
}

Noncompliant Code Example (char)

Wiki Markup
The {{char}} type is the only unsigned primitive type in Java; its representable range of values contains only non-negative values. Consequently, attempting to store and retrieve a value from a variable of any of the other integral primitive types will produce unexpected results when that value is negative. Similarly, comparing a value of type {{char}} with any negative number will never yield {{true}}. However, because the method {{read()}} returns -1 to indicate the End of File ({{EOF}}) condition, it is tempting to compare the character returned by {{read()}} with -1. This common error \[[Pugh 2008|AA. Bibliography#Pugh 08]\] is illustrated below.

...

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 in an attempt to detect EOFthe end of stream. This conversion leaves the value of c as 0xffff (Character.MAX_VALUE) instead of -1. As a result, the test for EOF the end of stream never evaluates to true.

Code Block
bgColor#FFcccc
char c;
while ((c = (char) in.read()) != -1) { 
  // ... 
}

Compliant Solution

...

(char)

Use and Always use a signed type of sufficient size to store signed data. To be compliant, use a value of type int to check for EOF while reading datacapture the return value of the character input method. When the value of type int returned by read() is not -1, it can be safely cast to type char.

Code Block
bgColor#ccccff
int cinbuff;
char data;
while ((cinbuff = in.read()) != -1) { 
  chdata = (char) c; inbuff;
  // ...  
}

Risk Assessment

Storing signed data in a variable of the unsigned type char can lead to misinterpreted data and possible memory leaks. Furthermore, comparing a value of type char with -1 never evaluates to true. This error can result in a denial-of-service, for example, when code fails to detect EOF.

Historically, using a narrow type to capture the return value of a byte input function has resulted in significant vulnerabilities, including command injection attacks. (See the CA-1996-22 advisory.) As a result, the severity of this error is high.

Rule Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

NUM03 FIO14-J

low high

unlikely probable

low medium

P3 P12

L3 L1

Automated Detection

FindBugs version 1.3.9 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

C++ Secure Coding Standard: 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"

...