The only unsigned primitive integer type in Java is the 16 bit char
data type; all of the other primitive integer types are signed. To interoperate with native languages, such as C or C++, that use unsigned types extensively, read unsigned values into the next larger Java signed primitive integer type. For example, use a long
to hold an unsigned 32-bit integer value obtained from native code.
Noncompliant Code Example
This noncompliant code example uses a generic method for reading in integer data without considering the signedness of the source. It assumes that the values read are always signed and treats the most significant bit as the sign bit. When the data being read is unsigned, this causes misinterpretations of the actual sign and magnitude of the value.
public static int getInteger(DataInputStream is) throws IOException { return is.readInt(); }
Compliant Solution
This compliant solution assumes that the values being read are 32-bit unsigned integers. It reads an unsigned integer value into a long
variable using the readInt()
method. The readInt()
method assumes signed values and returns a signed Java int
; the return value is converted to a long
with sign extension. The code uses an &
operation to mask off the upper 32-bits of the long; this produces a value in the range of a 32-bit unsigned integer, as intended. The mask size should be chosen to match the size of the unsigned integer values being read.
public static long getInteger(DataInputStream is) throws IOException { return is.readInt() & 0xFFFFFFFFL; // mask with 32 one-bits }
As a general rule, you must be aware of the signedness of the data you are reading.
Risk Assessment
Treating unsigned data as though it were signed will produce incorrect values and can lead to lost or misinterpreted data.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
NUM06-J |
low |
unlikely |
medium |
P2 |
L3 |
Automated Detection
Automated detection is infeasible in the general case.
Bibliography
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="270f0c58-437d-49de-93f1-5a230238edad"><ac:plain-text-body><![CDATA[ |
[[API 2006 |
AA. Bibliography#API 06]] |
Class DataInputStream: method |
]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="ca88b506-b137-44ba-9b5a-5c449018052f"><ac:plain-text-body><![CDATA[ |
[[Harold 1997 |
AA. Bibliography#Harold 97]] |
Chapter 2: Primitive Data Types, Cross Platform Issues, Unsigned Integers |
]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="83d77fac-717d-4a07-9b7c-0e018304ec49"><ac:plain-text-body><![CDATA[ |
[[Hitchens 2002 |
AA. Bibliography#Hitchens 02]] |
2.4.5 Accessing Unsigned Data |
]]></ac:plain-text-body></ac:structured-macro> |
NUM04-J. Use shift operators correctly 03. Numeric Types and Operations (NUM) NUM07-J. Avoid using floating-point numbers when precise computation is required