Java does not support the use of unsigned types, except for the 16 bit char
datatype. Sometimes, it is necessary to 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. The standard practice to deal with unsigned input is to read values into Java's larger signed
primitives, any unsigned values must be read and stored into a Java integer type that can fully represent the possible range of the unsigned data. For example, a signed the Java long
type can be used to hold an unsigned integer
represent all possible unsigned 32-bit integer values obtained from native code.
Noncompliant Code Example
This noncompliant code example incorrectly uses a generic method for reading in integer data irrespective without considering the signedness of the signednesssource. It assumes that the value data read is always signed and treats the most significant bit (MSB) as the sign bit causing misinterpretations about . When the data read is unsigned, the actual sign and magnitude of the integervalues may be misinterpreted.
Code Block | ||
---|---|---|
| ||
public static int getInteger(DataInputStream is) throws IOException {
return is.readInt();
}
|
Compliant Solution
This compliant solution assumes requires that the unsigned
integer has 32 bitsvalues read are 32-bit unsigned integers. It reads in an unsigned integer value into a long
variable using the readInt()
method. If the read integer is unsigned
, the most significant bit may be turned on. Consequently, all the higher order bits of the resulting long
are set because of sign extension, and these must be masked off as demonstrated. For other integer sizes, the mask size should vary depending on The readInt()
method assumes signed values and returns a signed 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
, producing 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.
Code Block | ||
---|---|---|
| ||
public static long getInteger(DataInputStream is) throws IOException { return is.readInt() & 0xFFFFFFFFL; // Mask with 32 one-bits } |
As a general principle, you should always be aware of the signedness of the data you are reading.
Risk Assessment
Treating an unsigned type data as signed can result in misinterpretations though it were signed produces incorrect values and can lead to lost or misinterpreted data.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
NUM03-J |
Low |
Unlikely |
Medium | P2 | L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[API 06|AA. Java References#API 06]\] Class DataInputStream: method {{readInt}}
\[[Harold 97|AA. Java References#Harold 97]\] Chapter 2: Primitive Data Types, Cross Platform Issues, Unsigned Integers
\[[Hitchens 02|AA. Java References#Hitchens 02]\] 2.4.5 Accessing Unsigned Data |
Automated detection is infeasible in the general case.
Bibliography
[API 2006] | Class |
Chapter 2, "Primitive Data Types, Cross-Platform Issues, Unsigned Integers" | |
Section 2.4.5, "Accessing Unsigned Data" | |
[Seacord 2015] |
...
INT07-J. Provide methods to read and write Little-Endian data 06. Integers (INT) INT02-J. Do not assume a positive remainder when using the remainder operator