Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

In Java, data is stored in big-endian format (also called network order). That is, all data is represented sequentially starting from the most significant bit (MSB) to the least significant. Prior JDK versions prior to JDK 1.4 , required definition of custom methods had to be defined to be compatible that manage reversing byte order to maintain compatibility with little-endian systems that use the reverse byte order. Handling . 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. Failure to handle data byte ordering issues can may cause misinterpretations and unexpected program behavior.

Noncompliant Code Example

The class java.io.DataInputStream defines read methods (readByte, readShort, readInt, readLong, readFloat and readDouble) and the corresponding write methods . All these methods work with defined by class java.io.DataInputStream operate only on big-endian data only. The use Use of these methods can be unsafe while interfacing interoperating with traditional languages such as C or C++ , that do not provide is unsafe, because such languages lack any guarantees on about endianness. This noncompliant code example shows such a discrepancy.

Code Block
bgColor#FFcccc
DataInputStream dis = new DataInputStream(
  new FileInputStream("data"));  // Little-endian data might be read as big-endian
int serialNumber = dis.readInt();

Compliant Solution (Use ByteBuffer)

Wiki Markup
This compliant solution uses methods provided by class {{ByteBuffer}} (see \[[API 2006|AA. Bibliography#API 06]\] [ByteBuffer|http://download.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html]) to correctly extract an {{int}} from the original input value. It wraps the input byte
array containing the integer bytes read-in into a ByteBuffer and sets the byte order to little-endian. The result is stored in the integer serialNumber.
 array with a {{ByteBuffer}}, sets the byte order to little-endian, and extracts the {{int}}. The result is stored in the integer {{serialNumber}}. 

Code Block
bgColor#ccccff
	 
DataInputStream dis = new DataInputStream(
  new FileInputStream("data"));

byte[] buffer= new byte[4];
int bytesRead = dis.read(buffer);  // Bytes are read into buffer
int serialNumber = ByteBuffer.wrap(buffer).order(ByteOrder.LITTLE_ENDIAN).getInt();

Class ByteBuffer provides analogous get and put methods for the other numeric types.

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 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() method reads data four bytes into a byte buffer and then pieces together the integer in the right order. The writeLittleEndianInteger() method obtains bytes by repeatedly casting the integer so that the most least significant byte is extracted on successive right shifts. Long values can be handled by defining a byte buffer of size eight.

Code Block
bgColor#ccccff
	 
// read method
public static int readLittleEndianInteger(InputStream ips) throws IOException {
  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;
}

// write method
public static void writeLittleEndianInteger(int i, OutputStream ops) throws IOException {
  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

...

(Use reverseBytes())

When programming for In JDK 1.5+, use the reverseBytes() method defined in the classes Character, Short, Integer and Long can be used 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
bgColor#ccccff
	 
public static int reverse(int i){
  return Integer.reverseBytes(i);
}

Risk Assessment

Reading and writing data without considering endianness may lead to serious misinterpretations about magnitude and sign, alike.

Guideline

Severity

Likelihood

Remediation Cost

Priority

Level

INT07-J

low

unlikely

low

P3

L3

Automated Detection

TODOAutomated detection is infeasible in the general case.

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this guideline on the CERT website.

Bibliography

Wiki Markup
\[[API 2006|AA. Bibliography#API 06]\] Class [ByteBuffer|http://download.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html]: Methods {{wrap}} and {{order}}. Class [Integer|http://download.oracle.com/javase/6/docs/api/java/lang/Integer.html]: method {{reverseBytes}}
\[[Harold 1997|AA. Bibliography#Harold 97]\] Chapter 2: "Primitive Data Types, Cross Platform issues"
\[[MITRE 2009|AA. Bibliography#MITRE 09]\] [CWE ID 198|http://cwe.mitre.org/data/definitions/198.html] "Use of Incorrect Byte Ordering"

...