Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: took out PRECISION defs, xrefed INT35-C

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
#include <stddef.h>
#include <inttypes.h>

extern size_t popcount(uintmax_t);
#define PRECISION(x) popcount(x)
 
void func(unsigned int ui_a, unsigned int ui_b) {
  unsigned int uresult = 0;
  if (ui_b >= PRECISION(UINT_MAX)) {
    /* Handle error condition */
  } else {
    uresult = ui_a << ui_b;
  }

  /* ... */
}

The PRECISION()macro provides the correct precision for any integer type (see INT35-C. Use correct integer precisions).

Modulo  Modulo behavior resulting from left-shifting an unsigned integer type is permitted by exception INT30-EX3 to INT30-C. Ensure that unsigned integer operations do not wrap.

...

Code Block
bgColor#FFcccc
langc
#include <limits.h>
#include <stddef.h>
#include <inttypes.h>
 
extern size_t popcount(uintmax_t);
#define PRECISION(x) popcount(x)

void func(signed long si_a, signed long si_b) {
  signed long result;
  if (si_a > (LONG_MAX >> si_b)) {
    /* Handle error */
  } else {
    result = si_a << si_b;
  }
  /* ... */
}

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
#include <stddef.h>
#include <inttypes.h>
 
extern size_t popcount(uintmax_t);
#define PRECISION(x) popcount(x)

void func(signed long si_a, signed long si_b) {
  signed long result;
  if ((si_a < 0) || (si_b < 0) ||
      (si_b >= PRECISION(ULONG_MAX)) ||
      (si_a > (LONG_MAX >> si_b))) {
    /* Handle error */
  } else {
    result = si_a << si_b;
  }
  /* ... */
}

 

The PRECISION()macro provides the correct precision for any integer type (see INT35-C. Use correct integer precisions)

 

Noncompliant Code Example (Right Shift)

...

Code Block
bgColor#FFcccc
langc
void func(unsigned int ui_a, unsigned int ui_b) {
  unsigned int uresult = ui_a >> ui_b;
  /* ... */
}

Making When working with signed operands, making assumptions about whether a right shift is implemented as an arithmetic (signed) shift or a logical (unsigned) shift can also lead to vulnerabilities. See INT13-C. Use bitwise operators only on unsigned operands.

...

Code Block
bgColor#ccccff
langc
#include <limits.h>
#include <stddef.h>
#include <inttypes.h>

extern size_t popcount(uintmax_t);
#define PRECISION(x) popcount(x)
 
void func(unsigned int ui_a, unsigned int ui_b) {
  unsigned int uresult = 0;
  if (ui_b >= PRECISION(UINT_MAX)) {
    /* Handle error condition */
  } else {
    uresult = ui_a >> ui_b;
  }
  /* ... */
}

 

The PRECISION()macro provides the correct precision for any integer type (see INT35-C. Use correct integer precisions)

Implementation Details

GCC has no options to handle shifts by negative amounts or by amounts outside the width of the type predictably or to trap on them; they are always treated as undefined. Processors may reduce the shift amount modulo the width of the type. For example, 32-bit shifts are implemented using the following instructions on x86-32:

Code Block
sa[rl]l   %cl, %eax

...