In Java, data is stored in Bigbig-Endian endian format (also called network order), that . That is, all data is represented sequentially starting from the most significant bit (MSB) to the least significant. Prior JDK versions prior to jdk JDK 1.4 , required definition of custom methods had to be defined to be compatible with Little-Endian systems that use the reverse byte order. Handling byte order related that manage reversing byte order to maintain compatibility with little-endian systems. Correct handling of byte order–related issues is critical when exchanging data is to be exchanged in a networked environment that consists of machines varying in Endiannessincludes both big-endian and little-endian machines or when working with other languages using Java Native Interface (JNI). Failure to handle such cases byte-ordering issues can cause misinterpretations and unexpected program behavior.
Noncompliant Code Example
The java.io.DataInputStream
class defines read methods (readByte()
, readShort()
, readInt()
, readLong()
, readFloat()
, and readDouble()
) and the corresponding write methods . All these methods work with Big-Endian data only. The usage of these methods can be unsafe while interfacing with traditional languages such as C/C++, that do not provide any guarantees on Endianness. This noncompliant defined by class java.io.DataInputStream
and class java.io.DataOutputStream
operate only on big-endian data. Use of these methods while interoperating with traditional languages, such as C and C++, is insecure because such languages lack any guarantees about endianness. This noncompliant code example shows such a discrepancy. :
Code Block | ||
---|---|---|
| ||
try { DataInputStream dis = null; try { dis = new DataInputStream( new FileInputStream("data.txt")); // Little-Endianendian data might be read as Bigbig-Endianendian int serialNumber = dis.readInt(); } catch (IOException x) { // Handle error } finally { if (dis != null) { try { dis.close(); } catch (IOException e) { // Handle error } } } } |
Compliant Solution (
...
ByteBuffer
)
This compliant solution uses methods provided by class ByteBuffer
[API 2014] to correctly extract an int
from the original input value. It wraps the input byte array containing the integer bytes read-in into with a ByteBuffer
and , sets the byte order to Little-Endianlittle-endian, and extracts the int
. The result is stored in the integer serialNumber
. Class ByteBuffer
provides analogous get and put methods for other numeric types.
Code Block | ||
---|---|---|
| ||
try { DataInputStream dis = null; try { dis = new DataInputStream( new FileInputStream("data.txt")); byte[] buffer = new byte[4]; int bytesRead = dis.read(buffer); // Bytes will beare read into buffer if (bytesRead != 4) { throw new IOException("Unexpected End of Stream"); } int serialNumber = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).getInt(); } finally { if (dis != null) { try { dis.close(); } catch (IOException x) { // Handle error } } } } catch (IOException x) { // Handle error } |
Compliant Solution (
...
Define Special-Purpose Methods)
An alternative compliant solution is to define read and write methods that support the necessary byte-swapping while reading from or writing to the file. In this example, the readLittleEndianInteger()
method reads four bytes Assuming that an integer value is to be read from the file, read and write methods can be defined for handling Little-Endian data. The readLittleEndianInteger
reads data into a byte buffer and then pieces together the integer in the right correct order. Long
values can be handled by defining a byte buffer of size 8
. The writeLittleEndianInteger()
method obtains bytes by repeatedly casting the integer so that the MSB least significant byte is extracted on successive right shifts. Long
values can be handled by defining a byte buffer of size 8.
Code Block | ||
---|---|---|
| ||
// readRead method public static int readLittleEndianInteger(InputStream ips) throws IOException { int result; byte[] buffer = new byte[4]; int check = ips.read(buffer); if (check != 4) { throw new IOException("Unexpected End of Stream"); } int result = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0]; return result; } // writeWrite method public static void writeLittleEndianInteger(int i, OutputStream ops) throws IOException { int result; byte[] buffer = new byte[4]; buffer[0] = (byte) i; buffer[1] = (byte) (i >> 8); buffer[2] = (byte) (i >> 16); buffer[3] = (byte) (i >> 24); ops.write(buffer); } |
Compliant Solution (reverseBytes(
...
)
)
In jdk When programming for JDK 1.5 +and later, use the Integer.reverseBytes()
method can be used defined in the classes Character
, Short
, Integer
, and Long
to reverse the order of the bytes constituting the integerintegral value's bytes. Note that there is no such method for float
and double
valuesclasses Float
and Double
lack such a method.
Code Block | ||
---|---|---|
| ||
public static int reverse(int i) { return Integer.reverseBytes(i); } |
Risk Assessment
Reading and writing data without considering Endianness may endianness can lead to serious misinterpretations about of both the magnitude and sign , alikeof the data.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
FIO12-J |
Low |
Unlikely |
Low | P3 | L3 |
Automated Detection
...
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Automated detection is infeasible in the general case.
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Parasoft Jtest |
| CERT.FIO12.PMRWLED | Provide methods to read and write little-endian data |
Related Guidelines
Bibliography
[API 2014] | Class |
"On Holy Wars and a Plea for Peace" | |
Chapter 2, "Primitive Data Types, Cross-Platform Issues" |
...
Wiki Markup |
---|
\[[API 06|AA. Java References#API 06]\] Class ByteBuffer: Methods {{wrap}} and {{order}}. Class Integer: method {{reverseBytes}}
\[[Harold 97|AA. Java References#Harold 97]\] Chapter 2: Primitive Data Types, Cross Platform issues |
04. Integers (INT) 04. Integers (INT) INT01-J. Provide mechanisms to handle unsigned data when required