Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

There are 22 possible narrowing primitive conversions in Java. According to the Java Language SpecificationJLS, §5.1.3, "Narrowing Primitive Conversions" [JLS 2005]:

  • short to byte or char
  • char to byte or short
  • int to byte, short, or char
  • long to byte, short, char, or int
  • float to byte, short, char, int, or long
  • double to byte, short, char, int, long, or float

...

Integer type ranges are defined by the JLS, §4.2.1, "Integral Types and Values", [JLS 2005], and are also described in rule NUM00-J. Detect or prevent integer overflow.

The following 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 resulting type T (precision).

From

To

Description

Possible Resulting Errors

signed integer

integral type T

Keeps only n lower-order bits

Lost or misinterpreted data

char

integral type T

Keeps only n lower-order bits

Magnitude error; negative number even though char is 16-bit unsigned

When integers are cast to narrow narrower 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 an integral type T is a two-step procedure:

1. When converting a floating-point value to an int or long and the value is a NaN, a zero value is produced. Otherwise, if the value is not infinity, it is rounded towards zero to an integer value V:

  • If T is long, and V can be represented as a long, the long value V is produced.
  • If V can be represented as an int, then the int value V is produced.

Otherwise,

  • The value is negative infinity or a value too negative to be represented, and Integer.MIN_VALUE or Long.MIN_VALUE is produced.
  • The value is positive infinity or a value too positive to be represented, Integer.MAX_VALUE or Long.MAX_VALUE is produced.

...

See the JLS, §5.1.3, "Narrowing Primitive Conversions,"[JLS 2005] for more information.

Other Conversions

Narrower primitive types can be cast to wider types without affecting the magnitude of numeric values. See the JLS, §5.1.2, Widening Primitive Conversion" [JLS 2005], for more information. Conversion from int or long to float, or from long to double can lead to loss of precision (loss of least significant bits). No runtime exception occurs despite this loss.

Note that conversions from float to double or from double to float can also lose information about the overall magnitude of the converted value. See rule NUM06-J . Use the strictfp modifier for floating-point calculation consistency across platforms for additional information.

...

Code Block
bgColor#ccccff
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
  } 
}

...

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.

...

Code Block
bgColor#ccccff
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

Noncompliant Code Example (double to float Conversion)

The narrowing primitive conversions in this noncompliant code example suffer from a loss in the magnitude of the numeric value , as well as a loss of precision. Because Double.MAX_VALUE is larger than Float.MAX_VALUE, c receives the value infinity and because Double.MIN_VALUE is smaller than Float.MIN_VALUE, d b receives the value 0.

Code Block
bgColor#FFcccc
double i = Double.MIN_VALUE;
double j = Double.MAX_VALUE;
float b = (float) i;
float c = (float) j;

Compliant Solution (double to float Conversion)

Perform This compliant solution performs range checks on both i and j variables before proceeding with the conversions. Because both values are out of the valid range for a short float, this code will always throw an ArithmeticException.

Code Block
bgColor#ccccff
double i = Double.MIN_VALUE;
double j = Double.MAX_VALUE;
if ((i < Float.MIN_VALUE) || (i > Float.MAX_VALUE) ||
    (j < Float.MIN_VALUE) || (j > Float.MAX_VALUE)) {
  throw new ArithmeticException ("Value is out of range");    
}

float b = (float) i;
float c = (float) j;
// other operations

Exceptions

NUM12-EX0: Java's narrowing conversions are both well - defined and portable. The effects of narrowing on integral types can be easily reproduced in code; however, the effects of narrowing on floating-point types , and between floating-point types and integral types cannot be easily represented. Knowledgeable programmers may intentionally apply narrowing conversions involving floating-point types in contexts where their output is both expected and reasonable. Consequently, narrowing conversions are permitted when the code contains comments that document both the use of narrowing conversions and that the potential for anticipated truncation has been anticipated. A suitable comment might read:
"// Deliberate narrowing cast of i; possible truncation OK"

This exception does not permit narrowing conversions without range-checking among integral types. The following code example demonstrates how to perform explicit narrowing from a long to an int where range-checking is not required.

...

The CERT C Secure Coding Standard

INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data

 

FLP34-C. Ensure that floating point conversions are within range of the new type

The CERT C++ Secure Coding Standard

INT31-CPP. Ensure that integer conversions do not result in lost or misinterpreted data

 

FLP34-CPP. Ensure that floating point conversions are within range of the new type

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="a92330ee0d0e46a1-88101558-43264b62-8ee6b7d7-850550e94c455841fc401140"><ac:plain-text-body><![CDATA[

[ISO/IEC TR 24772:2010

http://www.aitcnet.org/isai/]

" Numeric Conversion Errors [FLC] "

]]></ac:plain-text-body></ac:structured-macro>

MITRE CWE

CWE-681, ". Incorrect Conversion between Numeric Types" conversion between numeric types

 

CWE-197, "Numeric Truncation Error" . Numeric truncation error

Bibliography

...

      03. Numeric Types and Operations (NUM)