Versions Compared

Key

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

Integer variables are frequently intended to represent either a numeric value or a bit collection. Numeric values must be exclusively operated upon on using arithmetic operations, while whereas bit collections should must be exclusively operated upon on using logical bitwise operations. However, static analyzers are frequently unable to determine the intended use of a particular integer variableBitwise operators include the unary operator ~ and the binary operators <<, >>, >>>, &, ^, and |.

Performing bitwise and arithmetic operations on the same data suggests confusion regarding can obscure the purpose of the data stored in the variable and often indicates confusion regarding that purpose. Unfortunately, bitwise operations are frequently performed on arithmetic values as a form of premature optimization. Bitwise operators include the unary operator ~ and the binary operators <<, >>, &, ^, and |. Although such operations are valid and will compile, they can reduce code readability.

Noncompliant Code Example (Left Shift)

Left- and right-shift operators are often employed to multiply or divide a number by a power of 2two. This approach compromises code readability and portability for the sake of often-illusory speed gains. The Java Virtual Machine (JVM will ) usually make makes such optimizations automatically, and, unlike a programmer, the JVM can optimize for the implementation details of the current platform. This noncompliant code example includes both bit bitwise and arithmetic manipulations of the integer x that conceptually contains a numeric value. The result is a prematurely optimized statement that assigns the value 5x + 1 to x, which is what the programmer intended to express.

Code Block
bgColor#ffcccc

int x = 50;
x += (x << 2) + 1;

Noncompliant Code Example (Left Shift)

This noncompliant code example segregates arithmetic and bitwise operators by variables. The x variable participates only in bitwise operations, and y participates only in arithmetic operations.

Code Block
bgColor#ffcccc
int x = 50;
int y = x << 2;
x += y + 1;

This example is noncompliant because the actual data has both bitwise and arithmetic operations performed on it, even though the operations are performed on different variables.

Compliant Solution (Left Shift)

In this compliant solution, the assignment statement is modified to reflect the arithmetic nature of x, resulting in a clearer indication of the programmer's intentions.

Code Block
bgColor#ccccff

int x = 50;
x = 5 * x + 1;

A reviewer could now recognize that the operation should also be checked for overflow. This The need for an overflow check might not have been apparent in the original, noncompliant code example . For more information, (see rule NUM00-J. Detect or prevent integer overflow for more information).

Noncompliant Code Example (Logical Right Shift)

In this noncompliant code example, the programmer wishes to devide divide x by 4. HenceIn a misguided attempt to optimize performance, the programmer attempts to optimize performance by using uses a right-shift operation , rather than a division operation.

Code Block
bgColor#ffcccc

int x = -50;
x >>>= 2;

The >>>= operator is a logical right shift; it fills the leftmost bits with zeroes, regardless of the number's original sign. After execution of this code sequence, x contains a large positive number (specifically, 0x3FFFFFF3). Using logical right shift for division produces an incorrect result when the dividend (x in this example) contains a negative value.

Noncompliant Code Example (Arithmetic Right Shift)

In this noncompliant code example, the programmer attempts to correct the previous example by using an arithmetic right shift (the >>= operator):

Code Block
bgColor#ffcccc

int x = -50;
x >>= 2;

After this code sequence is run, x contains the value -13 rather than the expected -12. Arithmetic right shift truncates its results towards the resulting value toward negative infinity; , whereas integer division truncates towards toward zero.

Compliant Solution (Right Shift)

In this compliant solution, the right shift is correctly replaced by division.

Code Block
bgColor#ccccff

int x = -50;
x /= 4;

Noncompliant Code Example

In this noncompliant code example, a programmer is attempting attempts to fetch four values from a byte array and pack them into the integer variable result. The integer value in this example represents a bit collection, not a numeric value.

Code Block
bgColor#FFCCCC

// b[] is a byte array, initialized to 0xff
byte[] b = new byte[] {-1, -1, -1, -1};
int result = 0;
for (int i = 0; i < 4; i++) {
  result = ((result << 8) + b[i]);
}

...

In the bitwise operation, the value of the byte array element {{b\[i\]}} is promoted to an {{int}} by sign - extension. When a byte array element contains a negative value (for example, {{0xff}}), the sign - extension propagates 1-bits into the upper 24 bits of the {{int}}. This behavior could might be unexpected if the programmer is assuming that {{byte}} is an unsigned type. In this example, adding the promoted byte values to {{result}} fails to result in a packed integer representation of the bytes \ [[FindBugs 2008|AA. Bibliography#FindBugs 08]\].

Noncompliant Code Example

This noncompliant code example masks off the upper 24 bits of the promoted byte array element before performing the addition. The number of bits required to mask the sizes of byte and int are specified by the JLS The Java Language Specification. Although this code calculates the correct result, it violates this rule by combining bitwise and arithmetic operations on the same data.

Code Block
bgColor#ffcccc

byte[] b = new byte[] {-1, -1, -1, -1};
int result = 0;
for (int i = 0; i < 4; i++) {
  result = ((result << 8) + (b[i] & 0xff));
}

Compliant Solution

This compliant solution masks off the upper 24 bits of the promoted byte array element. The result is then combined with result using a logical OR operation.

Code Block
bgColor#ccccff

byte[] b = new byte[] {-1, -1, -1, -1};
int result = 0;
for (int i = 0; i < 4; i++) {

  result = ((result << 8) | (b[i] & 0xff));
}

Exceptions

NUM01-EX0: Bitwise operations may be used to construct constant expressions.

Code Block
bgColor#ccccff

int limit = (1 << 17) - 1; // 2^17 - 1 = 131071

Nevertheless, as a matter of style, we recommend replacing it is preferable to replace such constant expressions with the equivalent hexadecimal constants.

Code Block
bgColor#ccccff

int limit = 0x1FFFF; // 2^17 - 1 = 131071

NUM01-J-EX1: Data that is normally treated arithmetically may be treated with bitwise operations for the purpose of serialization or deserialization. This alternative treatment is often required for reading or writing the data from a file or network socket. Bitwise operations are also permitted when reading or writing the data from a tightly packed data structure of bytes.

Code Block
bgColor#ccccff

int value = /* interestingInteresting value */
Byte[] bytes = new Byte[4];
for (int i = 0; i < bytes.length; i++) {
  bytes[i] = value >> (i*8) & 0xFF;
}
/* bytes[] now has same bit representation as value  */

Risk Assessment

Performing bit bitwise manipulation and arithmetic operations on the same variable obscures the programmer's intentions and reduces readability. ThisConsequently, in turn, makes it is more difficult for a security auditor or maintainer to determine which checks must be performed to eliminate security flaws and ensure data integrity. For instance, overflow checks are critical for numeric types that undergo arithmetic operations , but less critical for numeric types that undergo bitwise operations.

Recommendation

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

NUM01-J

medium

Medium

unlikely

Unlikely

medium

Medium

P4

L3

Automated Detection

ToolVersionCheckerDescription
Parasoft Jtest

Include Page
Parasoft_V
Parasoft_V

CERT.NUM01.BADSHIFT
CERT.NUM01.NCBAV
Avoid incorrect shift operations
Do not perform bitwise and arithmetic operations on the same data

Related Guidelines

Bibliography

<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="736f694c-4691-431e-8fd8-063a39b5e518"><ac:plain-text-body><![CDATA[

[[Steele 1977

AA. Bibliography#Steele 1977]]

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

...


...

Image Added Image Added Image Added assume that the remainder operator always returns a non-negative result for integral operands      03. Numeric Types and Operations (NUM)      NUM02-J. Use shift operators correctly