]> The Tcpdump Group git mirrors - libpcap/commitdiff
Catch shifts > 31 bits generated by the optimizer.
authorGuy Harris <[email protected]>
Mon, 22 Oct 2018 08:58:04 +0000 (01:58 -0700)
committerGuy Harris <[email protected]>
Mon, 22 Oct 2018 08:58:04 +0000 (01:58 -0700)
We already caught them in the code generator - but only if they were
between 31 and 2^31-1, but we weren't catching them when shifts by the X
register got optimized into shifts by a constant, so we need to:

1) catch it in the optimizer;

2) fix the check in the code generator.

(In the longer run, we need to clear up signed vs. unsigned stuff in the
code generator and optimizer.)

Credit to OSS-Fuzz for finding the optimizer issue (which was using a
shift constant that was "negative", thus pointing out the code generator
issue).

gencode.c
optimize.c

index 15cb93473deb568d15f0aad75bbf10d2d6e9b7dd..95a3ef9579a27e409202a320c1420aa1a6b7fe2f 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -7466,7 +7466,13 @@ gen_arth(compiler_state_t *cstate, int code, struct arth *a0,
                if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
                        bpf_error(cstate, "modulus by zero");
        } else if (code == BPF_LSH || code == BPF_RSH) {
-               if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k > 31)
+               /*
+                * XXX - we need to make up our minds as to what integers
+                * are signed and what integers are unsigned in BPF programs
+                * and in our IR.
+                */
+               if (a1->s->s.code == (BPF_LD|BPF_IMM) &&
+                   (a1->s->s.k < 0 || a1->s->s.k > 31))
                        bpf_error(cstate, "shift by more than 31 bits");
        }
        s0 = xfer_to_x(cstate, a1);
index 4c2a84c1864c590bbf493c4cef1beea8a3334090..6c6deb00d22cbc2caab8c0cbfc2796ced0f85ec7 100644 (file)
@@ -1201,6 +1201,16 @@ opt_stmt(compiler_state_t *cstate, opt_state_t *opt_state,
                        else {
                                s->code = BPF_ALU|BPF_K|op;
                                s->k = opt_state->vmap[val[X_ATOM]].const_val;
+                               /*
+                                * XXX - we need to make up our minds
+                                * as to what integers are signed and
+                                * what integers are unsigned in BPF
+                                * programs and in our IR.
+                                */
+                               if ((op == BPF_LSH || op == BPF_RSH) &&
+                                   (s->k < 0 || s->k > 31))
+                                       opt_error(cstate, opt_state,
+                                           "shift by more than 31 bits");
                                opt_state->done = 0;
                                val[A_ATOM] =
                                        F(opt_state, s->code, val[A_ATOM], K(s->k));