From: Guy Harris Date: Tue, 16 Oct 2018 22:41:35 +0000 (-0700) Subject: Use the EXTRACT_ macros to extract big-endian integers from a buffer. X-Git-Tag: libpcap-1.10-bp~773 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/a7f69da5b4939ad107f773eedca07838b05b4fab Use the EXTRACT_ macros to extract big-endian integers from a buffer. This: 1) makes it a bit clearer what the code is doing; 2) means that on platforms that support unaligned accesses, the generated code involves fewer instructions; 3) squelches an undefined behavior warning from shifting an int value left 24 bits (in practice, it works, but...). Also, note that we do too much signed integer stuff here. Credit to OSS-Fuzz for finding the undefined behavior issue. --- diff --git a/gencode.c b/gencode.c index 3f528fa2..51adc328 100644 --- a/gencode.c +++ b/gencode.c @@ -50,6 +50,8 @@ #include "pcap-int.h" +#include "extract.h" + #include "ethertype.h" #include "nlpid.h" #include "llc.h" @@ -975,13 +977,22 @@ gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset, { register struct block *b, *tmp; + /* + * XXX - the actual *instructions* do unsigned comparisons on + * most platforms, and the load instructions don't do sign + * extension, so gen_cmp() should really take an unsigned + * value argument. + * + * As the load instructons also don't do sign-extension, we + * fetch the values from the byte array as unsigned. We don't + * want to use the signed versions of the extract calls. + */ b = NULL; while (size >= 4) { register const u_char *p = &v[size - 4]; - bpf_int32 w = ((bpf_int32)p[0] << 24) | - ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3]; - tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w); + tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, + (bpf_int32)EXTRACT_BE_U_4(p)); if (b != NULL) gen_and(b, tmp); b = tmp; @@ -989,9 +1000,9 @@ gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset, } while (size >= 2) { register const u_char *p = &v[size - 2]; - bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1]; - tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w); + tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, + (bpf_int32)EXTRACT_BE_U_2(p)); if (b != NULL) gen_and(b, tmp); b = tmp;