]> The Tcpdump Group git mirrors - libpcap/commitdiff
Don't shift by more than 31 bit positions.
authorGuy Harris <[email protected]>
Tue, 16 Oct 2018 22:57:06 +0000 (15:57 -0700)
committerGuy Harris <[email protected]>
Tue, 16 Oct 2018 22:57:06 +0000 (15:57 -0700)
That's undefined in C, and there are currently-used processors on which
a shift of 32 bits, for example, shifts all the bits out and processors
on which it does no shift (i.e., the shift count is, or isn't, taken
modulo 32).

We'll treat it as shifting all the bits out.

Note that the BPF interpreter doesn't do this test, so the BPF machine's
behavior mirrors the behavior of the processor on which it's running.
We suggest you not write filter expressions, or BPF programs, that rely
on any particular behavior from shifts of more than 31 bits.

Credit to OSS-Fuzz for finding this issue.

optimize.c

index fa8e0ac1feb2bd1008496eb22b57a80c9767a63b..0d2fcca28d566bc8e707bf133ca60442b1a20b79 100644 (file)
@@ -745,11 +745,39 @@ fold_op(compiler_state_t *cstate, opt_state_t *opt_state,
                break;
 
        case BPF_LSH:
-               a <<= b;
+               /*
+                * A left shift of more than the width of the type
+                * is undefined in C; we'll just treat it as shifting
+                * all the bits out.
+                *
+                * XXX - the BPF interpreter doesn't check for this,
+                * so its behavior is dependent on the behavior of
+                * the processor on which it's running.  There are
+                * processors on which it shifts all the bits out
+                * and processors on which it does no shift.
+                */
+               if (b < 32)
+                       a <<= b;
+               else
+                       a = 0;
                break;
 
        case BPF_RSH:
-               a >>= b;
+               /*
+                * A right shift of more than the width of the type
+                * is undefined in C; we'll just treat it as shifting
+                * all the bits out.
+                *
+                * XXX - the BPF interpreter doesn't check for this,
+                * so its behavior is dependent on the behavior of
+                * the processor on which it's running.  There are
+                * processors on which it shifts all the bits out
+                * and processors on which it does no shift.
+                */
+               if (b < 32)
+                       a >>= b;
+               else
+                       a = 0;
                break;
 
        default: