...
Code Block | ||||
---|---|---|---|---|
| ||||
#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
macro provides the correct precision for any integer type (see INT35-C. Use correct integer precisions).PRECISION()
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 | ||||
---|---|---|---|---|
| ||||
#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 | ||||
---|---|---|---|---|
| ||||
#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
macro provides the correct precision for any integer type (see INT35-C. Use correct integer precisions). PRECISION()
Noncompliant Code Example (Right Shift)
...
Code Block | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
#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
macro provides the correct precision for any integer type (see INT35-C. Use correct integer precisions). PRECISION()
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 |
...