]> The Tcpdump Group git mirrors - libpcap/commitdiff
Cast the LHS if bit shifts to bpf_u_int32 to avoid undefined behavior.
authorGuy Harris <[email protected]>
Thu, 12 Jul 2018 20:59:18 +0000 (13:59 -0700)
committerGuy Harris <[email protected]>
Thu, 12 Jul 2018 20:59:33 +0000 (13:59 -0700)
To quote C99 6.5.7 "Bitwise shift operators":

The integer promotions are performed on each of the operands.
The type of the result is that of the promoted left operand.

The result of E1 << E2 is E1 left-shifted E2 bit positions;
vacated bits are filled with zeros.  If E1 has an unsigned type,
the value of the result is E1*2^E2, reduced modulo one more than
the maximum value representable in the result type.  If E1 has a
signed type and nonnegative value, and E1*2^E2 is representable
in the result type, then that is the resulting value; otherwise,
the behavior is undefined.

This means that, in 1 << x, an int value, i.e. a signed value, is being
shifted, and 2^31 isn't representable as a 32-bit int.

The bits we're setting/clearing/testing are from a bpf_u_int32, so cast
1 to bpf_u_int32 before shifting.

optimize.c

index 7c6424b0159260a37b84f949645a61d87f073039..947a39933f669aa91ecbb30c1b73b0436067375f 100644 (file)
@@ -252,19 +252,19 @@ typedef struct {
  * True if a is in uset {p}
  */
 #define SET_MEMBER(p, a) \
-((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD)))
+((p)[(unsigned)(a) / BITS_PER_WORD] & ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD)))
 
 /*
  * Add 'a' to uset p.
  */
 #define SET_INSERT(p, a) \
-(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD))
+(p)[(unsigned)(a) / BITS_PER_WORD] |= ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
 
 /*
  * Delete 'a' from uset p.
  */
 #define SET_DELETE(p, a) \
-(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD))
+(p)[(unsigned)(a) / BITS_PER_WORD] &= ~((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
 
 /*
  * a := a intersect b
@@ -1480,7 +1480,7 @@ opt_j(opt_state_t *opt_state, struct edge *ep)
 
                while (x != 0) {
                        k = lowest_set_bit(x);
-                       x &=~ (1 << k);
+                       x &=~ ((bpf_u_int32)1 << k);
                        k += i * BITS_PER_WORD;
 
                        target = fold_edge(ep->succ, opt_state->edges[k]);