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 non-representable 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"); // convert x to a String byte[] byteArray = x.toByteArray(); String s = new String(byteArray); // convert s back to a BigInteger byteArray = s.getBytes(); x = new BigInteger(byteArray);
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"); String ns = new String(byteArray, "UTF8"); // ns prints as "530500452766" BigInteger x1 = new BigInteger(ns); // construct the original BigInteger } 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 which, 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 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="4afca68d-22d1-49af-af3a-5f4d2be9e5bc"><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> |