In Java, byte arrays are often used to transmit raw binary data as well as character-encoded data. Attempts to read raw binary data as if it were character-encoded data often fail because some of the bytes fall outside the default or specified encoding scheme and for that reason fail to denote valid characters. For example, converting a cryptographic key containing nonrepresentable bytes to character-encoded data for transmission may result in an error.
Noncompliant Code Example
This noncompliant code example attempts to convert the byte array representing a BigInteger into a String. Because some of the bytes do not denote valid characters, the resulting String representation loses information. Converting the String back to a BigInteger produces a different value.
BigInteger x = new BigInteger("530500452766");
byte [] byteArray = x.toByteArray(); // convert to byte array
String s = new String(byteArray); // s prints as "{,J?z" -
// the fourth character is invalid
// convert s back to a BigInteger
byteArray = s.getBytes(); // convert to bytes
x = new BigInteger(byteArray); // now x = 530500435870
When this program was run on a Linux platform where the default character encoding is US-ASCII, the string s got the value {?J??, because some of the characters were unprintable. When converted back to a BigInteger, x got the value 149830058370101340468658109.
Compliant Solution
This compliant solution first produces a String representation of the BigInteger object and then converts the String object to a byte array. This process is reversed on input. Because the textual representation in the String object was generated by the BigInteger class, it contains valid characters.
BigInteger x = new BigInteger("530500452766");
String s = x.toString(); // valid character data
try {
byte[] byteArray = s.getBytes("UTF8");
// ns prints as "530500452766"
String ns = new String(byteArray, "UTF8");
// construct the original BigInteger
BigInteger x1 = new BigInteger(ns);
} catch (UnsupportedEncodingException ex) {
// handle error
}
Do not try to convert the String object to a byte array to obtain the original BigInteger. Character encoded data may yield a byte array that, when converted to a BigInteger, results in a completely different value.
Exceptions
FIO11-EX0: Binary data that is expected to be a valid string may be read and converted to a string. How to perform this operation securely is explained in rule IDS13-J. Use compatible encodings on both sides of file or network IO. Also see rule IDS10-J. Do not split characters between two data structures.
Risk Assessment
Attempting to read a byte array containing raw binary data as if it were character data may produce erroneous results.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
FIO11-J |
low |
unlikely |
medium |
P2 |
L3 |
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="282bdd72-d0c0-4f66-a765-e928fa6c7e41"><ac:plain-text-body><![CDATA[ |
[[API 2006 |
AA. Bibliography#API 06]] |
[Class String |
http://java.sun.com/javase/6/docs/api/java/lang/String.html] |
]]></ac:plain-text-body></ac:structured-macro> |