summaryrefslogtreecommitdiff
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
parentc0d8b3eadaccb07b46da5a5494ef589596bf858d (diff)
downloadlibpcap-db833b997d9d825a4bb0e78804d85552b38a562a.tar.gz
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.
-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: