aboutsummaryrefslogtreecommitdiff
path: root/bpf_filter.c
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2018-10-16 23:23:10 -0700
committerGuy Harris <guy@alum.mit.edu>2018-10-16 23:23:10 -0700
commitdb833b997d9d825a4bb0e78804d85552b38a562a (patch)
tree8f059a7c3e95f7772d4b6c39175dff73a48b1db3 /bpf_filter.c
parentc0d8b3eadaccb07b46da5a5494ef589596bf858d (diff)
Fix the semantics of BPF_LSH and BPF_RSH for shifts >= 32 bits.
Some processors treat shifts greater than the width of the shifted operand as setting the destination to 0, some others treat it as a shift modulo the width. C says it's undefined, and most if not all implementations make it work the way the target processor works. We treat it as setting the destination to 0, regardless of how the processor on which we're running works. Credit to OSS-Fuzz for finding this issue.
Diffstat (limited to 'bpf_filter.c')
-rw-r--r--bpf_filter.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/bpf_filter.c b/bpf_filter.c
index e5c286b5..b19b25d1 100644
--- a/bpf_filter.c
+++ b/bpf_filter.c
@@ -302,11 +302,17 @@ pcap_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
continue;
case BPF_ALU|BPF_LSH|BPF_X:
- A <<= X;
+ if (X < 32)
+ A <<= X;
+ else
+ A = 0;
continue;
case BPF_ALU|BPF_RSH|BPF_X:
- A >>= X;
+ if (X < 32)
+ A >>= X;
+ else
+ A = 0;
continue;
case BPF_ALU|BPF_ADD|BPF_K: