...
short
tobyte
orchar
char
tobyte
orshort
int
tobyte
,short
, orchar
long
tobyte
,short
,char
, orint
float
tobyte
,short
,char
,int
, orlong
double
tobyte
,short
,char
,int
,long
, orfloat
Integer Narrowing
The table below presents the rules for narrowing primitive conversions of integer types. In the table, for an integer type T
, n
represents the number of bits used to represent the type T
(precision).
...
When integers are cast to narrow data types, the magnitude of the numeric value and the corresponding sign can be affected. Consequently, data can be lost or misinterpreted.
Floating-point Conversion to Integer
Floating-point conversion to an integral type T
is a two step procedure. The first step results in a long
value if T
is long
; otherwise, it results in an int
value. The second step narrows the int
value to T
if T
is not int
using the integer narrowing conversions outlined above. See JLS, Section 5.1.3, "Narrowing Primitive Conversions" for more information.
...
Note that conversions from float
to double
or double
to float
can also lose information about the overall magnitude of the converted value. See guideline FLP04-J. Use the strictfp modifier for floating point calculation consistency for additional information.
Noncompliant Code Example (Integer Narrowing)
Consider the conversion from an integer
to a byte
. The higher order bytes of the integer
are truncated and the lowest order byte
is transferred to the target byte
. However, because bytes store signed values, any value outside the range of -128 to +127 results in truncation and data loss. This noncompliant code example shows that an input of 128 yields a result value of -128. Similarly, 129 becomes -127 and so on. This is a consequence of interpreting the bit pattern of low order 8 bits of the input as a signed byte. For example, the binary representation of 129 is 10000001, which, as a byte
, is interpreted as -127.
Code Block | ||
---|---|---|
| ||
class CastAway { public static void main(String[] args) { int i = 128; workWith(i); } public static void workWith(int i) byte b = (byte) i; // b has value -128 // work with b } } |
Compliant Solution (Integer Narrowing)
This compliant solution validates the permissible range before converting the integer to the narrower target type.
Code Block | ||
---|---|---|
| ||
class CastAway { public static void workWith(int i) //check if i is within byte range if ((i < Byte.MIN_VALUE) || (i > Byte.MAX_VALUE)) { throw new ArithmeticException("Value is out of range"); } byte b = (byte) i; // work with b } } |
Noncompliant Code Example (Floating-point Conversion to Integer)
The narrowing primitive conversions in this noncompliant code example suffer from loss in the magnitude of the numeric value, as well as a loss of precision. In accordance with the language semantics quoted above, the minimum and maximum float
values are converted to minimum and maximum int
values (0x80000000 and 0x7fffffff), and the resulting short
values are the lower 16 bits of these values (0x0000 and 0xffff, respectively). The resulting final values (0 and -1) could be unexpected.
Code Block | ||
---|---|---|
| ||
float i = Float.MIN_VALUE; float j = Float.MAX_VALUE; short b = (short) i; short c = (short) j; |
Compliant Solution (Floating-point Conversion to Integer)
Perform range checks on both i
and j
variables before proceeding with the conversions.
Code Block | ||
---|---|---|
| ||
float i = Float.MIN_VALUE; float j = Float.MAX_VALUE; if ((i < Short.MIN_VALUE) || (i > Short.MAX_VALUE) || (j < Short.MIN_VALUE) || (j > Short.MAX_VALUE)) { throw new ArithmeticException ("Value is out of range"); } short b = (short) i; short c = (short) j; //other operations |
Risk Assessment
Casting a numeric value to a narrower type can result in information loss related to the sign and magnitude of the numeric value. Consequently, data can be misrepresented or interpreted incorrectly.
Guideline | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP13-J | low | unlikely | medium | P2 | L3 |
Automated Detection
Automated detection of narrowing conversions on integral types is straightforward. Determining whether such conversions correctly reflect the intent of the programmer is infeasible in the general case. Heuristic warnings could be useful.
Related Guidelines
C Secure Coding Standard: INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
C Secure Coding Standard: FLP34-C. Ensure that floating point conversions are within range of the new type
C++ Secure Coding Standard: INT31-CPP. Ensure that integer conversions do not result in lost or misinterpreted data
C++ Secure Coding Standard: FLP34-CPP. Ensure that floating point conversions are within range of the new type
MITRE CWE: CWE-681 "Incorrect Conversion between Numeric Types"
MITRE CWE: CWE-197 "Numeric Truncation Error"
Bibliography
[Harold 1999]
[JLS 2005] Section 5.1.3, "Narrowing Primitive Conversions"
...